48     void addTransactionResult( QDomDocument &responseDoc, QDomElement &resultsElem,
    49                                const QString &locator, 
const QString &message );
    60     response.
setHeader( 
"Content-Type", 
"text/xml; charset=utf-8" );
    61     response.
write( doc.toByteArray() );
    75     if ( doc.setContent( parameters.value( QStringLiteral( 
"REQUEST_BODY" ) ), 
true, &errorMsg ) )
    77       QDomElement docElem = doc.documentElement();
    86     if ( actionCount == 0 )
    97     QDomElement respElem = resp.createElement( QStringLiteral( 
"TransactionResponse" ) );
    98     respElem.setAttribute( QStringLiteral( 
"xmlns" ), 
WFS_NAMESPACE );
    99     respElem.setAttribute( QStringLiteral( 
"xmlns:xsi" ), QStringLiteral( 
"http://www.w3.org/2001/XMLSchema-instance" ) );
   100     respElem.setAttribute( QStringLiteral( 
"xsi:schemaLocation" ), 
WFS_NAMESPACE + 
" http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" );
   101     respElem.setAttribute( QStringLiteral( 
"xmlns:ogc" ), 
OGC_NAMESPACE );
   102     respElem.setAttribute( QStringLiteral( 
"version" ), QStringLiteral( 
"1.1.0" ) );
   103     resp.appendChild( respElem );
   105     int totalInserted = 0;
   106     int totalUpdated = 0;
   107     int totalDeleted = 0;
   111     QDomElement trsElem = doc.createElement( QStringLiteral( 
"TransactionResults" ) );
   114     QDomElement irsElem = doc.createElement( QStringLiteral( 
"InsertResults" ) );
   115     QList<transactionInsert>::iterator tiIt = aRequest.
inserts.begin();
   116     for ( ; tiIt != aRequest.
inserts.end(); ++tiIt )
   122         QString locator = action.
handle;
   123         if ( locator.isEmpty() )
   125           locator = QStringLiteral( 
"Insert:%1" ).arg( action.
typeName );
   127         addTransactionResult( resp, trsElem, locator, action.
errorMsg );
   134           QString fidStr = *fidIt;
   135           QDomElement irElem = doc.createElement( QStringLiteral( 
"Feature" ) );
   136           if ( !action.
handle.isEmpty() )
   138             irElem.setAttribute( QStringLiteral( 
"handle" ), action.
handle );
   140           QDomElement fiElem = doc.createElement( QStringLiteral( 
"ogc:FeatureId" ) );
   141           fiElem.setAttribute( QStringLiteral( 
"fid" ), fidStr );
   142           irElem.appendChild( fiElem );
   143           irsElem.appendChild( irElem );
   149     QList<transactionUpdate>::iterator tuIt = aRequest.
updates.begin();
   150     for ( ; tuIt != aRequest.
updates.end(); ++tuIt )
   156         QString locator = action.
handle;
   157         if ( locator.isEmpty() )
   159           locator = QStringLiteral( 
"Update:%1" ).arg( action.
typeName );
   161         addTransactionResult( resp, trsElem, locator, action.
errorMsg );
   166     QList<transactionDelete>::iterator tdIt = aRequest.
deletes.begin();
   167     for ( ; tdIt != aRequest.
deletes.end(); ++tdIt )
   173         QString locator = action.
