Skip to content

Commit

Permalink
Add support for empty OGC WMS filters
Browse files Browse the repository at this point in the history
The FILTER query parameter can now look like that:
`(<Filter>...</Filter>)()`

That means that the second layer has no filter. This is compliant with
waht MapServer supports:
https://mapserver.org/development/rfc/ms-rfc-118.html#examples
  • Loading branch information
Patrick Valsecchi committed Sep 3, 2018
1 parent 3f85938 commit da58c1d
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 22 deletions.
61 changes: 39 additions & 22 deletions src/server/services/wms/qgswmsparameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1167,29 +1167,46 @@ namespace QgsWms
QStringList QgsWmsParameters::filters() const
{
const QString filter = mWmsParameters[ QgsWmsParameter::FILTER ].toString();
if ( filter.startsWith( QStringLiteral( "(<" ) ) && filter.endsWith( QStringLiteral( "Filter>)" ) ) )
QStringList results;
int pos = 0;
while ( pos < filter.size() )
{
// OGC filter on multiple layers
// remove the "(<" at the beginning and the "Filter>)" at the end
const QString toSplit = filter.mid( 2, filter.length() - 10 );

QStringList result;
for ( const QString &cur : toSplit.split( QStringLiteral( "Filter>)(<" ), QString::SkipEmptyParts ) )
if ( pos + 1 < filter.size() && filter[pos] == '(' && filter[pos + 1] == '<' )
{
result.append( QStringLiteral( "<" ) + cur + QStringLiteral( "Filter>" ) );
// OGC filter on multiple layers
int posEnd = filter.indexOf( "Filter>)", pos );
if ( posEnd < 0 )
{
posEnd = filter.size();
}
results.append( filter.mid( pos + 1, posEnd - pos + 6 ) );
pos = posEnd + 8;
}
else if ( pos + 1 < filter.size() && filter[pos] == '(' && filter[pos + 1] == ')' )
{
// empty OGC filter
results.append( "" );
pos += 2;
}
else if ( filter[pos] == '<' )
{
// Single OGC filter
results.append( filter.mid( pos ) );
break;
}
else
{
// QGIS specific filter
int posEnd = filter.indexOf( ';', pos + 1 );
if ( posEnd < 0 )
{
posEnd = filter.size();
}
results.append( filter.mid( pos, posEnd - pos ) );
pos = posEnd + 1;
}
return result;
}
else if ( filter.startsWith( QStringLiteral( "<" ) ) && filter.endsWith( QStringLiteral( "Filter>" ) ) )
{
// single OGC filter
return QStringList( filter );
}
else
{
// QGIS specific filter
return filter.split( ';', QString::SkipEmptyParts );
}
return results;
}

QString QgsWmsParameters::filterGeom() const
Expand Down Expand Up @@ -1233,8 +1250,6 @@ namespace QgsWms

QMultiMap<QString, QString> QgsWmsParameters::getLayerFilters( const QStringList &layers ) const
{
// filter format: "LayerName:filterString;LayerName2:filterString2;..."
// several filters can be defined for one layer
const QStringList rawFilters = filters();
QMultiMap<QString, QString> layerFilters;
for ( int i = 0; i < rawFilters.size(); i++ )
Expand All @@ -1244,8 +1259,10 @@ namespace QgsWms
{
layerFilters.insert( layers[i], f );
}
else
else if ( !f.isEmpty() )
{
// filter format: "LayerName:filterString;LayerName2:filterString2;..."
// several filters can be defined for one layer
const QStringList splits = f.split( ':' );
if ( splits.size() == 2 )
{
Expand Down
21 changes: 21 additions & 0 deletions tests/src/python/test_qgsserver_wms_getmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -800,6 +800,27 @@ def test_wms_getmap_filter_ogc(self):
r, h = self._result(self._execute_request(qs))
self._img_diff_error(r, h, "WMS_GetMap_Filter_OGC")

def test_wms_getmap_filter_ogc_with_empty(self):
filter = "(<Filter><PropertyIsEqualTo><PropertyName>name</PropertyName>" + \
"<Literal>eurasia</Literal></PropertyIsEqualTo></Filter>)()"
qs = "?" + "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetMap",
"LAYERS": "Country,Hello",
"STYLES": "",
"FORMAT": "image/png",
"BBOX": "-16817707,-4710778,5696513,14587125",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:3857",
"FILTER": filter
}.items())])

r, h = self._result(self._execute_request(qs))
self._img_diff_error(r, h, "WMS_GetMap_Filter_OGC")

def test_wms_getmap_selection(self):
qs = "?" + "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
Expand Down

0 comments on commit da58c1d

Please sign in to comment.