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

iTowns / itowns / 10902507646

17 Sep 2024 11:56AM UTC coverage: 86.931% (-0.03%) from 86.964%
10902507646

push

github

Desplandis
release v2.44.2

2791 of 3694 branches covered (75.55%)

Branch coverage included in aggregate %.

24241 of 27402 relevant lines covered (88.46%)

1027.5 hits per line

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

92.39
/src/Source/WFSSource.js
1
import Source from 'Source/Source';
1✔
2
import URLBuilder from 'Provider/URLBuilder';
1✔
3
import CRS from 'Core/Geographic/Crs';
1✔
4

1✔
5
/**
1✔
6
 * An object defining the source of resources to get from a
1✔
7
 * [WFS](http://www.opengeospatial.org/standards/wfs) server. It inherits
1✔
8
 * from {@link Source}.
1✔
9
 *
1✔
10
 * @extends Source
1✔
11
 *
1✔
12
 * @property {boolean} isWFSSource - Used to checkout whether this source is a
1✔
13
 * WFSSource. Default is true. You should not change this, as it is used
1✔
14
 * internally for optimisation.
1✔
15
 * @property {string} typeName - The name of the feature to get, used in the
1✔
16
 * generation of the url.
1✔
17
 * @property {string} version - The version of the WFS server to request on.
1✔
18
 * Default value is '2.0.2'.
1✔
19
 * @property {Object} zoom - Object containing the minimum and maximum values of
1✔
20
 * the level, to zoom in the source.
1✔
21
 * @property {number} zoom.min - The minimum level of the source. Default value
1✔
22
 * is 0.
1✔
23
 * @property {number} zoom.max - The maximum level of the source. Default value
1✔
24
 * is 21.
1✔
25
 * @property {string} bboxDigits - The bbox digits precision used in URL
1✔
26
 * @property {Object} vendorSpecific - An object containing vendor specific
1✔
27
 * parameters. See for example a [list of these parameters for GeoServer]{@link
1✔
28
 * https://docs.geoserver.org/latest/en/user/services/wfs/vendor.html}. This
1✔
29
 * object is read simply with the `key` being the name of the parameter and
1✔
30
 * `value` being the value of the parameter. If used, this property should be
1✔
31
 * set in the constructor parameters.
1✔
32
 *
1✔
33
 * @example
1✔
34
 * // Add color layer with WFS source
1✔
35
 * // Create the source
1✔
36
 * const wfsSource = new itowns.WFSSource({
1✔
37
 *     url: 'https://data.geopf.fr/wfs/ows?',
1✔
38
 *     version: '2.0.0',
1✔
39
 *     typeName: 'BDTOPO_BDD_WLD_WGS84G:bati_remarquable',
1✔
40
 *     crs: 'EPSG:4326',
1✔
41
 *     extent: {
1✔
42
 *         west: 4.568,
1✔
43
 *         east: 5.18,
1✔
44
 *         south: 45.437,
1✔
45
 *         north: 46.03,
1✔
46
 *     },
1✔
47
 *     zoom: { min: 14, max: 14 },
1✔
48
 *     format: 'application/json',
1✔
49
 * });
1✔
50
 *
1✔
51
 * // Create the layer
1✔
52
 * const colorlayer = new itowns.ColorLayer('color_build', {
1✔
53
 *     style: {
1✔
54
 *         fill: 'red',
1✔
55
 *         fillOpacity: 0.5,
1✔
56
 *         stroke: 'white',
1✔
57
 *     },
1✔
58
 *     source: wfsSource,
1✔
59
 * });
1✔
60
 *
1✔
61
 * // Add the layer
1✔
62
 * view.addLayer(colorlayer);
1✔
63
 *
1✔
64
 * @example
1✔
65
 * // Add geometry layer with WFS source
1✔
66
 * // Create the source
1✔
67
 * const wfsSource = new itowns.WFSSource({
1✔
68
 *     url: 'https://data.geopf.fr/wfs/ows?',
1✔
69
 *     version: '2.0.0',
1✔
70
 *     typeName: 'BDTOPO_BDD_WLD_WGS84G:bati_remarquable',
1✔
71
 *     crs: 'EPSG:4326',
1✔
72
 *     extent: {
1✔
73
 *         west: 4.568,
1✔
74
 *         east: 5.18,
1✔
75
 *         south: 45.437,
1✔
76
 *         north: 46.03,
1✔
77
 *     },
1✔
78
 *     zoom: { min: 14, max: 14 },
1✔
79
 *     format: 'application/json',
1✔
80
 * });
1✔
81
 *
1✔
82
 * // Create the layer
1✔
83
 * const geometryLayer = new itowns.FeatureGeometryLayer('mesh_build', {
1✔
84
 *     style: {
1✔
85
 *         fill: {
1✔
86
 *             color: new itowns.THREE.Color(0xffcc00),
1✔
87
 *             base_altitude: (p) => p.altitude,
1✔
88
 *             extrusion_height: (p) => p.height,
1✔
89
 *         }
1✔
90
 *     },
1✔
91
 *     source: wfsSource,
1✔
92
 *     zoom: { min: 14 },
1✔
93
 * };
1✔
94
 *
1✔
95
 * // Add the layer
1✔
96
 * view.addLayer(geometryLayer);
1✔
97
 */