handle;
   174         if ( locator.isEmpty() )
   176           locator = QStringLiteral( 
"Delete:%1" ).arg( action.
typeName );
   178         addTransactionResult( resp, trsElem, locator, action.
errorMsg );
   184     QDomElement summaryElem = doc.createElement( QStringLiteral( 
"TransactionSummary" ) );
   185     if ( aRequest.
inserts.size() > 0 )
   187       QDomElement totalInsertedElem = doc.createElement( QStringLiteral( 
"TotalInserted" ) );
   188       totalInsertedElem.appendChild( doc.createTextNode( QString::number( totalInserted ) ) );
   189       summaryElem.appendChild( totalInsertedElem );
   191     if ( aRequest.
updates.size() > 0 )
   193       QDomElement totalUpdatedElem = doc.createElement( QStringLiteral( 
"TotalUpdated" ) );
   194       totalUpdatedElem.appendChild( doc.createTextNode( QString::number( totalUpdated ) ) );
   195       summaryElem.appendChild( totalUpdatedElem );
   197     if ( aRequest.
deletes.size() > 0 )
   199       QDomElement totalDeletedElem = doc.createElement( QStringLiteral( 
"TotalDeleted" ) );
   200       totalDeletedElem.appendChild( doc.createTextNode( QString::number( totalDeleted ) ) );
   201       summaryElem.appendChild( totalDeletedElem );
   203     respElem.appendChild( summaryElem );
   206     if ( errorCount > 0 && trsElem.hasChildNodes() )
   208       respElem.appendChild( trsElem );
   212     if ( aRequest.
inserts.size() > 0 && irsElem.hasChildNodes() )
   214       respElem.appendChild( irsElem );
   221 #ifndef HAVE_SERVER_PYTHON_PLUGINS   225     QStringList typeNameList;
   227     QList<transactionInsert>::iterator tiIt = aRequest.
inserts.begin();
   228     for ( ; tiIt != aRequest.
inserts.end(); ++tiIt )
   230       QString name = ( *tiIt ).typeName;
   231       if ( !typeNameList.contains( name ) )
   232         typeNameList << name;
   234     QList<transactionUpdate>::iterator tuIt = aRequest.
updates.begin();
   235     for ( ; tuIt != aRequest.
updates.end(); ++tuIt )
   237       QString name = ( *tuIt ).typeName;
   238       if ( !typeNameList.contains( name ) )
   239         typeNameList << name;
   241     QList<transactionDelete>::iterator tdIt = aRequest.
deletes.begin();
   242     for ( ; tdIt != aRequest.
deletes.end(); ++tdIt )
   244       QString name = ( *tdIt ).typeName;
   245       if ( !typeNameList.contains( name ) )
   246         typeNameList << name;
   249 #ifdef HAVE_SERVER_PYTHON_PLUGINS   263     QMap<QString, QgsVectorLayer *> mapLayerMap;
   264     for ( 
int i = 0; i < wfsLayerIds.size(); ++i )
   278       if ( !typeNameList.contains( name ) )
   305       if ( !wfstUpdateLayerIds.contains( vlayer->
id() )
   306            && !wfstDeleteLayerIds.contains( vlayer->
id() )
   307            && !wfstInsertLayerIds.contains( vlayer->
id() ) )
   311 #ifdef HAVE_SERVER_PYTHON_PLUGINS   324       mapLayerMap[name] = vlayer;
   328     tuIt = aRequest.
updates.begin();
   329     for ( ; tuIt != aRequest.
updates.end(); ++tuIt )
   334       if ( !mapLayerMap.keys().contains( typeName ) )
   337         action.
errorMsg = QStringLiteral( 
"TypeName '%1' unknown" ).arg( typeName );
   345       if ( !wfstUpdateLayerIds.contains( vlayer->
id() ) )
   348         action.
errorMsg = QStringLiteral( 
"No permissions to do WFS updates on layer '%1'" ).arg( typeName );
   351 #ifdef HAVE_SERVER_PYTHON_PLUGINS   355         action.
errorMsg = QStringLiteral( 
"No permissions to do WFS updates on layer '%1'" ).arg( typeName );
   367         action.
errorMsg = QStringLiteral( 
"No capabilities to do WFS updates on layer '%1'" ).arg( typeName );
   390 #ifdef HAVE_SERVER_PYTHON_PLUGINS   399       int totalUpdated = 0;
   401       QMap<QString, QString> propertyMap = action.
propertyMap;
   405       const QMap<QString, int> fieldMap = provider->
fieldNameMap();
   406       QMap<QString, int>::const_iterator fieldMapIt;
   408       bool conversionSuccess;
   412 #ifdef HAVE_SERVER_PYTHON_PLUGINS   413         if ( accessControl && !accessControl->
allowToEdit( vlayer, feature ) )
   416           action.
errorMsg = QStringLiteral( 
"Feature modify permission denied on layer '%1'" ).arg( typeName );
   421         QMap< QString, QString >::const_iterator it = propertyMap.constBegin();
   422         for ( ; it != propertyMap.constEnd(); ++it )
   424           fieldName = it.key();
   425           fieldMapIt = fieldMap.find( fieldName );
   426           if ( fieldMapIt == fieldMap.constEnd() )
   430           QgsField field = fields.
