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

geosolutions-it / MapStore2 / 19933858499

04 Dec 2025 01:54PM UTC coverage: 76.636% (-0.03%) from 76.661%
19933858499

Pull #11648

github

web-flow
Update User Guide - Itinerary plugin (#11768)

* add_11664

* Update docs/user-guide/itinerary.md

Co-authored-by: Suren <dsuren1@gmail.com>

* Update docs/user-guide/itinerary.md

Co-authored-by: Suren <dsuren1@gmail.com>

* Update docs/user-guide/itinerary.md

Co-authored-by: Suren <dsuren1@gmail.com>

* Update docs/user-guide/itinerary.md

Co-authored-by: Suren <dsuren1@gmail.com>

---------

Co-authored-by: Suren <dsuren1@gmail.com>
Pull Request #11648: #11644: Implement dynamic request configurations

32316 of 50296 branches covered (64.25%)

132 of 155 new or added lines in 40 files covered. (85.16%)

283 existing lines in 32 files now uncovered.

40207 of 52465 relevant lines covered (76.64%)

37.89 hits per line

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

79.09
/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 axios from '../../../../libs/ajax';
15
import CoordinatesUtils from '../../../../utils/CoordinatesUtils';
16
import { getProjection } from '../../../../utils/ProjectionUtils';
17
import { getConfigProp } from '../../../../utils/ConfigUtils';
18

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

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

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

31
import { isVectorFormat } from '../../../../utils/VectorTileUtils';
32
import { isValidResponse } from '../../../../utils/WMSUtils';
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) {
50✔
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();
51✔
40
    let newSrc = proxySource(options.forceProxy, src);
50✔
41

42
    if (typeof window.btoa === 'function' && src.length >= (options.maxLengthUrl || getConfigProp('miscSettings')?.maxURLLength || Infinity)) {
50✔
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) {
45✔
73
            axios.get(newSrc, {
4✔
74
                headers,
75
                responseType: 'blob'
76
            }).then(response => {
77
                if (isValidResponse(response)) {
4!
78
                    image.getImage().src = URL.createObjectURL(response.data);
4✔
79
                } else {
80
                    // #10701 this is needed to trigger the imageloaderror event
81
                    // in ol otherwise this event is not triggered if you assign
82
                    // the xml content of the exception to the src attribute
83
                    image.getImage().src = null;
×
84
                    console.error("error: " + response.data);
×
85
                }
86
            }).catch(e => {
87
                image.getImage().src = null;
4✔
88
                console.error(e);
4✔
89
            });
90
        } else {
91
            img.src = newSrc;
41✔
92
        }
93
    }
94
};
95

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

112
    if (options.singleTile && !vectorFormat) {
50✔
113
        return new ImageLayer({
8✔
114
            msId: options.id,
115
            opacity: options.opacity !== undefined ? options.opacity : 1,
8✔
116
            visible: options.visibility !== false,
117
            zIndex: options.zIndex,
118
            minResolution: options.minResolution,
119
            maxResolution: options.maxResolution,
120
            source: new ImageWMS({
121
                url: urls[0],
122
                crossOrigin: options.crossOrigin,
123
                attributions: toOLAttributions(options.credits),
124
                params: queryParameters,
125
                ratio: options.ratio || 1,
15✔
126
                imageLoadFunction: loadFunction(options, headers)
127
            })
128
        });
129
    }
130
    const sourceOptions = {
42✔
131
        attributions: toOLAttributions(options.credits),
132
        urls: urls,
133
        crossOrigin: options.crossOrigin,
134
        params: queryParameters,
135
        tileGrid: generateTileGrid(options, map),
136
        tileLoadFunction: loadFunction(options, headers)
137
    };
138

139
    const wmsSource = new TileWMS({ ...sourceOptions });
42✔
140
    const layerConfig = {
42✔
141
        msId: options.id,
142
        opacity: options.opacity !== undefined ? options.opacity : 1,
42✔
143
        visible: options.visibility !== false,
144
        zIndex: options.zIndex,
145
        minResolution: options.minResolution,
146
        maxResolution: options.maxResolution
147
    };
148
    let layer;
