Navigation Menu

Skip to content

Commit

Permalink
Merge pull request #9385 from pblottiere/server_external_clean
Browse files Browse the repository at this point in the history
[server] Update external layer management
  • Loading branch information
pblottiere committed Mar 19, 2019
2 parents 477ec2a + 63c0278 commit 1e8aec4
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 32 deletions.
58 changes: 56 additions & 2 deletions src/server/services/wms/qgswmsparameters.cpp
Expand Up @@ -19,6 +19,8 @@
#include "qgsdatasourceuri.h"
#include "qgsmessagelog.h"

const QString EXTERNAL_LAYER_PREFIX = QStringLiteral( "EXTERNAL_WMS:" );

namespace QgsWms
{
//
Expand Down Expand Up @@ -1408,6 +1410,10 @@ namespace QgsWms
for ( int i = 0; i < layers.size(); i++ )
{
QString layer = layers[i];

if ( isExternalLayer( layer ) )
continue;

QgsWmsParametersLayer param;
param.mNickname = layer;

Expand Down Expand Up @@ -1492,6 +1498,21 @@ namespace QgsWms
return params;
}

QList<QgsWmsParametersExternalLayer> QgsWmsParameters::externalLayersParameters() const
{
QList<QgsWmsParametersExternalLayer> externalLayers;

QStringList layers = allLayersNickname();
QStringList::const_iterator rit = std::remove_if( layers.begin(), layers.end(), QgsWmsParameters::isExternalLayer );

for ( QStringList::const_iterator it = layers.begin(); it != rit; ++it )
{
externalLayers << externalLayerParameter( *it );
}

return externalLayers;
}

QString QgsWmsParameters::backgroundColor() const
{
return mWmsParameters[ QgsWmsParameter::BGCOLOR ].toString();
Expand Down Expand Up @@ -1577,13 +1598,30 @@ namespace QgsWms
}

//layers
QStringList layers;
QStringList allLayers;
wmsParam = idParameter( QgsWmsParameter::LAYERS, mapId );
if ( wmsParam.isValid() )
{
layers = wmsParam.toStringList();
allLayers = wmsParam.toStringList();
}

// external layers
QStringList layers;
QList<QgsWmsParametersExternalLayer> eParams;

for ( const auto &layer : qgis::as_const( allLayers ) )
{
if ( isExternalLayer( layer ) )
{
eParams << externalLayerParameter( layer );
}
else
{
layers << layer;
}
}
param.mExternalLayers = eParams;

QStringList styles;
wmsParam = idParameter( QgsWmsParameter::STYLES, mapId );
if ( wmsParam.isValid() )
Expand Down Expand Up @@ -1763,4 +1801,20 @@ namespace QgsWms

return p;
}

QgsWmsParametersExternalLayer QgsWmsParameters::externalLayerParameter( const QString &name ) const
{
QgsWmsParametersExternalLayer param;

param.mName = name;
param.mName.remove( 0, EXTERNAL_LAYER_PREFIX.size() );
param.mUri = externalWMSUri( param.mName );

return param;
}

bool QgsWmsParameters::isExternalLayer( const QString &name )
{
return name.startsWith( EXTERNAL_LAYER_PREFIX );
}
}
17 changes: 17 additions & 0 deletions src/server/services/wms/qgswmsparameters.h
Expand Up @@ -55,6 +55,12 @@ namespace QgsWms
QString mStyle;
};

struct QgsWmsParametersExternalLayer
{
QString mName;
QString mUri;
};

struct QgsWmsParametersHighlightLayer
{
QString mName;
Expand All @@ -79,6 +85,7 @@ namespace QgsWms
float mGridX = 0;
float mGridY = 0;
QList<QgsWmsParametersLayer> mLayers; // list of layers for this composer map
QList<QgsWmsParametersExternalLayer> mExternalLayers; // list of external layers for this composer map
QList<QgsWmsParametersHighlightLayer> mHighlightLayers; // list of highlight layers for this composer map
};

Expand Down Expand Up @@ -944,6 +951,12 @@ namespace QgsWms
*/
QList<QgsWmsParametersHighlightLayer> highlightLayersParameters() const;