at( fieldMapIt.value() );
   431           QVariant value = it.value();
   432           if ( value.isNull() )
   437               action.
errorMsg = QStringLiteral( 
"NOT NULL constraint error on layer '%1', field '%2'" ).arg( typeName, field.
name() );
   444             if ( field.
type() == QVariant::Type::Int )
   446               value = it.value().toInt( &conversionSuccess );
   447               if ( !conversionSuccess )
   450                 action.
errorMsg = QStringLiteral( 
"Property conversion error on layer '%1'" ).arg( typeName );
   455             else if ( field.
type() == QVariant::Type::Double )
   457               value = it.value().toDouble( &conversionSuccess );
   458               if ( !conversionSuccess )
   461                 action.
errorMsg = QStringLiteral( 
"Property conversion error on layer '%1'" ).arg( typeName );
   466             else if ( field.
type() == QVariant::Type::LongLong )
   468               value = it.value().toLongLong( &conversionSuccess );
   469               if ( !conversionSuccess )
   472                 action.
errorMsg = QStringLiteral( 
"Property conversion error on layer '%1'" ).arg( typeName );
   485         if ( !geometryElem.isNull() )
   491             action.
errorMsg = QStringLiteral( 
"Geometry from GML error on layer '%1'" ).arg( typeName );
   498             action.
errorMsg = QStringLiteral( 
"Error in change geometry on layer '%1'" ).arg( typeName );
   509 #ifdef HAVE_SERVER_PYTHON_PLUGINS   516           if ( accessControl && !accessControl->
allowToEdit( vlayer, feature ) )
   519             action.
errorMsg = QStringLiteral( 
"Feature modify permission denied on layer '%1'" ).arg( typeName );
   535         action.
errorMsg = QStringLiteral( 
"Error committing updates: %1" ).arg( vlayer->
commitErrors().join( QStringLiteral( 
"; " ) ) );
   541       action.
error = 
false;
   546     tdIt = aRequest.
deletes.begin();
   547     for ( ; tdIt != aRequest.
deletes.end(); ++tdIt )
   552       if ( !mapLayerMap.keys().contains( typeName ) )
   555         action.
errorMsg = QStringLiteral( 
"TypeName '%1' unknown" ).arg( typeName );
   563       if ( !wfstDeleteLayerIds.contains( vlayer->
id() ) )
   566         action.
errorMsg = QStringLiteral( 
"No permissions to do WFS deletes on layer '%1'" ).arg( typeName );
   569 #ifdef HAVE_SERVER_PYTHON_PLUGINS   573         action.
errorMsg = QStringLiteral( 
"No permissions to do WFS deletes on layer '%1'" ).arg( typeName );
   585         action.
errorMsg = QStringLiteral( 
"No capabilities to do WFS deletes on layer '%1'" ).arg( typeName );
   605         action.
errorMsg = QStringLiteral( 
"No feature ids to do WFS deletes on layer '%1'" ).arg( typeName );
   612 #ifdef HAVE_SERVER_PYTHON_PLUGINS   626 #ifdef HAVE_SERVER_PYTHON_PLUGINS   627         if ( accessControl && !accessControl->
allowToEdit( vlayer, feature ) )
   630           action.
errorMsg = QStringLiteral( 
"Feature modify permission denied" );
   635         fids << feature.
id();
   645         action.
errorMsg = QStringLiteral( 
"Delete features failed on layer '%1'" ).arg( typeName );
   654         action.
errorMsg = QStringLiteral( 
"Error committing deletes: %1" ).arg( vlayer->
commitErrors().join( QStringLiteral( 
"; " ) ) );
   660       action.
error = 
false;
   664     tiIt = aRequest.
inserts.begin();
   665     for ( ; tiIt != aRequest.
inserts.end(); ++tiIt )
   670       if ( !mapLayerMap.keys().contains( typeName ) )
   673         action.
errorMsg = QStringLiteral( 
"TypeName '%1' unknown" ).arg( typeName );
   681       if ( !wfstInsertLayerIds.contains( vlayer->
id() ) )
   684         action.
