40#include <QRegularExpression> 
   41#include <QRegularExpressionMatch> 
   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( request.
data(), 
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;
 
  271      if ( layer->
type() != Qgis::LayerType::Vector )
 
  278      if ( !typeNameList.contains( name ) )
 
  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.contains( 
typeName ) )
 
  337        action.
errorMsg = QStringLiteral( 
"TypeName '%1' unknown" ).arg( 
typeName );
 
  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() )
 
  431          QVariant value = it.value();
 
  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( QLatin1String( 
"; " ) ) );
 
  541      action.
error = 
false;
 
  546    tdIt = aRequest.
deletes.begin();
 
  547    for ( ; tdIt != aRequest.
deletes.end(); ++tdIt )
 
  552      if ( !mapLayerMap.contains( 
typeName ) )
 
  555        action.
errorMsg = QStringLiteral( 
"TypeName '%1' unknown" ).arg( 
typeName );
 
  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( QLatin1String( 
"; " ) ) );
 
  660      action.
error = 
false;
 
  664    tiIt = aRequest.
inserts.begin();
 
  665    for ( ; tiIt != aRequest.
inserts.end(); ++tiIt )
 
  670      if ( !mapLayerMap.contains( 
typeName ) )
 
  673        action.
errorMsg = QStringLiteral( 
"TypeName '%1' unknown" ).arg( 
typeName );
 
  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 );
 
  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( QLatin1String( 
"; " ) ) );
 
  775      action.
error = 
false;
 
  779      for ( 
const QgsFeature &feat : std::as_const( featureList ) )
 
  786    filterRestorer.reset();
 
  798    const QMap<QString, int> fieldMap = provider->fieldNameMap();
 
  799    QMap<QString, int>::const_iterator fieldMapIt;
 
  801    for ( 
int i = 0; i < featureNodeList.count(); i++ )
 
  805      QDomElement featureElem = featureNodeList.at( i ).toElement();
 
  806      QDomNode currentAttributeChild = featureElem.firstChild();
 
  807      bool conversionSuccess = 
true;
 
  809      while ( !currentAttributeChild.isNull() )
 
  811        QDomElement currentAttributeElement = currentAttributeChild.toElement();
 
  812        QString attrName = currentAttributeElement.localName();
 
  814        if ( attrName != QLatin1String( 
"boundedBy" ) )
 
  816          if ( attrName != QLatin1String( 
"geometry" ) ) 
 
  818            fieldMapIt = fieldMap.find( attrName );
 
  819            if ( fieldMapIt == fieldMap.constEnd() )
 
  825            QString attrValue = currentAttributeElement.text();
 
  828            QgsMessageLog::logMessage( QStringLiteral( 
"attr: name=%1 idx=%2 value=%3" ).arg( attrName ).arg( fieldMapIt.value() ).arg( attrValue ) );
 
  830            if ( attrType == QVariant::Int )
 
  831              feat.
setAttribute( fieldMapIt.value(), attrValue.toInt( &conversionSuccess ) );
 
  832            else if ( attrType == QVariant::Double )
 
  833              feat.
