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

geosolutions-it / MapStore2 / 19060241474

04 Nov 2025 06:46AM UTC coverage: 76.943% (+0.02%) from 76.92%
19060241474

Pull #11648

github

web-flow
Merge 763e0cf1e into 19e678788
Pull Request #11648: #11644: Implement dynamic request configurations

32057 of 49801 branches covered (64.37%)

201 of 222 new or added lines in 39 files covered. (90.54%)

4 existing lines in 3 files now uncovered.

39801 of 51728 relevant lines covered (76.94%)

39.94 hits per line

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

78.08
/web/client/components/map/cesium/plugins/WMTSLayer.js
1
/**
2
 * Copyright 2015, 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/cesium/Layers';
10
import * as Cesium from 'cesium';
11
import ConfigUtils from '../../../../utils/ConfigUtils';
12
import {
13
    getProxyUrl
14
} from '../../../../utils/ProxyUtils';
15
import * as WMTSUtils from '../../../../utils/WMTSUtils';
16
import { creditsToAttribution, getAuthenticationParam, getURLs } from '../../../../utils/LayersUtils';
17
import { isEqual, isObject, isArray, slice, get, head} from 'lodash';
18

19
import urlParser from 'url';
20
import { isVectorFormat } from '../../../../utils/VectorTileUtils';
21
import { getRequestConfigurationByUrl } from '../../../../utils/SecurityUtils';
22

23
function splitUrl(originalUrl) {
24
    let url = originalUrl;
24✔
25
    let queryString = "";
24✔
26
    if (originalUrl.indexOf('?') !== -1) {
24✔
27
        url = originalUrl.substring(0, originalUrl.indexOf('?') + 1);
14✔
28
        if (originalUrl.indexOf('%') !== -1) {
14!
29
            url = decodeURIComponent(url);
14✔
30
        }
31
        queryString = originalUrl.substring(originalUrl.indexOf('?') + 1);
14✔
32
    }
33
    return {url, queryString};
24✔
34
}
35

36
function WMTSProxy(proxy) {
37
    this.proxy = proxy;
×
38
}
39

40
const isValidTile = (tileMatrixSet) => (x, y, level) =>
22✔
41
    tileMatrixSet && tileMatrixSet[level] && !tileMatrixSet[level].ranges ||
6✔
42
    (x <= parseInt(get(tileMatrixSet[level], "ranges.cols.max"), 10) &&
43
    x >= parseInt(get(tileMatrixSet[level], "ranges.cols.min"), 10) &&
44
    y <= parseInt(get(tileMatrixSet[level], "ranges.rows.max"), 10) &&
45
    y >= parseInt(get(tileMatrixSet[level], "ranges.rows.min"), 10));
46

47

48
WMTSProxy.prototype.getURL = function(resource) {
1✔
49
    let {url, queryString} = splitUrl(resource);
×
50
    return getProxyUrl() + encodeURIComponent(url + queryString);
×
51
};
52

53
function NoProxy() {
54
}
55

56
NoProxy.prototype.getURL = function(resource) {
1✔
57
    let {url, queryString} = splitUrl(resource);
24✔
58
    return url + queryString;
24✔
59
};
60
function getMatrixIds(matrix = [], setId) {
×
61
    return ((isObject(matrix) && matrix[setId]) || isArray(matrix) && matrix || []).map((el) => el.identifier);
42!
62
}
63

64
function getDefaultMatrixId(options) {
65
    let matrixIds = new Array(30);
×
66
    for (let z = 0; z < 30; ++z) {
×
67
        // generate matrixIds arrays for this WMTS
68
        matrixIds[z] = options.tileMatrixPrefix + z;
×
69
    }
70
    return matrixIds;
×
71
}
72

73
const limitMatrix = (matrix, len) => {
1✔
74
    if (matrix.length > len) {
42!
75
        return slice(matrix, 0, len);
×
76
    }
77
    if (matrix.length < len) {
42!
78
        return matrix.concat(new Array(len - matrix.length));
×
79
    }
80
    return matrix;
42✔
81
};
82

83
const getTilingSchema = (srs) => {
1✔
84
    if (srs.indexOf("EPSG:4326") >= 0) {
22✔
85
        return new Cesium.GeographicTilingScheme();
2✔
86
    } else if (srs.indexOf("EPSG:3857") >= 0) {
20!
87
        return new Cesium.WebMercatorTilingScheme();
20✔
88
    }
89
    return null;
×
90
};
91

92
const getMatrixOptions = (options, srs) => {
1✔
93
    const tileMatrixSet = WMTSUtils.getTileMatrixSet(options.tileMatrixSet, srs, options.allowedSRS, options.matrixIds);
42✔
94
    const matrixIds = limitMatrix(options.matrixIds && getMatrixIds(options.matrixIds, tileMatrixSet) || getDefaultMatrixId(options));
42!
95
    return {tileMatrixSet, matrixIds};
42✔
96
};
97

98
function wmtsToCesiumOptions(_options) {
99
    const options = WMTSUtils.parseTileMatrixSetOption(_options);
22✔
100
    let srs = 'EPSG:4326';
22✔
101
    let { tileMatrixSet: tileMatrixSetID, matrixIds} = getMatrixOptions(options, srs);
22✔
102
    if (matrixIds.length === 0) {
22✔
103
        srs = 'EPSG:3857';
20✔
104
        const matrixOptions = getMatrixOptions(options, srs);
20✔
105
        tileMatrixSetID = matrixOptions.tileMatrixSet;
20✔
106
        matrixIds = matrixOptions.matrixIds;
20✔
107
    }
108
    // NOTE: can we use opacity to manage visibility?
109
    // var opacity = options.opacity !== undefined ? options.opacity : 1;
110
    let proxyUrl = ConfigUtils.getProxyUrl({});
22✔
111
    let proxy;
112
    if (proxyUrl) {
22!
113
        proxy = options.forceProxy;
22✔
114
    }
115
    const isValid = isValidTile(options.matrixIds && options.matrixIds[tileMatrixSetID]);
22✔
116
    const queryParametersString = urlParser.format({ query: {...getAuthenticationParam(options)}});
22✔
117
    const cr = options.credits;
22✔
118
    const credit = cr ? new Cesium.Credit(creditsToAttribution(cr)) : '';
22✔
119

120
    let headersOpts;
121
    if (options.security && options.url) {
22!
NEW
122
        const urlToCheck = isArray(options.url) ? options.url[0] : options.url;
×
NEW
123
        const requestConfig = getRequestConfigurationByUrl(urlToCheck, null, options.security?.sourceId);
×
124

NEW
125
        if (requestConfig.headers) {
×
NEW
126
            headersOpts = { headers: requestConfig.headers };
×
127
        }
128
    }
129
    return Object.assign({
22✔
130
        // TODO: multi-domain support, if use {s} switches to RESTFul mode
131
        url: new Cesium.Resource({
132
            url: head(getURLs(isArray(options.url) ? options.url : [options.url], queryParametersString)),
22!
133
            proxy: proxy && new WMTSProxy(proxy) || new NoProxy(),
44!
134
            ...(headersOpts)
135
        }),
136
        // set image format to png if vector to avoid errors while switching between map type
137
        format: isVectorFormat(options.format) && 'image/png' || options.format || 'image/png',
44!
138
        isValid,
139
        // tileDiscardPolicy: {
140
        //    isReady: () => true,
141
        //    shouldDiscardImage: ({x, y, level}) => !isValid(x, y, level)
142
        // }, // not supported yet
143
        credit,
144
        layer: options.name,
145
        style: options.style || "",
44✔
146
        tileMatrixLabels: matrixIds,
147
        tilingScheme: getTilingSchema(srs, options.matrixIds[tileMatrixSetID]),
148
        enablePickFeatures: false,
149
        tileWidth: options.tileWidth || options.tileSize || 256,
66✔
150
        tileHeight: options.tileHeight || options.tileSize || 256,
66✔
151
        tileMatrixSetID: tileMatrixSetID,
152
        maximumLevel: 30,
153
        parameters: {...getAuthenticationParam(options)}
154
    });
155
}
156

157
const createLayer = options => {
1✔
158
    let layer;
159
    const cesiumOptions = wmtsToCesiumOptions(options);
22✔
160
    layer = new Cesium.WebMapTileServiceImageryProvider(cesiumOptions);
22✔
161
    const orig = layer.requestImage;
22✔
162
    layer.requestImage = (x, y, level) => cesiumOptions.isValid(x, y, level) ? orig.bind(layer)( x, y, level) : new Promise( () => undefined);
22✔
163
    layer.updateParams = (params) => {
22✔
164
        const newOptions = Object.assign({}, options, {
×
165
            params: Object.assign({}, options.params || {}, params)
×
166
        });
167
        return createLayer(newOptions);
×
168
    };
169
    return layer;
22✔
170
};
171

172
const updateLayer = (layer, newOptions, oldOptions) => {
1✔
173
    if (newOptions.securityToken !== oldOptions.securityToken
17✔
174
    || oldOptions.format !== newOptions.format
175
    || !isEqual(oldOptions.security, newOptions.security)
176
    || oldOptions.credits !== newOptions.credits || newOptions.forceProxy !== oldOptions.forceProxy) {
177
        return createLayer(newOptions);
15✔
178
    }
179
    return null;
2✔
180
};
181

182
Layers.registerType('wmts', {create: createLayer, update: updateLayer});
1✔
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