• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

geosolutions-it / MapStore2 / 14306534492

07 Apr 2025 10:10AM UTC coverage: 76.703% (-0.007%) from 76.71%
14306534492

Pull #10974

github

web-flow
Merge 557674f25 into 2c8a1d2bf
Pull Request #10974: [c027-2024.01.xx] #10970: Add configuration support to open resource in target from homepage

30692 of 48031 branches covered (63.9%)

8 of 22 new or added lines in 7 files covered. (36.36%)

31 existing lines in 7 files now uncovered.

38336 of 49980 relevant lines covered (76.7%)

32.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.55
/web/client/components/map/openlayers/plugins/WMSLayer.js
1
/*
2
 * Copyright 2017, GeoSolutions Sas.
3
 * All rights reserved.
4
 *
5
 * This source code is licensed under the BSD-style license found in the
6
 * LICENSE file in the root directory of this source tree.
7
 */
8

9
import Layers from '../../../../utils/openlayers/Layers';
10
import isNil from 'lodash/isNil';
11
import isEqual from 'lodash/isEqual';
12
import union from 'lodash/union';
13
import isArray from 'lodash/isArray';
14
import assign from 'object-assign';
15
import axios from '../../../../libs/ajax';
16
import CoordinatesUtils from '../../../../utils/CoordinatesUtils';
17
import { getProjection } from '../../../../utils/ProjectionUtils';
18
import { getConfigProp } from '../../../../utils/ConfigUtils';
19

20
import {optionsToVendorParams} from '../../../../utils/VendorParamsUtils';
21
import {addAuthenticationToSLD, addAuthenticationParameter, getAuthenticationHeaders} from '../../../../utils/SecurityUtils';
22

23
import ImageLayer from 'ol/layer/Image';
24
import ImageWMS from 'ol/source/ImageWMS';
25
import {get} from 'ol/proj';
26
import TileLayer from 'ol/layer/Tile';
27
import TileWMS from 'ol/source/TileWMS';
28

29
import VectorTileSource from 'ol/source/VectorTile';
30
import VectorTileLayer from 'ol/layer/VectorTile';
31

32
import { isVectorFormat } from '../../../../utils/VectorTileUtils';
33
import { OL_VECTOR_FORMATS, applyStyle } from '../../../../utils/openlayers/VectorTileUtils';
34

35
import { proxySource, getWMSURLs, wmsToOpenlayersOptions, toOLAttributions, generateTileGrid } from '../../../../utils/openlayers/WMSUtils';
36

37
const loadFunction = (options, headers) => function(image, src) {
48✔
38
    // fixes #3916, see https://gis.stackexchange.com/questions/175057/openlayers-3-wms-styling-using-sld-body-and-post-request
39
    let img = image.getImage();
10✔
40
    let newSrc = proxySource(options.forceProxy, src);
9✔
41

42
    if (typeof window.btoa === 'function' && src.length >= (options.maxLengthUrl || getConfigProp('miscSettings')?.maxURLLength || Infinity)) {
9✔
43
        // GET ALL THE PARAMETERS OUT OF THE SOURCE URL**
44
        let [url, ...dataEntries] = src.split("&");
5✔
45
        url = proxySource(options.forceProxy, url);
5✔
46

47
        // SET THE PROPER HEADERS AND FINALLY SEND THE PARAMETERS
48
        axios.post(url, "&" + dataEntries.join("&"), {
5✔
49
            headers: {
50
                "Content-type": "application/x-www-form-urlencoded;charset=utf-8",
51
                ...headers
52
            },
53
            responseType: 'arraybuffer'
54
        }).then(response => {
55
            if (response.status === 200) {
5!
56
                const uInt8Array = new Uint8Array(response.data);
5✔
57
                let i = uInt8Array.length;
5✔
58
                const binaryString = new Array(i);
5✔
59
                while (i--) {
5✔
60
                    binaryString[i] = String.fromCharCode(uInt8Array[i]);
×
61
                }
62
                const dataImg = binaryString.join('');
5✔
63
                const type = response.headers['content-type'];
5✔
64
                if (type.indexOf('image') === 0) {
5!
65
                    img.src = 'data:' + type + ';base64,' + window.btoa(dataImg);
5✔
66
                }
67
            }
68
        }).catch(e => {
69
            console.error(e);
×
70
        });
71
    } else {
72
        if (headers) {
4!
73
            axios.get(newSrc, {
4✔
74
                headers,
75
                responseType: 'blob'
76
            }).then(response => {
77
                if (response.status === 200 && response.data) {
4!
78
                    image.getImage().src = URL.createObjectURL(response.data);
4✔
79
                } else {
80
                    console.error("Status code: " + response.status);
×
81
                }
82
            }).catch(e => {
83
                console.error(e);
4✔
84
            });
85
        } else {
UNCOV
86
            img.src = newSrc;
×
87
        }
88
    }
89
};
90