149
    if (vectorFormat) {
42✔
150
        layer = new VectorTileLayer({
5✔
151
            ...layerConfig,
152
            source: new VectorTileSource({
153
                ...sourceOptions,
154
                format: new OL_VECTOR_FORMATS[options.format]({
155
                    layerName: '_layer_'
156
                }),
157
                tileUrlFunction: (tileCoord, pixelRatio, projection) => wmsSource.tileUrlFunction(tileCoord, pixelRatio, projection)
×
158
            })
159
        });
160
    } else {
161

162
        layer = new TileLayer({
37✔
163
            ...layerConfig,
164
            source: wmsSource
165
        });
166
    }
167
    layer.set('map', map);
42✔
168
    if (vectorFormat) {
42✔
169
        layer.set('wmsSource', wmsSource);
5✔
170
        if (options.vectorStyle) {
5✔
171
            applyStyle(options.vectorStyle, layer, map);
2✔
172
        }
173
    }
174
    return layer;
42✔
175
};
176

177
const mustCreateNewLayer = (oldOptions, newOptions) => {
1✔
178
    return (oldOptions.singleTile !== newOptions.singleTile
17✔
179
        || oldOptions.securityToken !== newOptions.securityToken
180
        || oldOptions.ratio !== newOptions.ratio
181
        // 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)
182
        || oldOptions.credits !== newOptions.credits && !newOptions.credits
183
        || isVectorFormat(oldOptions.format) !== isVectorFormat(newOptions.format)
184
        || isVectorFormat(oldOptions.format) && isVectorFormat(newOptions.format) && oldOptions.format !== newOptions.format
185
        || oldOptions.localizedLayerStyles !== newOptions.localizedLayerStyles
186
        || oldOptions.tileSize !== newOptions.tileSize
187
        || oldOptions.forceProxy !== newOptions.forceProxy
188
        || oldOptions.tileGridStrategy !== newOptions.tileGridStrategy
189
        || !isEqual(oldOptions.tileGrids, newOptions.tileGrids)
190
    );
191
};
192

193
Layers.registerType('wms', {
1✔
194
    create: createLayer,
195
    update: (layer, newOptions, oldOptions, map) => {
196
        const newIsVector = isVectorFormat(newOptions.format);
17✔
197

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

208
        const wmsSource = layer.get('wmsSource') || layer.getSource();
11✔
209
        const vectorSource = newIsVector ? layer.getSource() : null;
11!
210

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

226
        if (oldOptions.credits !== newOptions.credits && newOptions.credits) {
11✔
227
            wmsSource.setAttributions(toOLAttributions(newOptions.credits));
3✔
228
            needsRefresh = true;
3✔
229
        }
230

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

257
            needsRefresh = needsRefresh || changed;
11✔
258
        }
259

260
        if (oldOptions.minResolution !== newOptions.minResolution) {
11✔
261
            layer.setMinResolution(newOptions.minResolution === undefined ? 0 : newOptions.minResolution);
1!
262
        }
263
        if (oldOptions.maxResolution !== newOptions.maxResolution) {
11✔
264
            layer.setMaxResolution(newOptions.maxResolution === undefined ? Infinity : newOptions.maxResolution);
1!
265
        }
266
        if (!isEqual(oldOptions.security, newOptions.security)) {
11!
UNCOV
267
            const urls = getWMSURLs(isArray(newOptions.url) ? newOptions.url : [newOptions.url]);
×
UNCOV
268
            const headers = getAuthenticationHeaders(urls[0], newOptions.securityToken, newOptions.security);
×
269
            wmsSource.setTileLoadFunction(loadFunction(newOptions, headers));
×
UNCOV
270
            wmsSource.refresh();
×
271
        }
272
        if (needsRefresh) {
11✔
273
            // forces tile cache drop
274
            // this prevents old cached tiles at lower zoom levels to be
275
            // rendered during new params load
276
            wmsSource?.tileCache?.pruneExceptNewestZ?.();
8✔
277
            if (vectorSource) {
8!
UNCOV
278
                vectorSource.clear();
×
UNCOV
279
                vectorSource.refresh();
×
280
            }
281

282
            if (changed) {
8✔
283
                const params = Object.assign(newParams, addAuthenticationToSLD(optionsToVendorParams(newOptions) || {}, newOptions));
5✔
284

285
                wmsSource.updateParams(Object.assign(params, Object.keys(oldParams || {}).reduce((previous, key) => {
5!
286
                    return !isNil(params[key]) ? previous : Object.assign(previous, {
45✔
287
                        [key]: undefined
288
                    });
289
                }, {})));
290
            }
291
        }
292
        return null;
11✔
293
    }
294
});
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