1✔
98
class WFSSource extends Source {
1✔
99
    /**
1✔
100
     * @param {Object} source - An object that can contain all properties of a
1✔
101
     * WFSSource and {@link Source}. `url`, `typeName` and `crs` are
1✔
102
     * mandatory.
1✔
103
     */
1✔
104
    constructor(source) {
1✔
105
        if (source.projection) {
7!
106
            console.warn('WFSSource projection parameter is deprecated, use crs instead.');
×
107
            source.crs = source.crs || source.projection;
×
108
        }
×
109
        if (!source.typeName) {
7✔
110
            throw new Error('source.typeName is required in wfs source.');
1✔
111
        }
1✔
112

6✔
113
        if (!source.crs) {
7✔
114
            throw new Error('source.crs is required in wfs source');
1✔
115
        }
1✔
116

5✔
117
        source.format = source.format || 'application/json';
7✔
118

7✔
119
        super(source);
7✔
120

7✔
121
        this.isWFSSource = true;
7✔
122
        this.typeName = source.typeName;
7✔
123
        this.version = source.version || '2.0.2';
7✔
124
        this.bboxDigits = source.bboxDigits;
7✔
125

7✔
126
        // Add ? at the end of the url if it is not already in the given URL
7✔
127
        if (!this.url.endsWith('?')) {
7✔
128
            this.url = `${this.url}?`;
5✔
129
        }
5✔
130
        this.url = `${source.url
5✔
131
        }SERVICE=WFS&REQUEST=GetFeature&typeName=${this.typeName
5✔
132
        }&VERSION=${this.version
5✔
133
        }&SRSNAME=${this.crs
5✔
134
        }&outputFormat=${this.format
5✔
135
        }&BBOX=%bbox,${this.crs}`;
5✔
136

5✔
137
        this.zoom = { min: 0, max: Infinity };
5✔
138

5✔
139
        this.vendorSpecific = source.vendorSpecific;
5✔
140
        for (const name in this.vendorSpecific) {
7✔
141
            if (Object.prototype.hasOwnProperty.call(this.vendorSpecific, name)) {
9✔
142
                this.url = `${this.url}&${name}=${this.vendorSpecific[name]}`;
9✔
143
            }
9✔
144
        }
9✔
145
    }
3✔
146

1✔
147
    handlingError(err) {
1✔
148
        if (err.response && err.response.status == 400) {
1!
149
            return err.response.text().then((text) => {
×
150
                const getCapUrl = `${this.url}SERVICE=WFS&REQUEST=GetCapabilities&VERSION=${this.version}`;
×
151
                const xml = new DOMParser().parseFromString(text, 'application/xml');
×
152
                const errorElem = xml.querySelector('Exception');
×
153
                const errorCode = errorElem.getAttribute('exceptionCode');
×
154
                const errorMessage = errorElem.querySelector('ExceptionText').textContent;
×
155
                console.error(`Source ${this.typeName}: bad request when fetching data. Server says: "${errorCode}: ${errorMessage}". \nReviewing ${getCapUrl} may help.`, err);
×
156
            });
×
157
        }
×
158
        return super.handlingError(err);
1✔
159
    }
1✔
160

1✔
161
    requestToKey(extent) {
1✔
162
        if (CRS.isTms(extent.crs)) {
8✔
163
            return super.requestToKey(extent);
7✔
164
        } else {
8✔
165
            return [extent.zoom, extent.south, extent.west];
1✔
166
        }
1✔
167
    }
8✔
168

1✔
169
    urlFromExtent(extent) {
1✔
170
        return URLBuilder.bbox(extent, this);
4✔
171
    }
4✔
172

1✔
173
    extentInsideLimit(extent) {
1✔
174
        return this.extent.intersectsExtent(extent);
4✔
175
    }
4✔
176
}
1✔
177

1✔
178
export default WFSSource;
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