91
const createLayer = (options, map, mapId) => {
1✔
92
    // the useForElevation in wms types will be deprecated
93
    // as support for existing configuration
94
    // we can use this fallback
95
    if (options.useForElevation) {
52✔
96
        return Layers.createLayer('elevation', {
4✔
97
            ...options,
98
            provider: 'wms'
99
        }, map, mapId);
100
    }
101
    const urls = getWMSURLs(isArray(options.url) ? options.url : [options.url]);
48✔
102
    const queryParameters = wmsToOpenlayersOptions(options) || {};
48!
103
    urls.forEach(url => addAuthenticationParameter(url, queryParameters, options.securityToken));
50✔
104
    const headers = getAuthenticationHeaders(urls[0], options.securityToken);
48✔
105
    const vectorFormat = isVectorFormat(options.format);
48✔
106

107
    if (options.singleTile && !vectorFormat) {
48✔
108
        return new ImageLayer({
7✔
109
            msId: options.id,
110
            opacity: options.opacity !== undefined ? options.opacity : 1,
7✔
111
            visible: options.visibility !== false,
112
            zIndex: options.zIndex,
113
            minResolution: options.minResolution,
114
            maxResolution: options.maxResolution,
115
            source: new ImageWMS({
116
                url: urls[0],
117
                crossOrigin: options.crossOrigin,
118
                attributions: toOLAttributions(options.credits),
119
                params: queryParameters,
120
                ratio: options.ratio || 1,
13✔
121
                imageLoadFunction: loadFunction(options, headers)
122
            })
123
        });
124
    }
125
    const sourceOptions = {
41✔
126
        attributions: toOLAttributions(options.credits),
127
        urls: urls,
128
        crossOrigin: options.crossOrigin,
129
        params: queryParameters,
130
        tileGrid: generateTileGrid(options, map),
131
        tileLoadFunction: loadFunction(options, headers)
132
    };
133
    const wmsSource = new TileWMS({ ...sourceOptions });
41✔
134
    const layerConfig = {
41✔
135
        msId: options.id,
136
        opacity: options.opacity !== undefined ? options.opacity : 1,
41✔
137
        visible: options.visibility !== false,
138
        zIndex: options.zIndex,
139
        minResolution: options.minResolution,
140
        maxResolution: options.maxResolution
141
    };
142
    let layer;
143
    if (vectorFormat) {
41✔
144
        layer = new VectorTileLayer({
5✔
145
            ...layerConfig,
146
            source: new VectorTileSource({
147
                ...sourceOptions,
148
                format: new OL_VECTOR_FORMATS[options.format]({
149
                    layerName: '_layer_'
150
                }),
151
                tileUrlFunction: (tileCoord, pixelRatio, projection) => wmsSource.tileUrlFunction(tileCoord, pixelRatio, projection)
×
152
            })
153
        });
154
    } else {
155

156
        layer = new TileLayer({
36✔
157
            ...layerConfig,
158
            source: wmsSource
159
        });
160
    }
161
    layer.set('map', map);
41✔
162
    if (vectorFormat) {
41✔
163
        layer.set('wmsSource', wmsSource);
5✔
164
        if (options.vectorStyle) {
5✔
165
            applyStyle(options.vectorStyle, layer, map);
2✔
166
        }
167
    }
168
    return layer;
41✔
169
};
170

171
const mustCreateNewLayer = (oldOptions, newOptions) => {
1✔
172
    return (oldOptions.singleTile !== newOptions.singleTile
17✔
173
        || oldOptions.securityToken !== newOptions.securityToken
174
        || oldOptions.ratio !== newOptions.ratio
175
        // no way to remove attribution when credits are removed, so have re-create the layer is needed. Seems to be solved in OL v5.3.0, due to the ol commit 9b8232f65b391d5d381d7a99a7cd070fc36696e9 (https://github.com/openlayers/openlayers/pull/7329)
176
        || oldOptions.credits !== newOptions.credits && !newOptions.credits
177
        || isVectorFormat(oldOptions.format) !== isVectorFormat(newOptions.format)
178
        || isVectorFormat(oldOptions.format) && isVectorFormat(newOptions.format) && oldOptions.format !== newOptions.format
179
        || oldOptions.localizedLayerStyles !== newOptions.localizedLayerStyles
180
        || oldOptions.tileSize !== newOptions.tileSize
181
        || oldOptions.forceProxy !== newOptions.forceProxy
182
        || oldOptions.url !== newOptions.url
183
        || oldOptions.tileGridStrategy !== newOptions.tileGridStrategy
184
        || !isEqual(oldOptions.tileGrids, newOptions.tileGrids)
185
    );
186
};
187