setAttribute( fieldMapIt.value(), attrValue.toDouble( &conversionSuccess ) );
 
  837            if ( !conversionSuccess )
 
  853        currentAttributeChild = currentAttributeChild.nextSibling();
 
  863    if ( !parameters.contains( QStringLiteral( 
"OPERATION" ) ) )
 
  867    if ( parameters.value( QStringLiteral( 
"OPERATION" ) ).toUpper() != QLatin1String( 
"DELETE" ) )
 
  873    if ( ( parameters.contains( QStringLiteral( 
"FEATUREID" ) )
 
  874           && ( parameters.contains( QStringLiteral( 
"FILTER" ) ) || parameters.contains( QStringLiteral( 
"BBOX" ) ) ) )
 
  875         || ( parameters.contains( QStringLiteral( 
"FILTER" ) )
 
  876              && ( parameters.contains( QStringLiteral( 
"FEATUREID" ) ) || parameters.contains( QStringLiteral( 
"BBOX" ) ) ) )
 
  877         || ( parameters.contains( QStringLiteral( 
"BBOX" ) )
 
  878              && ( parameters.contains( QStringLiteral( 
"FEATUREID" ) ) || parameters.contains( QStringLiteral( 
"FILTER" ) ) ) )
 
  886    QStringList typeNameList;
 
  888    if ( parameters.contains( QStringLiteral( 
"FEATUREID" ) ) )
 
  890      QStringList fidList = parameters.value( QStringLiteral( 
"FEATUREID" ) ).split( 
',' );
 
  892      QMap<QString, QStringList> fidsMap;
 
  894      QStringList::const_iterator fidIt = fidList.constBegin();
 
  895      for ( ; fidIt != fidList.constEnd(); ++fidIt )
 
  898        QString fid = *fidIt;
 
  901        if ( !fid.contains( 
'.' ) )
 
  906        QString 
typeName = fid.section( 
'.', 0, 0 );
 
  907        fid = fid.section( 
'.', 1, 1 );
 
  908        if ( !typeNameList.contains( 
typeName ) )
 
  922      QMap<QString, QStringList>::const_iterator fidsMapIt = fidsMap.constBegin();
 
  923      while ( fidsMapIt != fidsMap.constEnd() )
 
  931        request.
deletes.append( action );
 
  936    if ( !parameters.contains( QStringLiteral( 
"TYPENAME" ) ) )
 
  941    typeNameList = parameters.value( QStringLiteral( 
"TYPENAME" ) ).split( 
',' );
 
  944    QStringList::const_iterator typeNameIt = typeNameList.constBegin();
 
  945    for ( ; typeNameIt != typeNameList.constEnd(); ++typeNameIt )
 
  953      request.
deletes.append( action );
 
  957    if ( parameters.contains( QStringLiteral( 
"EXP_FILTER" ) ) )
 
  959      QString expFilterName = parameters.value( QStringLiteral( 
"EXP_FILTER" ) );
 
  960      QStringList expFilterList;
 
  961      const thread_local QRegularExpression rx( 
"\\(([^()]+)\\)" );
 
  962      QRegularExpressionMatchIterator matchIt = rx.globalMatch( expFilterName );
 
  963      if ( !matchIt.hasNext() )
 
  965        expFilterList << expFilterName;
 
  969        while ( matchIt.hasNext() )
 
  971          const QRegularExpressionMatch match = matchIt.next();
 
  972          if ( match.hasMatch() )
 
  974            QStringList matches = match.capturedTexts();
 
  976            expFilterList.append( matches );
 
  982      if ( request.
deletes.size() == expFilterList.size() )
 
  985        QList<transactionDelete>::iterator dIt = request.
deletes.begin();
 
  986        QStringList::const_iterator expFilterIt = expFilterList.constBegin();
 
  987        for ( ; dIt != request.
deletes.end(); ++dIt )
 
  992          if ( expFilterIt != expFilterList.constEnd() )
 
  994            expFilter = *expFilterIt;
 
  996          std::shared_ptr<QgsExpression> filter( 
new QgsExpression( expFilter ) );
 
  999            if ( filter->hasParserError() )
 
 1005              if ( filter->needsGeometry() )
 
 1016        QgsMessageLog::logMessage( 
"There has to be a 1:1 mapping between each element in a TYPENAME and the EXP_FILTER list" );
 
 1020    if ( parameters.contains( QStringLiteral( 
"BBOX" ) ) )
 
 1023      QString bbox = parameters.value( QStringLiteral( 
"BBOX" ) );
 
 1024      if ( bbox.isEmpty() )
 
 1030      QStringList corners = bbox.split( 
',' );
 
 1031      if ( corners.size() != 4 )
 
 1039      for ( 
int i = 0; i < 4; i++ )
 
 1041        corners[i].replace( 
' ', 
'+' );
 
 1042        d[i] = corners[i].toDouble( &ok );
 
 1052      QList<transactionDelete>::iterator dIt = request.
deletes.begin();
 
 1053      for ( ; dIt != request.
deletes.end(); ++dIt )
 
 1060    else if ( parameters.contains( QStringLiteral( 
"FILTER" ) ) )
 
 1062      QString filterName = parameters.value( QStringLiteral( 
"FILTER" ) );
 
 1063      QStringList filterList;
 
 1064      const thread_local QRegularExpression rx( 
"\\(([^()]+)\\)" );
 
 1065      QRegularExpressionMatchIterator matchIt = rx.globalMatch( filterName );
 
 1066      if ( !matchIt.hasNext() )
 
 1068        filterList << filterName;
 
 1072        while ( matchIt.hasNext() )
 
 1074          const QRegularExpressionMatch match = matchIt.next();
 
 1075          if ( match.hasMatch() )
 
 1077            QStringList matches = match.capturedTexts();
 
 1078            matches.pop_front(); 
 
 1079            filterList.append( matches );
 
 1085      if ( request.
deletes.size() != filterList.size() )
 
 1091      QList<transactionDelete>::iterator dIt = request.
deletes.begin();
 
 1092      QStringList::const_iterator filterIt = filterList.constBegin();
 
 1093      for ( ; dIt != request.
deletes.end(); ++dIt )
 
 1098        QDomDocument filter;
 
 1099        if ( filterIt != filterList.constEnd() )
 
 1102          if ( !filter.setContent( *filterIt, 
true, &errorMsg ) )
 
 1108        QDomElement filterElem = filter.firstChildElement();
 
 1109        QStringList serverFids;
 
 1113        if ( filterIt != filterList.constEnd() )
 
 1128    QDomNodeList docChildNodes = docElem.childNodes();
 
 1130    QDomElement actionElem;
 
 1133    for ( 
int i = docChildNodes.count(); 0 < i; --i )
 
 1135      actionElem = docChildNodes.at( i - 1 ).toElement();
 
 1136      actionName = actionElem.localName();
 
 1138      if ( actionName == QLatin1String( 
"Insert" ) )
 
 1141        request.
inserts.append( action );
 
 1143      else if ( actionName == QLatin1String( 
"Update" ) )
 
 1146        request.
updates.append( action );
 
 1148      else if ( actionName == QLatin1String( 
"Delete" ) )
 
 1151        request.
deletes.append( action );
 
 1160    QString 
typeName = actionElem.attribute( QStringLiteral( 
"typeName" ) );
 
 1164    QDomElement filterElem = actionElem.firstChild().toElement();
 
 1165    if ( filterElem.tagName() != QLatin1String( 
"Filter" ) )
 
 1170    QStringList serverFids;
 
 1177    action.
error = 
false;
 
 1179    if ( actionElem.hasAttribute( QStringLiteral( 
"handle" ) ) )
 
 1181      action.
handle = actionElem.attribute( QStringLiteral( 
"handle" ) );
 
 1189    QgsMessageLog::logMessage( QStringLiteral( 
"parseUpdateActionElement" ), QStringLiteral( 
"Server" ), Qgis::MessageLevel::Info );
 
 1190    QString 
typeName = actionElem.attribute( QStringLiteral( 
"typeName" ) );
 
 1194    QDomNodeList propertyNodeList = actionElem.elementsByTagName( QStringLiteral( 
"Property" ) );
 
 1195    if ( propertyNodeList.isEmpty() )
 
 1200    QMap<QString, QString> propertyMap;
 
 1201    QDomElement propertyElem;
 
 1202    QDomElement nameElem;
 
 1203    QDomElement valueElem;
 
 1204    QDomElement geometryElem;
 
 1206    for ( 
int l = 0; l < propertyNodeList.count(); ++l )
 
 1208      propertyElem = propertyNodeList.at( l ).toElement();
 
 1209      nameElem = propertyElem.elementsByTagName( QStringLiteral( 
"Name" ) ).at( 0 ).toElement();
 
 1210      valueElem = propertyElem.elementsByTagName( QStringLiteral( 
"Value" ) ).at( 0 ).toElement();
 
 1211      if ( nameElem.text() != QLatin1String( 
"geometry" ) )
 
 1213        propertyMap.insert( nameElem.text(), valueElem.text() );
 
 1217        geometryElem = valueElem;
 
 1221    QDomNodeList filterNodeList = actionElem.elementsByTagName( QStringLiteral( 
"Filter" ) );
 
 1223    QStringList serverFids;
 
 1224    if ( filterNodeList.size() != 0 )
 
 1226      QDomElement filterElem = filterNodeList.at( 0 ).toElement();
 
 1229    QgsMessageLog::logMessage( QStringLiteral( 
"parseUpdateActionElement: serverFids length %1" ).arg( serverFids.count() ), QStringLiteral( 
"Server" ), Qgis::MessageLevel::Info );
 
 1237    action.
error = 
false;
 
 1239    if ( actionElem.hasAttribute( QStringLiteral( 
"handle" ) ) )
 
 1241      action.
handle = actionElem.attribute( QStringLiteral( 
"handle" ) );
 
 1249    QDomNodeList featureNodeList = actionElem.childNodes();
 
 1250    if ( featureNodeList.size() != 1 )
 
 1256    for ( 
int i = 0; i < featureNodeList.count(); ++i )
 
 1258      QString tempTypeName = featureNodeList.at( i ).toElement().localName();
 
 1259      if ( tempTypeName.contains( 
':' ) )
 
 1260        tempTypeName = tempTypeName.section( 
':', 1, 1 );
 
 1266      else if ( tempTypeName != 
typeName )
 
 1275    action.
error = 
false;
 
 1277    if ( actionElem.hasAttribute( QStringLiteral( 
"handle" ) ) )
 
 1279      action.
handle = actionElem.attribute( QStringLiteral( 
"handle" ) );
 
 1288    void addTransactionResult( QDomDocument &responseDoc, QDomElement &resultsElem,
 
 1289                               const QString &locator, 
const QString &message )
 
 1291      QDomElement trElem = responseDoc.createElement( QStringLiteral( 
"Action" ) );
 
 1292      resultsElem.appendChild( trElem );
 
 1294      if ( !locator.isEmpty() )
 
 1296        trElem.setAttribute( QStringLiteral( 
"locator" ), locator );
 
 1299      if ( !message.isEmpty() )
 
 1301        QDomElement mesElem = responseDoc.createElement( QStringLiteral( 
"Message" ) );
 
 1302        mesElem.appendChild( responseDoc.createTextNode( message ) );
 
 1303        trElem.appendChild( mesElem );
 
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.
 
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...
 
Class for 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)
 
