Skip to content

Commit

Permalink
Merge pull request #41979 from pblottiere/wms_getstyle
Browse files Browse the repository at this point in the history
WMS getstyle
  • Loading branch information
pblottiere committed Mar 8, 2021
2 parents 3f27472 + 4ac3ef2 commit 875ba80
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 166 deletions.
8 changes: 2 additions & 6 deletions src/server/services/wms/qgswms.cpp
Expand Up @@ -125,13 +125,9 @@ namespace QgsWms
{
writeGetSchemaExtension( response );
}
else if ( QSTR_COMPARE( req, "GetStyle" ) )
else if ( QSTR_COMPARE( req, "GetStyle" ) or QSTR_COMPARE( req, "GetStyles" ) )
{
writeGetStyle( mServerIface, project, version, request, response );
}
else if ( QSTR_COMPARE( req, "GetStyles" ) )
{
writeGetStyles( mServerIface, project, version, request, response );
writeGetStyles( mServerIface, project, request, response );
}
else if ( QSTR_COMPARE( req, "DescribeLayer" ) )
{
Expand Down
183 changes: 45 additions & 138 deletions src/server/services/wms/qgswmsgetstyles.cpp
Expand Up @@ -23,6 +23,7 @@
#include "qgswmsutils.h"
#include "qgswmsserviceexception.h"
#include "qgswmsgetstyles.h"
#include "qgswmsrendercontext.h"
#include "qgsserverprojectutils.h"

#include "qgsproject.h"
Expand All @@ -37,90 +38,35 @@ namespace QgsWms

namespace
{
QDomDocument getStyledLayerDescriptorDocument( QgsServerInterface *serverIface, const QgsProject *project,
QStringList &layerList );
QDomDocument getStyledLayerDescriptorDocument( QgsServerInterface *serverIface, const QgsProject *project, const QgsServerRequest &request );
}

void writeGetStyles( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
void writeGetStyles( QgsServerInterface *serverIface, const QgsProject *project,
const QgsServerRequest &request, QgsServerResponse &response )
{
QDomDocument doc = getStyles( serverIface, project, version, request );
QDomDocument doc = getStyles( serverIface, project, request );
response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) );
response.write( doc.toByteArray() );
}

QDomDocument getStyles( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
QDomDocument getStyles( QgsServerInterface *serverIface, const QgsProject *project,
const QgsServerRequest &request )
{
Q_UNUSED( version )

QgsServerRequest::Parameters parameters = request.parameters();

QString layersName = parameters.value( "LAYERS" );

if ( layersName.isEmpty() )
{
throw QgsBadRequestException( QgsServiceException::QGIS_MissingParameterValue,
QgsWmsParameter::LAYERS );
}

#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
QStringList layerList = layersName.split( ',', QString::SkipEmptyParts );
#else
QStringList layerList = layersName.split( ',', Qt::SkipEmptyParts );
#endif
if ( layerList.isEmpty() )
{
throw QgsBadRequestException( QgsServiceException::QGIS_MissingParameterValue,
QgsWmsParameter::LAYERS );
}

return getStyledLayerDescriptorDocument( serverIface, project, layerList );
}

//GetStyle for compatibility with earlier QGIS versions
void writeGetStyle( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
const QgsServerRequest &request, QgsServerResponse &response )
{
QDomDocument doc = getStyle( serverIface, project, version, request );
response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) );
response.write( doc.toByteArray() );
return getStyledLayerDescriptorDocument( serverIface, project, request );
}

QDomDocument getStyle( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
const QgsServerRequest &request )
namespace
{
Q_UNUSED( version )

QgsServerRequest::Parameters parameters = request.parameters();

QDomDocument doc;

QString styleName = parameters.value( QStringLiteral( "STYLE" ) );
QString layerName = parameters.value( QStringLiteral( "LAYER" ) );

if ( styleName.isEmpty() )
QDomDocument getStyledLayerDescriptorDocument( QgsServerInterface *serverIface, const QgsProject *project, const QgsServerRequest &request )
{
throw QgsBadRequestException( QgsServiceException::QGIS_MissingParameterValue,
QgsWmsParameter::STYLE );
}
// init WMS parameters and context
const QgsWmsParameters parameters( request.serverParameters() );

if ( layerName.isEmpty() )
{
throw QgsBadRequestException( QgsServiceException::QGIS_MissingParameterValue,
QgsWmsParameter::LAYERS );
}

QStringList layerList;
layerList.append( layerName );
return getStyledLayerDescriptorDocument( serverIface, project, layerList );
}
QgsWmsRenderContext context( project, serverIface );
context.setFlag( QgsWmsRenderContext::SetAccessControl );
context.setParameters( parameters );