188
Layers.registerType('wms', {
1✔
189
    create: createLayer,
190
    update: (layer, newOptions, oldOptions, map) => {
191
        const newIsVector = isVectorFormat(newOptions.format);
17✔
192

193
        if (mustCreateNewLayer(oldOptions, newOptions)) {
17✔
194
            // TODO: do we need to clean anything before re-creating stuff from scratch?
195
            return createLayer(newOptions, map);
6✔
196
        }
197
        let needsRefresh = false;
11✔
198
        if (newIsVector && newOptions.vectorStyle && !isEqual(newOptions.vectorStyle, oldOptions.vectorStyle || {})) {
11!
199
            applyStyle(newOptions.vectorStyle, layer, map);
×
200
            needsRefresh = true;
×
201
        }
202

203
        const wmsSource = layer.get('wmsSource') || layer.getSource();
11✔
204
        const vectorSource = newIsVector ? layer.getSource() : null;
11!
205

206
        if (oldOptions.srs !== newOptions.srs) {
11!
207
            const normalizedSrs = CoordinatesUtils.normalizeSRS(newOptions.srs, newOptions.allowedSRS);
×
208
            const extent = get(normalizedSrs).getExtent() || getProjection(normalizedSrs).extent;
×
209
            if (newOptions.singleTile && !newIsVector) {
×
210
                layer.setExtent(extent);
×
211
            } else {
212
                const tileGrid = generateTileGrid(newOptions, map);
×
213
                wmsSource.tileGrid = tileGrid;
×
214
                if (vectorSource) {
×
215
                    vectorSource.tileGrid = tileGrid;
×
216
                }
217
            }
218
            needsRefresh = true;
×
219
        }
220

221
        if (oldOptions.credits !== newOptions.credits && newOptions.credits) {
11✔
222
            wmsSource.setAttributions(toOLAttributions(newOptions.credits));
3✔
223
            needsRefresh = true;
3✔
224
        }
225

226
        let changed = false;
11✔
227
        let oldParams;
228
        let newParams;
229
        if (oldOptions && wmsSource && wmsSource.updateParams) {
11!
230
            if (oldOptions.params && newOptions.params) {
11✔
231
                changed = union(
4✔
232
                    Object.keys(oldOptions.params),
233
                    Object.keys(newOptions.params)
234
                ).reduce((found, param) => {
235
                    if (newOptions.params[param] !== oldOptions.params[param]) {
5✔
236
                        return true;
3✔
237
                    }
238
                    return found;
2✔
239
                }, false);
240
            } else if ((!oldOptions.params && newOptions.params) || (oldOptions.params && !newOptions.params)) {
7!
241
                changed = true;
×
242
            }
243
            oldParams = wmsToOpenlayersOptions(oldOptions);
11✔
244
            newParams = wmsToOpenlayersOptions(newOptions);
11✔
245
            changed = changed || ["LAYERS", "STYLES", "FORMAT", "TRANSPARENT", "TILED", "VERSION", "_v_", "CQL_FILTER", "SLD", "VIEWPARAMS"].reduce((found, param) => {
11✔
246
                if (oldParams[param] !== newParams[param]) {
80✔
247
                    return true;
2✔
248
                }
249
                return found;
78✔
250
            }, false);
251

252
            needsRefresh = needsRefresh || changed;
11✔
253
        }
254

255
        if (oldOptions.minResolution !== newOptions.minResolution) {
11✔
256
            layer.setMinResolution(newOptions.minResolution === undefined ? 0 : newOptions.minResolution);
1!
257
        }
258
        if (oldOptions.maxResolution !== newOptions.maxResolution) {
11✔
259
            layer.setMaxResolution(newOptions.maxResolution === undefined ? Infinity : newOptions.maxResolution);
1!
260
        }
261
        if (needsRefresh) {
11✔
262
            // forces tile cache drop
263
            // this prevents old cached tiles at lower zoom levels to be
264
            // rendered during new params load
265
            wmsSource?.tileCache?.pruneExceptNewestZ?.();
8✔
266
            if (vectorSource) {
8!
267
                vectorSource.clear();
×
268
                vectorSource.refresh();
×
269
            }
270

271
            if (changed) {
8✔
272
                const params = assign(newParams, addAuthenticationToSLD(optionsToVendorParams(newOptions) || {}, newOptions));
5✔
273

274
                wmsSource.updateParams(assign(params, Object.keys(oldParams || {}).reduce((previous, key) => {
5!
275
                    return !isNil(params[key]) ? previous : assign(previous, {
45✔
276
                        [key]: undefined
277
                    });
278
                }, {})));
279
            }
280
        }
281
        return null;
11✔
282
    }
283
});
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc