QGIS API Documentation  3.4.15-Madeira (e83d02e274)
qgswmsgetstyles.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgswmsgetstyles.h
3  -------------------------
4  begin : December 20 , 2016
5  copyright : (C) 2007 by Marco Hugentobler (original code)
6  (C) 2014 by Alessandro Pasotti (original code)
7  (C) 2016 by David Marteau
8  email : marco dot hugentobler at karto dot baug dot ethz dot ch
9  a dot pasotti at itopen dot it
10  david dot marteau at 3liz dot com
11  ***************************************************************************/
12 
13 /***************************************************************************
14  * *
15  * This program is free software; you can redistribute it and/or modify *
16  * it under the terms of the GNU General Public License as published by *
17  * the Free Software Foundation; either version 2 of the License, or *
18  * (at your option) any later version. *
19  * *
20  ***************************************************************************/
21 
22 
23 #include "qgswmsutils.h"
24 #include "qgswmsgetstyles.h"
25 #include "qgsserverprojectutils.h"
26 
27 #include "qgsproject.h"
28 #include "qgsrenderer.h"
29 #include "qgsvectorlayer.h"
31 #include "qgsvectorlayerlabeling.h"
32 
33 
34 namespace QgsWms
35 {
36 
37  namespace
38  {
39  QDomDocument getStyledLayerDescriptorDocument( QgsServerInterface *serverIface, const QgsProject *project,
40  QStringList &layerList );
41  }
42 
43  void writeGetStyles( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
44  const QgsServerRequest &request, QgsServerResponse &response )
45  {
46  QDomDocument doc = getStyles( serverIface, project, version, request );
47  response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) );
48  response.write( doc.toByteArray() );
49  }
50 
51  QDomDocument getStyles( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
52  const QgsServerRequest &request )
53  {
54  Q_UNUSED( version );
55 
56  QgsServerRequest::Parameters parameters = request.parameters();
57 
58  QString layersName = parameters.value( "LAYERS" );
59 
60  if ( layersName.isEmpty() )
61  {
62  throw QgsBadRequestException( QStringLiteral( "LayerNotSpecified" ),
63  QStringLiteral( "Layers is mandatory for GetStyles operation" ) );
64  }
65 
66  QStringList layerList = layersName.split( ',', QString::SkipEmptyParts );
67  if ( layerList.isEmpty() )
68  {
69  throw QgsBadRequestException( QStringLiteral( "LayerNotSpecified" ),
70  QStringLiteral( "Layers is mandatory for GetStyles operation" ) );
71  }
72 
73  return getStyledLayerDescriptorDocument( serverIface, project, layerList );
74  }
75 
76  //GetStyle for compatibility with earlier QGIS versions
77  void writeGetStyle( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
78  const QgsServerRequest &request, QgsServerResponse &response )
79  {
80  QDomDocument doc = getStyle( serverIface, project, version, request );
81  response.setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/xml; charset=utf-8" ) );
82  response.write( doc.toByteArray() );
83  }
84 
85  QDomDocument getStyle( QgsServerInterface *serverIface, const QgsProject *project, const QString &version,
86  const QgsServerRequest &request )
87  {
88  Q_UNUSED( version );
89 
90  QgsServerRequest::Parameters parameters = request.parameters();
91 
92  QDomDocument doc;
93 
94  QString styleName = parameters.value( QStringLiteral( "STYLE" ) );
95  QString layerName = parameters.value( QStringLiteral( "LAYER" ) );
96 
97  if ( styleName.isEmpty() )
98  {
99  throw QgsServiceException( QStringLiteral( "StyleNotSpecified" ),
100  QStringLiteral( "Style is mandatory for GetStyle operation" ), 400 );
101  }
102 
103  if ( layerName.isEmpty() )
104  {
105  throw QgsServiceException( QStringLiteral( "LayerNotSpecified" ),
106  QStringLiteral( "Layer is mandatory for GetStyle operation" ), 400 );
107  }
108 
109  QStringList layerList;
110  layerList.append( layerName );
111  return getStyledLayerDescriptorDocument( serverIface, project, layerList );
112  }
113 
114  namespace
115  {
116  QDomDocument getStyledLayerDescriptorDocument( QgsServerInterface *serverIface, const QgsProject *project,
117  QStringList &layerList )
118  {
119  QDomDocument myDocument = QDomDocument();
120 
121  QDomNode header = myDocument.createProcessingInstruction( QStringLiteral( "xml" ), QStringLiteral( "version=\"1.0\" encoding=\"UTF-8\"" ) );
122  myDocument.appendChild( header );
123 
124  // Create the root element
125  QDomElement root = myDocument.createElementNS( QStringLiteral( "http://www.opengis.net/sld" ), QStringLiteral( "StyledLayerDescriptor" ) );
126  root.setAttribute( QStringLiteral( "version" ), QStringLiteral( "1.1.0" ) );
127  root.setAttribute( QStringLiteral( "xsi:schemaLocation" ), QStringLiteral( "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" ) );
128  root.setAttribute( QStringLiteral( "xmlns:ogc" ), QStringLiteral( "http://www.opengis.net/ogc" ) );
129  root.setAttribute( QStringLiteral( "xmlns:se" ), QStringLiteral( "http://www.opengis.net/se" ) );
130  root.setAttribute( QStringLiteral( "xmlns:xlink" ), QStringLiteral( "http://www.w3.org/1999/xlink" ) );
131  root.setAttribute( QStringLiteral( "xmlns:xsi" ), QStringLiteral( "http://www.w3.org/2001/XMLSchema-instance" ) );
132  myDocument.appendChild( root );
133 
134  // access control
135 #ifdef HAVE_SERVER_PYTHON_PLUGINS
136  QgsAccessControl *accessControl = serverIface->accessControls();
137 #else
138  ( void )serverIface;
139 #endif
140  // Use layer ids
141  bool useLayerIds = QgsServerProjectUtils::wmsUseLayerIds( *project );
142  // WMS restricted layers
143  QStringList restrictedLayers = QgsServerProjectUtils::wmsRestrictedLayers( *project );
144 
145  for ( QgsMapLayer *layer : project->mapLayers() )
146  {
147  QString name = layer->name();
148  if ( useLayerIds )
149  name = layer->id();
150  else if ( !layer->shortName().isEmpty() )
151  name = layer->shortName();
152 
153  if ( !layerList.contains( name ) )
154  {
155  continue;
156  }
157 
158  //unpublished layer
159  if ( restrictedLayers.contains( layer->name() ) )
160  {
161  throw QgsSecurityException( QStringLiteral( "You are not allowed to access to this layer" ) );
162  }
163 
164  if ( accessControl && !accessControl->layerReadPermission( layer ) )
165  {
166  throw QgsSecurityException( QStringLiteral( "You are not allowed to access to this layer" ) );
167  }
168 
169  // Create the NamedLayer element
170  QDomElement namedLayerNode = myDocument.createElement( QStringLiteral( "NamedLayer" ) );
171  root.appendChild( namedLayerNode );
172 
173  // store the Name element
174  QDomElement nameNode = myDocument.createElement( QStringLiteral( "se:Name" ) );
175  nameNode.appendChild( myDocument.createTextNode( name ) );
176  namedLayerNode.appendChild( nameNode );
177 
178  if ( layer->type() == QgsMapLayer::VectorLayer )
179  {
180  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( layer );
181  if ( vlayer->isSpatial() )
182  {
183  QString currentStyle = vlayer->styleManager()->currentStyle();
184 
185  QgsStringMap props;
186  if ( vlayer->hasScaleBasedVisibility() )
187  {
188  props[ QStringLiteral( "scaleMinDenom" ) ] = QString::number( vlayer->maximumScale() );
189  props[ QStringLiteral( "scaleMaxDenom" ) ] = QString::number( vlayer->minimumScale() );
190  }
191 
192  for ( const QString &styleName : vlayer->styleManager()->styles() )
193  {
194  vlayer->styleManager()->setCurrentStyle( styleName );
195 
196  QDomElement userStyleElem = myDocument.createElement( QStringLiteral( "UserStyle" ) );
197 
198  QDomElement styleNameElem = myDocument.createElement( QStringLiteral( "se:Name" ) );
199  styleNameElem.appendChild( myDocument.createTextNode( styleName ) );
200 
201  userStyleElem.appendChild( styleNameElem );
202 
203  QDomElement featureTypeStyleElem = myDocument.createElement( QStringLiteral( "se:FeatureTypeStyle" ) );
204  userStyleElem.appendChild( featureTypeStyleElem );
205 
206  vlayer->renderer()->toSld( myDocument, featureTypeStyleElem, props );
207  if ( vlayer->labelsEnabled() )
208  {
209  vlayer->labeling()->toSld( featureTypeStyleElem, props );
210  }
211 
212  namedLayerNode.appendChild( userStyleElem );
213  }
214  vlayer->styleManager()->setCurrentStyle( currentStyle );
215  }
216  }
217  }
218 
219  return myDocument;
220  }
221  }
222 
223 
224 } // namespace QgsWms
225 
226 
227 
228 
QDomDocument getStyle(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request)
Returns an SLD file with the style of the requested layer.
void writeGetStyles(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output GetStyles response.
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...
Base class for all map layer types.
Definition: qgsmaplayer.h:63
double maximumScale() const
Returns the maximum map scale (i.e.
QgsMapLayerStyleManager * styleManager() const
Gets access to the layer&#39;s style manager.
Exception thrown in case of malformed request.
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device...
QMap< QString, QString > QgsStringMap
Definition: qgis.h:577
bool isSpatial() const FINAL
Returns true if this is a geometry layer and false in case of NoGeometry (table only) or UnknownGeome...
Exception class for WMS service exceptions.
bool hasScaleBasedVisibility() const
Returns whether scale based visibility is enabled for the layer.
const QgsAbstractVectorLayerLabeling * labeling() const
Access to const labeling configuration.
QString currentStyle() const
Returns name of the current style.
virtual void toSld(QDomNode &parent, const QgsStringMap &props) const
Writes the SE 1.1 TextSymbolizer element based on the current layer labeling settings.
Reads and writes project states.
Definition: qgsproject.h:89
QgsFeatureRenderer * renderer()
Returns renderer.
virtual void toSld(QDomDocument &doc, QDomElement &element, const QgsStringMap &props=QgsStringMap()) const
used from subclasses to create SLD Rule elements following SLD v1.1 specs
Definition: qgsrenderer.h:300
double minimumScale() const
Returns the minimum map scale (i.e.
void writeGetStyle(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request, QgsServerResponse &response)
Output GetStyle response.
Median cut implementation.
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins...
Exception thrown when data access violates access controls.
QDomDocument getStyles(QgsServerInterface *serverIface, const QgsProject *project, const QString &version, const QgsServerRequest &request)
Returns an SLD file with the styles of the requested layers.
A helper class that centralizes restrictions given by all the access control filter plugins...
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
virtual QgsAccessControl * accessControls() const =0
Gets the registered access control filters.
SERVER_EXPORT QStringList wmsRestrictedLayers(const QgsProject &project)
Returns the restricted layer name list.
bool labelsEnabled() const
Returns whether the layer contains labels which are enabled and should be drawn.
Represents a vector layer which manages a vector based data sets.
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase.
QMap< QString, QgsMapLayer * > mapLayers() const
Returns a map of all registered layers by layer ID.
bool setCurrentStyle(const QString &name)
Set a different style as the current style - will apply it to the layer.
QMap< QString, QString > Parameters
SERVER_EXPORT bool wmsUseLayerIds(const QgsProject &project)
Returns if layer ids are used as name in WMS.
QStringList styles() const
Returns list of all defined style names.
bool layerReadPermission(const QgsMapLayer *layer) const
Returns the layer read right.