errorMsg = QStringLiteral( 
"No permissions to do WFS inserts on layer '%1'" ).arg( typeName );
   687 #ifdef HAVE_SERVER_PYTHON_PLUGINS   691         action.
errorMsg = QStringLiteral( 
"No permissions to do WFS inserts on layer '%1'" ).arg( typeName );
   703         action.
errorMsg = QStringLiteral( 
"No capabilities to do WFS inserts on layer '%1'" ).arg( typeName );
   719         action.
errorMsg = QStringLiteral( 
"%1 '%2'" ).arg( ex.
message() ).arg( typeName );
   723       if ( featureList.empty() )
   726         action.
errorMsg = QStringLiteral( 
"No features to insert in layer '%1'" ).arg( typeName );
   730 #ifdef HAVE_SERVER_PYTHON_PLUGINS   734         QgsFeatureList::iterator featureIt = featureList.begin();
   735         while ( featureIt != featureList.end() )
   737           if ( !accessControl->
allowToEdit( vlayer, *featureIt ) )
   740             action.
errorMsg = QStringLiteral( 
"Feature modify permission denied on layer '%1'" ).arg( typeName );
   757         action.
errorMsg = QStringLiteral( 
"Insert features failed on layer '%1'" ).arg( typeName );
   758         if ( provider ->hasErrors() )
   770         action.
errorMsg = QStringLiteral( 
"Error committing inserts: %1" ).arg( vlayer->
commitErrors().join( QStringLiteral( 
"; " ) ) );
   775       action.
error = 
false;
   779       for ( 
const QgsFeature &feat : qgis::as_const( featureList ) )
   786     filterRestorer.reset();
   796     const QMap<QString, int> fieldMap = provider->
fieldNameMap();
   797     QMap<QString, int>::const_iterator fieldMapIt;
   799     for ( 
int i = 0; i < featureNodeList.count(); i++ )
   803       QDomElement featureElem = featureNodeList.at( i ).toElement();
   804       QDomNode currentAttributeChild = featureElem.firstChild();
   805       bool conversionSuccess = 
true;
   807       while ( !currentAttributeChild.isNull() )
   809         QDomElement currentAttributeElement = currentAttributeChild.toElement();
   810         QString attrName = currentAttributeElement.localName();
   812         if ( attrName != QLatin1String( 
"boundedBy" ) )
   814           if ( attrName != QLatin1String( 
"geometry" ) ) 
   816             fieldMapIt = fieldMap.find( attrName );
   817             if ( fieldMapIt == fieldMap.constEnd() )
   822             QgsField field = fields.
at( fieldMapIt.value() );
   823             QString attrValue = currentAttributeElement.text();
   824             int attrType = field.
type();
   826             QgsMessageLog::logMessage( QStringLiteral( 
"attr: name=%1 idx=%2 value=%3" ).arg( attrName ).arg( fieldMapIt.value() ).arg( attrValue ) );
   828             if ( attrType == QVariant::Int )
   829               feat.
setAttribute( fieldMapIt.value(), attrValue.toInt( &conversionSuccess ) );
   830             else if ( attrType == QVariant::Double )
   831               feat.