/**
* Returns parameters for each external layer.
* \since QGIS 3.8
*/
QList<QgsWmsParametersExternalLayer> externalLayersParameters() const;

/**
* Returns HIGHLIGHT_GEOM as a list of string in WKT.
* \returns highlight geometries
Expand Down Expand Up @@ -1165,6 +1178,8 @@ namespace QgsWms
QStringList atlasPk() const;

private:
static bool isExternalLayer( const QString &name );

bool loadParameter( const QString &name, const QString &value ) override;

void save( const QgsWmsParameter &parameter, bool multi = false );
Expand All @@ -1174,6 +1189,8 @@ namespace QgsWms
void raiseError( const QString &msg ) const;
void log( const QString &msg ) const;

QgsWmsParametersExternalLayer externalLayerParameter( const QString &name ) const;

QMultiMap<QString, QgsWmsParametersFilter> layerFilters( const QStringList &layers ) const;

QMap<QgsWmsParameter::Name, QgsWmsParameter> mWmsParameters;
Expand Down
52 changes: 25 additions & 27 deletions src/server/services/wms/qgswmsrenderer.cpp
Expand Up @@ -653,13 +653,14 @@ namespace QgsWms

if ( !map->keepLayerSet() )
{
if ( cMapParams.mLayers.isEmpty() )
if ( cMapParams.mLayers.isEmpty() && cMapParams.mExternalLayers.isEmpty() )
{
map->setLayers( mapSettings.layers() );
}
else
{
QList<QgsMapLayer *> layerSet = stylizedLayers( cMapParams.mLayers );
layerSet << externalLayers( cMapParams.mExternalLayers );
layerSet << highlightLayers( cMapParams.mHighlightLayers );
std::reverse( layerSet.begin(), layerSet.end() );
map->setLayers( layerSet );
Expand Down Expand Up @@ -856,6 +857,9 @@ namespace QgsWms
setLayerAccessControlFilter( layer );
}

// add external layers
layers = layers << externalLayers( mWmsParameters.externalLayersParameters() );

// add highlight layers above others
layers = layers << highlightLayers( mWmsParameters.highlightLayersParameters() );

Expand Down Expand Up @@ -2914,6 +2918,25 @@ namespace QgsWms
return highlightLayers;
}

QList<QgsMapLayer *> QgsRenderer::externalLayers( const QList<QgsWmsParametersExternalLayer> &params )
{
QList<QgsMapLayer *> layers;

for ( const QgsWmsParametersExternalLayer &param : params )
{
std::unique_ptr<QgsMapLayer> layer = qgis::make_unique< QgsRasterLayer >( param.mUri, param.mName, QStringLiteral( "wms" ) );

if ( layer->isValid() )
{
// to delete later
mTemporaryLayers.append( layer.release() );
layers << mTemporaryLayers.last();
}
}

return layers;
}

QList<QgsMapLayer *> QgsRenderer::sldStylizedLayers( const QString &sld ) const
{
QList<QgsMapLayer *> layers;
Expand Down Expand Up @@ -2976,19 +2999,7 @@ namespace QgsWms
{
QString nickname = param.mNickname;
QString style = param.mStyle;
if ( nickname.startsWith( "EXTERNAL_WMS:" ) )
{
QString externalLayerId = nickname;
externalLayerId.remove( 0, 13 );
QgsMapLayer *externalWMSLayer = createExternalWMSLayer( externalLayerId );
if ( externalWMSLayer )
{
layers.append( externalWMSLayer );
mNicknameLayers[nickname] = externalWMSLayer; //might be used later in GetPrint request
mTemporaryLayers.append( externalWMSLayer );
}
}
else if ( mNicknameLayers.contains( nickname ) && !mRestrictedLayers.contains( nickname ) )
if ( mNicknameLayers.contains( nickname ) && !mRestrictedLayers.contains( nickname ) )
{
if ( !style.isEmpty() )
{
Expand Down Expand Up @@ -3032,19 +3043,6 @@ namespace QgsWms
return layers;
}

QgsMapLayer *QgsRenderer::createExternalWMSLayer( const QString &externalLayerId ) const
{
QString wmsUri = mWmsParameters.externalWMSUri( externalLayerId.toUpper() );
QgsMapLayer *wmsLayer = new QgsRasterLayer( wmsUri, externalLayerId, QStringLiteral( "wms" ) );
if ( !wmsLayer->isValid() )
{
delete wmsLayer;
return nullptr;
}

return wmsLayer;
}

void QgsRenderer::removeTemporaryLayers()
{
qDeleteAll( mTemporaryLayers );
Expand Down
6 changes: 3 additions & 3 deletions src/server/services/wms/qgswmsrenderer.h
Expand Up @@ -122,6 +122,9 @@ namespace QgsWms
// Build and returns highlight layers
QList<QgsMapLayer *> highlightLayers( QList<QgsWmsParametersHighlightLayer> params );

// Build and returns external layers
QList<QgsMapLayer *> externalLayers( const QList<QgsWmsParametersExternalLayer> &params );

// Init a map with nickname for layers' project
void initNicknameLayers();

Expand Down Expand Up @@ -289,9 +292,6 @@ namespace QgsWms
* */
bool configurePrintLayout( QgsPrintLayout *c, const QgsMapSettings &mapSettings, bool atlasPrint = false );