namespace
{
QDomDocument getStyledLayerDescriptorDocument( QgsServerInterface *serverIface, const QgsProject *project,
QStringList &layerList )
{
// init document
QDomDocument myDocument = QDomDocument();

QDomNode header = myDocument.createProcessingInstruction( QStringLiteral( "xml" ), QStringLiteral( "version=\"1.0\" encoding=\"UTF-8\"" ) );
Expand All @@ -136,98 +82,59 @@ namespace QgsWms
root.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
myDocument.appendChild( root );

// access control
#ifdef HAVE_SERVER_PYTHON_PLUGINS
QgsAccessControl *accessControl = serverIface->accessControls();
#else
( void )serverIface;
#endif
// Use layer ids
bool useLayerIds = QgsServerProjectUtils::wmsUseLayerIds( *project );
// WMS restricted layers
QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );

for ( QgsMapLayer *layer : project->mapLayers() )
for ( auto layer : context.layersToRender() )
{
QString name = layer->name();
if ( useLayerIds )
name = layer->id();
else if ( !layer->shortName().isEmpty() )
name = layer->shortName();

if ( !layerList.contains( name ) )
{
continue;
}

//unpublished layer
if ( restrictedLayers.contains( layer->name() ) )
{
throw QgsSecurityException( QStringLiteral( "You are not allowed to access to this layer" ) );
}
#ifdef HAVE_SERVER_PYTHON_PLUGINS
if ( accessControl && !accessControl->layerReadPermission( layer ) )
{
throw QgsSecurityException( QStringLiteral( "You are not allowed to access to this layer" ) );
}
#endif
// Create the NamedLayer element
QDomElement namedLayerNode = myDocument.createElement( QStringLiteral( "NamedLayer" ) );
root.appendChild( namedLayerNode );

// store the Name element
QDomElement nameNode = myDocument.createElement( QStringLiteral( "se:Name" ) );
nameNode.appendChild( myDocument.createTextNode( name ) );
nameNode.appendChild( myDocument.createTextNode( context.layerNickname( *layer ) ) );
namedLayerNode.appendChild( nameNode );

if ( layer->type() == QgsMapLayerType::VectorLayer )
{
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( vlayer->isSpatial() )
{
QString currentStyle = vlayer->styleManager()->currentStyle();
if ( layer->type() != QgsMapLayerType::VectorLayer )
continue;

QVariantMap props;
if ( vlayer->hasScaleBasedVisibility() )
{
props[ QStringLiteral( "scaleMinDenom" ) ] = QString::number( vlayer->maximumScale() );
props[ QStringLiteral( "scaleMaxDenom" ) ] = QString::number( vlayer->minimumScale() );
}
QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
if ( ! vlayer->isSpatial() )
continue;

for ( const QString &styleName : vlayer->styleManager()->styles() )
{
vlayer->styleManager()->setCurrentStyle( styleName );
QString currentStyle = vlayer->styleManager()->currentStyle();

QDomElement userStyleElem = myDocument.createElement( QStringLiteral( "UserStyle" ) );
QVariantMap props;
if ( vlayer->hasScaleBasedVisibility() )
{
props[ QStringLiteral( "scaleMinDenom" ) ] = QString::number( vlayer->maximumScale() );
props[ QStringLiteral( "scaleMaxDenom" ) ] = QString::number( vlayer->minimumScale() );
}

QDomElement styleNameElem = myDocument.createElement( QStringLiteral( "se:Name" ) );
styleNameElem.appendChild( myDocument.createTextNode( styleName ) );
for ( const QString &styleName : vlayer->styleManager()->styles() )
{
vlayer->styleManager()->setCurrentStyle( styleName );

userStyleElem.appendChild( styleNameElem );
QDomElement userStyleElem = myDocument.createElement( QStringLiteral( "UserStyle" ) );

QDomElement featureTypeStyleElem = myDocument.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
userStyleElem.appendChild( featureTypeStyleElem );
QDomElement styleNameElem = myDocument.createElement( QStringLiteral( "se:Name" ) );
styleNameElem.appendChild( myDocument.createTextNode( styleName ) );

vlayer->renderer()->toSld( myDocument, featureTypeStyleElem, props );
if ( vlayer->labelsEnabled() )
{
vlayer->labeling()->toSld( featureTypeStyleElem, props );
}
userStyleElem.appendChild( styleNameElem );

namedLayerNode.appendChild( userStyleElem );
}
vlayer->styleManager()->setCurrentStyle( currentStyle );
QDomElement featureTypeStyleElem = myDocument.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
userStyleElem.appendChild( featureTypeStyleElem );

vlayer->renderer()->toSld( myDocument, featureTypeStyleElem, props );
if ( vlayer->labelsEnabled() )
{
vlayer->labeling()->toSld( featureTypeStyleElem, props );
}

namedLayerNode.appendChild( userStyleElem );
}
vlayer->styleManager()->setCurrentStyle( currentStyle );
}

return myDocument;
}
}


} // namespace QgsWms




24 changes: 2 additions & 22 deletions src/server/services/wms/qgswmsgetstyles.h
Expand Up @@ -25,34 +25,14 @@ namespace QgsWms
/**
* Output GetStyles response
*/
void writeGetStyles( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
void writeGetStyles( QgsServerInterface *serverIface, const QgsProject *project,
const QgsServerRequest &request, QgsServerResponse &response );


/**
* Returns an SLD file with the styles of the requested layers. Exception is raised in case of troubles :-)
*/
QDomDocument getStyles( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
QDomDocument getStyles( QgsServerInterface *serverIface, const QgsProject *project,
const QgsServerRequest &request );

//GetStyle for compatibility with earlier QGIS versions

/**
* Output GetStyle response
*/
void writeGetStyle( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
const QgsServerRequest &request, QgsServerResponse &response );

/**
* Returns an SLD file with the style of the requested layer
*/
QDomDocument getStyle( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
const QgsServerRequest &request );



} // namespace QgsWms




6 changes: 6 additions & 0 deletions tests/src/python/test_qgsserver_wms.py
Expand Up @@ -131,6 +131,12 @@ def test_getstyles(self):
'getstyles_pointlabel',
project=self.projectPath)

# Test GetStyle with labeling
self.wms_request_compare('GetStyle',
'&layers=pointlabel',
'getstyles_pointlabel',
project=self.projectPath)

def test_wms_getschemaextension(self):
self.wms_request_compare('GetSchemaExtension',
'',
Expand Down

0 comments on commit 875ba80

Please sign in to comment.