This class wraps a request for features to a vector layer (or directly its vector data provider).
 
QgsFeatureRequest & setFlags(QgsFeatureRequest::Flags 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...
 
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.
 
Q_GADGET Constraints constraints
 
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.
 
Base class for all map layer types.
 
QString id() const
Returns the layer's unique ID, which is used to access this layer from QgsProject.
 
QgsCoordinateTransformContext transformContext() const
Returns the layer data provider coordinate transform context or a default transform context if the la...
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
 
RAII class to restore layer filters on destruction.
 
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.
 
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins.
 
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
 
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
 
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.
 
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
 
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)
Returns true if the specified variant should be considered a NULL value.
 
This is the base class for vector data providers.
 
@ ChangeGeometries
Allows modifications of geometries.
 
@ DeleteFeatures
Allows deletion of features.
 
@ ChangeAttributeValues
Allows modification of attribute values.
 
@ AddFeatures
Allows adding features.
 
void clearErrors()
Clear recorded errors.
 
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.
 
virtual Q_INVOKABLE QgsVectorDataProvider::Capabilities capabilities() const
Returns flags containing the supported capabilities.
 
Represents a vector layer which manages a vector based data sets.
 
Q_INVOKABLE bool startEditing()
Makes the layer editable.
 
QgsFeatureIterator getFeatures(const QgsFeatureRequest &request=QgsFeatureRequest()) const FINAL
Queries the layer for features specified in request.
 
bool deleteFeatures(const QgsFeatureIds &fids, DeleteContext *context=nullptr)
Deletes a set of features from the layer (but does not commit it)
 
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...
 
QgsVectorDataProvider * dataProvider() FINAL
Returns the layer's data provider, it may be nullptr.
 
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).
 
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.
 
SERVER_EXPORT QgsFeatureRequest updateFeatureRequestFromServerFids(QgsFeatureRequest &featureRequest, const QStringList &serverFids, const QgsVectorDataProvider *provider)
Returns the feature request based on feature ids build with primary keys.
 
SERVER_EXPORT QString getServerFid(const QgsFeature &feature, const QgsAttributeList &pkAttributes)
Returns the feature id based on primary keys.
 
SERVER_EXPORT QStringList wfsLayerIds(const QgsProject &project)
Returns the Layer ids list defined in a QGIS project as published in WFS.
 
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.
 
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.
 
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.
 
QString layerTypeName(const QgsMapLayer *layer)
Returns typename from vector layer.
 
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.
 
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< transactionInsert > inserts
 
QList< transactionDelete > deletes
 
QList< transactionUpdate > updates
 
QgsFeatureRequest featureRequest
 
QDomElement geometryElement
 
QMap< QString, QString > propertyMap