//! Creates external WMS layer. Caller takes ownership
QgsMapLayer *createExternalWMSLayer( const QString &externalLayerId ) const;

void removeTemporaryLayers();

void handlePrintErrors( const QgsLayout *layout ) const;
Expand Down
26 changes: 26 additions & 0 deletions tests/src/python/test_qgsserver_wms_getmap.py
Expand Up @@ -1457,6 +1457,32 @@ def test_wms_getmap_datasource_error(self):

self.assertTrue('ServerException' in str(r))

@unittest.skipIf(os.environ.get('TRAVIS', '') == 'true', 'Can\'t rely on external resources for continuous integration')
def test_wms_getmap_external(self):
# 1 bits
qs = "?" + "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"REQUEST": "GetMap",
"LAYERS": "EXTERNAL_WMS:landsat",
"landsat:layers": "GEBCO_LATEST",
"landsat:dpiMode": "7",
"landsat:url": "https://www.gebco.net/data_and_products/gebco_web_services/web_map_service/mapserv",
"landsat:crs": "EPSG:4326",
"landsat:styles": "default",
"landsat:format": "image/jpeg",
"landsat:bbox": "-90,-180,90,180",
"landsat:version": "1.3.0",
"STYLES": "",
"BBOX": "-90,-180,90,180",
"HEIGHT": "500",
"WIDTH": "500",
"CRS": "EPSG:4326"
}.items())])

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


if __name__ == '__main__':
unittest.main()
24 changes: 24 additions & 0 deletions tests/src/python/test_qgsserver_wms_getprint.py
Expand Up @@ -437,6 +437,30 @@ def test_wms_getprint_atlas_getProjectSettings(self):
self.assertTrue('atlasEnabled="1"' in str(r))
self.assertTrue('<PrimaryKeyAttribute>' in str(r))

@unittest.skipIf(os.environ.get('TRAVIS', '') == 'true', 'Can\'t rely on external resources for continuous integration')
def test_wms_getprint_external(self):
qs = "?" + "&".join(["%s=%s" % i for i in list({
"MAP": urllib.parse.quote(self.projectPath),
"SERVICE": "WMS",
"VERSION": "1.1.1",
"REQUEST": "GetPrint",
"TEMPLATE": "layoutA4",
"map0:EXTENT": "-90,-180,90,180",
"map0:LAYERS": "EXTERNAL_WMS:landsat",
"landsat:layers": "GEBCO_LATEST",
"landsat:dpiMode": "7",
"landsat:url": "https://www.gebco.net/data_and_products/gebco_web_services/web_map_service/mapserv",
"landsat:crs": "EPSG:4326",
"landsat:styles": "default",
"landsat:format": "image/jpeg",
"landsat:bbox": "-90,-180,90,180",
"landsat:version": "1.3.0",
"CRS": "EPSG:4326"
}.items())])

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


if __name__ == '__main__':
unittest.main()
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1e8aec4

Please sign in to comment.