setAttribute( fieldMapIt.value(), attrValue.toDouble( &conversionSuccess ) );
   835             if ( !conversionSuccess )
   850         currentAttributeChild = currentAttributeChild.nextSibling();
   860     if ( !parameters.contains( QStringLiteral( 
"OPERATION" ) ) )
   864     if ( parameters.value( QStringLiteral( 
"OPERATION" ) ).toUpper() != QStringLiteral( 
"DELETE" ) )
   870     if ( ( parameters.contains( QStringLiteral( 
"FEATUREID" ) )
   871            && ( parameters.contains( QStringLiteral( 
"FILTER" ) ) || parameters.contains( QStringLiteral( 
"BBOX" ) ) ) )
   872          || ( parameters.contains( QStringLiteral( 
"FILTER" ) )
   873               && ( parameters.contains( QStringLiteral( 
"FEATUREID" ) ) || parameters.contains( QStringLiteral( 
"BBOX" ) ) ) )
   874          || ( parameters.contains( QStringLiteral( 
"BBOX" ) )
   875               && ( parameters.contains( QStringLiteral( 
"FEATUREID" ) ) || parameters.contains( QStringLiteral( 
"FILTER" ) ) ) )
   883     QStringList typeNameList;
   885     if ( parameters.contains( QStringLiteral( 
"FEATUREID" ) ) )
   887       QStringList fidList = parameters.value( QStringLiteral( 
"FEATUREID" ) ).split( 
',' );
   889       QMap<QString, QStringList> fidsMap;
   891       QStringList::const_iterator fidIt = fidList.constBegin();
   892       for ( ; fidIt != fidList.constEnd(); ++fidIt )
   895         QString fid = *fidIt;
   898         if ( !fid.contains( 
'.' ) )
   903         QString 
typeName = fid.section( 
'.', 0, 0 );
   904         fid = fid.section( 
'.', 1, 1 );
   905         if ( !typeNameList.contains( typeName ) )
   911         if ( fidsMap.contains( typeName ) )
   913           fids = fidsMap.value( typeName );
   916         fidsMap.insert( typeName, fids );
   919       QMap<QString, QStringList>::const_iterator fidsMapIt = fidsMap.constBegin();
   920       while ( fidsMapIt != fidsMap.constEnd() )
   928         request.
deletes.append( action );
   933     if ( !parameters.contains( QStringLiteral( 
"TYPENAME" ) ) )
   938     typeNameList = parameters.value( QStringLiteral( 
"TYPENAME" ) ).split( 
',' );
   941     QStringList::const_iterator typeNameIt = typeNameList.constBegin();
   942     for ( ; typeNameIt != typeNameList.constEnd(); ++typeNameIt )
   945       typeName = typeName.trimmed();
   950       request.
deletes.append( action );
   954     if ( parameters.contains( QStringLiteral( 
"EXP_FILTER" ) ) )
   956       QString expFilterName = parameters.value( QStringLiteral( 
"EXP_FILTER" ) );
   957       QStringList expFilterList;
   958       QRegExp rx( 
"\\(([^()]+)\\)" );
   959       if ( rx.indexIn( expFilterName, 0 ) == -1 )
   961         expFilterList << expFilterName;
   966         while ( ( pos = rx.indexIn( expFilterName, pos ) ) != -1 )
   968           expFilterList << rx.cap( 1 );
   969           pos += rx.matchedLength();
   974       if ( request.
deletes.size() == expFilterList.size() )
   977         QList<transactionDelete>::iterator dIt = request.
deletes.begin();
   978         QStringList::const_iterator expFilterIt = expFilterList.constBegin();
   979         for ( ; dIt != request.
deletes.end(); ++dIt )
   984           if ( expFilterIt != expFilterList.constEnd() )
   986             expFilter = *expFilterIt;
   988           std::shared_ptr<QgsExpression> filter( 
new QgsExpression( expFilter ) );
   991             if ( filter->hasParserError() )
   997               if ( filter->needsGeometry() )
  1008         QgsMessageLog::logMessage( 
"There has to be a 1:1 mapping between each element in a TYPENAME and the EXP_FILTER list" );
  1012     if ( parameters.contains( QStringLiteral( 
"BBOX" ) ) )
  1015       QString bbox = parameters.value( QStringLiteral( 
"BBOX" ) );
  1016       if ( bbox.isEmpty() )
  1022       QStringList corners = bbox.split( 
',' );
  1023       if ( corners.size() != 4 )
  1031       for ( 
int i = 0; i < 4; i++ )
  1033         corners[i].replace( 
' ', 
'+' );
  1034         d[i] = corners[i].toDouble( &ok );
  1044       QList<transactionDelete>::iterator dIt = request.
deletes.begin();
  1045       for ( ; dIt != request.
deletes.end(); ++dIt )
  1052     else if ( parameters.contains( QStringLiteral( 
"FILTER" ) ) )
  1054       QString filterName = parameters.value( QStringLiteral( 
"FILTER" ) );
  1055       QStringList filterList;
  1056       QRegExp rx( 
"\\(([^()]+)\\)" );
  1057       if ( rx.indexIn( filterName, 0 ) == -1 )
  1059         filterList << filterName;
  1064         while ( ( pos = rx.indexIn( filterName, pos ) ) != -1 )
  1066           filterList << rx.cap( 1 );
  1067           pos += rx.matchedLength();
  1072       if ( request.
deletes.size() != filterList.size() )
  1078       QList<transactionDelete>::iterator dIt = request.
deletes.begin();
  1079       QStringList::const_iterator filterIt = filterList.constBegin();
  1080       for ( ; dIt != request.
deletes.end(); ++dIt )
  1085         QDomDocument filter;
  1086         if ( filterIt != filterList.constEnd() )
  1089           if ( !filter.setContent( *filterIt, 
true, &errorMsg ) )
  1095         QDomElement filterElem = filter.firstChildElement();
  1096         QStringList serverFids;
  1100         if ( filterIt != filterList.constEnd() )
  1115     QDomNodeList docChildNodes = docElem.childNodes();
  1117     QDomElement actionElem;
  1120     for ( 
int i = docChildNodes.count(); 0 < i; --i )
  1122       actionElem = docChildNodes.at( i - 1 ).toElement();
  1123       actionName = actionElem.localName();
  1125       if ( actionName == QLatin1String( 
"Insert" ) )
  1128         request.
inserts.append( action );
  1130       else if ( actionName == QLatin1String( 
"Update" ) )
  1133         request.
updates.append( action );
  1135       else if ( actionName == QLatin1String( 
"Delete" ) )
  1138         request.
deletes.append( action );
  1147     QString 
typeName = actionElem.attribute( QStringLiteral( 
"typeName" ) );
  1148     if ( typeName.contains( 
':' ) )
  1149       typeName = typeName.section( 
':', 1, 1 );
  1151     QDomElement filterElem = actionElem.firstChild().toElement();
  1152     if ( filterElem.tagName() != QLatin1String( 
"Filter" ) )
  1157     QStringList serverFids;
  1164     action.
error = 
false;
  1166     if ( actionElem.hasAttribute( QStringLiteral( 
"handle" ) ) )
  1168       action.
handle = actionElem.attribute( QStringLiteral( 
"handle" ) );
  1177     QString 
typeName = actionElem.attribute( QStringLiteral( 
"typeName" ) );
  1178     if ( typeName.contains( 
':' ) )
  1179       typeName = typeName.section( 
':', 1, 1 );
  1181     QDomNodeList propertyNodeList = actionElem.elementsByTagName( QStringLiteral( 
"Property" ) );
  1182     if ( propertyNodeList.isEmpty() )
  1187     QMap<QString, QString> propertyMap;
  1188     QDomElement propertyElem;
  1189     QDomElement nameElem;
  1190     QDomElement valueElem;
  1191     QDomElement geometryElem;
  1193     for ( 
int l = 0; l < propertyNodeList.count(); ++l )
  1195       propertyElem = propertyNodeList.at( l ).toElement();
  1196       nameElem = propertyElem.elementsByTagName( QStringLiteral( 
"Name" ) ).at( 0 ).toElement();
  1197       valueElem = propertyElem.elementsByTagName( QStringLiteral( 
"Value" ) ).at( 0 ).toElement();
  1198       if ( nameElem.text() != QLatin1String( 
"geometry" ) )
  1200         propertyMap.insert( nameElem.text(), valueElem.text() );
  1204         geometryElem = valueElem;
  1208     QDomNodeList filterNodeList = actionElem.elementsByTagName( QStringLiteral( 
"Filter" ) );
  1210     QStringList serverFids;
  1211     if ( filterNodeList.size() != 0 )
  1213       QDomElement filterElem = filterNodeList.at( 0 ).toElement();
  1220     action.propertyMap = propertyMap;
  1221     action.geometryElement = geometryElem;
  1222     action.featureRequest = featureRequest;
  1223     action.serverFids = serverFids;
  1224     action.error = 
false;
  1226     if ( actionElem.hasAttribute( QStringLiteral( 
"handle" ) ) )
  1228       action.handle = actionElem.attribute( QStringLiteral( 
"handle" ) );
  1236     QDomNodeList featureNodeList = actionElem.childNodes();
  1237     if ( featureNodeList.size() != 1 )
  1243     for ( 
int i = 0; i < featureNodeList.count(); ++i )
  1245       QString tempTypeName = featureNodeList.at( i ).toElement().localName();
  1246       if ( tempTypeName.contains( 
':' ) )
  1247         tempTypeName = tempTypeName.section( 
':', 1, 1 );
  1249       if ( typeName.isEmpty() )
  1251         typeName = tempTypeName;
  1253       else if ( tempTypeName != typeName )
  1262     action.
error = 
false;
  1264     if ( actionElem.hasAttribute( QStringLiteral( 
"handle" ) ) )
  1266       action.
handle = actionElem.attribute( QStringLiteral( 
"handle" ) );
  1275     void addTransactionResult( QDomDocument &responseDoc, QDomElement &resultsElem,
  1276                                const QString &locator, 
const QString &message )
  1278       QDomElement trElem = responseDoc.createElement( QStringLiteral( 
"Action" ) );
  1279       resultsElem.appendChild( trElem );
  1281       if ( !locator.isEmpty() )
  1283         trElem.setAttribute( QStringLiteral( 
"locator" ), locator );
  1286       if ( !message.isEmpty() )
  1288         QDomElement mesElem = responseDoc.createElement( QStringLiteral( 
"Message" ) );
  1289         mesElem.appendChild( responseDoc.createTextNode( message ) );
  1290         trElem.appendChild( mesElem );
 Class for parsing and evaluation of expressions (formerly called "search strings"). 
bool layerInsertPermission(const QgsVectorLayer *layer) const
Returns the layer insert right. 
Wrapper for iterator of features from vector data provider or vector layer. 
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...
A rectangle specified with double values. 
Base class for all map layer types. 
transactionUpdate parseUpdateActionElement(QDomElement &actionElem, const QgsProject *project)
Transform Update element to transactionUpdate. 
SERVER_EXPORT QStringList wfstUpdateLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with update capabilities...
QSet< QgsFeatureId > QgsFeatureIds
virtual QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities. 
QMap< QString, int > fieldNameMap() const
Returns a map where the key is the name of the field and the value is its index. 
QgsMapLayerType type() const
Returns the type of the layer. 
QgsFeatureRequest featureRequest
SERVER_EXPORT QString getServerFid(const QgsFeature &feature, const QgsAttributeList &pkAttributes)
Returns the feature id based on primary keys. 
transactionRequest parseTransactionRequestBody(QDomElement &docElem, const QgsProject *project)
Transform RequestBody root element to getFeatureRequest. 
bool addFeatures(QgsFeatureList &flist, QgsFeatureSink::Flags flags=nullptr) override
Adds a list of features to the sink. 
QList< QgsFeature > QgsFeatureList
bool commitChanges()
Attempts to commit to the underlying data provider any buffered changes made since the last to call t...
bool startEditing()
Makes the layer editable. 
Exception base class for service exceptions. 
virtual QgsAttributeList pkAttributeIndexes() const
Returns list of indexes of fields that make up the primary key. 
bool deleteFeatures(const QgsFeatureIds &fids)
Deletes a set of features from the layer (but does not commit it) 
Container of fields for a vector layer. 
A geometry is the spatial representation of a feature. 
bool setAttribute(int field, const QVariant &attr)
Set an attribute's value by field index. 
static QgsExpressionContextScope * projectScope(const QgsProject *project)
Creates a new scope which contains variables and functions relating to a QGIS project. 
The feature class encapsulates a single feature including its id, geometry and a list of field/values...
QString message() const
Returns the exception message. 
bool layerDeletePermission(const QgsVectorLayer *layer) const
Returns the layer delete right. 
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device...
QString layerTypeName(const QgsMapLayer *layer)
Returns typename from vector layer. 
QgsField at(int i) const
Gets field at particular index (must be in range 0..N-1) 
QList< transactionUpdate > updates
static void applyAccessControlLayerFilters(const QgsAccessControl *accessControl, QgsMapLayer *mapLayer, QHash< QgsMapLayer *, QString > &originalLayerFilters)
Apply filter from AccessControl. 
QMap< QString, QString > propertyMap
QgsFeatureRequest & setExpressionContext(const QgsExpressionContext &context)
Sets the expression context used to evaluate filter expressions. 
QgsFeatureRequest & setFilterExpression(const QString &expression)
Set the filter expression. 
transactionRequest parseTransactionParameters(QgsServerRequest::Parameters parameters, const QgsProject *project)
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context...
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject. 
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...
bool rollBack(bool deleteBuffer=true)
Stops a current editing operation and discards any uncommitted edits. 
QList< transactionInsert > inserts
SERVER_EXPORT QStringList wfstDeleteLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with delete capabilities...
QgsFields fields() const override=0
Returns the fields associated with this data provider. 
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase. 
QDomNodeList featureNodeList
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary). 
This class wraps a request for features to a vector layer (or directly its vector data provider)...
void writeTransaction(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output WFS transaction response. 
const QString WFS_NAMESPACE
QgsFeatureRequest & setFilterRect(const QgsRectangle &rectangle)
Sets the rectangle from which features will be taken. 
QgsFeatureRequest parseFilterElement(const QString &typeName, QDomElement &filterElem, const QgsProject *project)
Transform a Filter element to a feature request. 
Allows modifications of geometries. 
Encapsulates a QGIS project, including sets of map layers and their styles, layouts, annotations, canvases, etc. 
void clearErrors()
Clear recorded errors. 
QgsFeatureList featuresFromGML(QDomNodeList featureNodeList, QgsVectorDataProvider *provider)
Transform GML feature nodes to features. 
Encapsulate a field in an attribute table or data source. 
SERVER_EXPORT QgsFeatureRequest updateFeatureRequestFromServerFids(QgsFeatureRequest &featureRequest, const QStringList &serverFids, const QgsVectorDataProvider *provider)
Returns the feature request based on feature ids build with primary keys. 
transactionDelete parseDeleteActionElement(QDomElement &actionElem, const QgsProject *project)
Transform Delete element to transactionDelete. 
const QString OGC_NAMESPACE
QDomDocument createTransactionDocument(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request)
Create a wfs transaction document. 
QStringList commitErrors() const
Returns a list containing any error messages generated when attempting to commit changes to the layer...
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
QStringList insertFeatureIds
static QgsGeometry geometryFromGML(const QString &xmlString)
Static method that creates geometry from GML. 
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins...
QgsFieldConstraints constraints
SERVER_EXPORT QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS. 
void setGeometry(const QgsGeometry &geometry)
Set the feature's geometry. 
QList< transactionDelete > deletes
RAII class to restore layer filters on destruction. 
void performTransaction(transactionRequest &aRequest, QgsServerInterface *serverIface, const QgsProject *project)
Perform the transaction. 
A helper class that centralizes restrictions given by all the access control filter plugins...
void filterFeatures(const QgsVectorLayer *layer, QgsFeatureRequest &filterFeatures) const override
Filter the features of the layer. 
Q_INVOKABLE QgsMapLayer * mapLayer(const QString &layerId) const
Retrieve a pointer to a registered layer by layer ID. 
SERVER_EXPORT QStringList wfstInsertLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published as WFS-T with insert capabilities...
Exception thrown when data access violates access controls. 
Allows deletion of features. 
bool layerUpdatePermission(const QgsVectorLayer *layer) const
Returns the layer update right. 
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request. 
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
bool changeAttributeValue(QgsFeatureId fid, int field, const QVariant &newValue, const QVariant &oldValue=QVariant(), bool skipDefaultValues=false)
Changes an attribute value for a feature (but does not immediately commit the changes). 
QDomElement geometryElement
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters. 
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr. 
QList< int > QgsAttributeList
static QgsExpressionContextScope * layerScope(const QgsMapLayer *layer)
Creates a new scope which contains variables and functions relating to a QgsMapLayer. 
bool nextFeature(QgsFeature &f)
This is the base class for vector data providers. 
Represents a vector layer which manages a vector based data sets. 
Allows modification of attribute values. 
transactionInsert parseInsertActionElement(QDomElement &actionElem)
Transform Insert element to transactionInsert. 
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags flags)
Sets flags that affect how features will be fetched. 
QMap< QString, QString > Parameters
bool allowToEdit(const QgsVectorLayer *layer, const QgsFeature &feature) const
Are we authorized to modify the following geometry. 
QgsFeatureRequest featureRequest