Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Branch master (5c2c02)
by Sebastian
03:02
created

plugins/pageview/tx_dlf_altoparser.js   D

Complexity

Total Complexity 66
Complexity/F 3.67

Size

Lines of Code 344
Function Count 18

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 0
c 0
b 0
f 0
nc 51200
dl 0
loc 344
rs 4.4126
wmc 66
mnd 4
bc 37
fnc 18
bpm 2.0555
cpm 3.6666
noi 14

10 Functions

Rating   Name   Duplication   Size   Complexity  
A dlfAltoParser.parseXML_ 0 6 3
A dlfAltoParser.parseTextBlockFeatures_ 0 20 3
A dlfAltoParser.parseFeatures 0 70 2
C dlfAltoParser.parseGeometry_ 0 29 7
B dlfAltoParser.parseContentFeatures_ 0 29 6
A dlfAltoParser.parseTextLineFeatures_ 0 20 3
A dlfAltoParser.generateId_ 0 4 2
A dlfAltoParser.parsePrintSpaceFeature_ 0 7 2
A dlfAltoParser.parseFeatureWithGeometry_ 0 21 1
D dlfAltoParser.parseAltoFeature_ 0 45 17

How to fix   Complexity   

Complexity

Complex classes like plugins/pageview/tx_dlf_altoparser.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/**
2
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
3
 *
4
 * This file is part of the Kitodo and TYPO3 projects.
5
 *
6
 * @license GNU General Public License version 3 or later.
7
 * For the full copyright and license information, please read the
8
 * LICENSE.txt file that was distributed with this source code.
9
 */
10
11
/**
12
 * @constructor
13
 * @param {Object=} opt_imageObj
14
 * @param {number=} opt_width
15
 * @param {number=} opt_height
16
 * @param {number=} opt_offset
17
 */
18
var dlfAltoParser = function(opt_imageObj, opt_width, opt_height, opt_offset) {
19
20
    /**
21
     * @type {Object|undefined}
22
     * @private
23
     */
24
    this.image_ = dlfUtils.exists(opt_imageObj) ? opt_imageObj : undefined;
0 ignored issues
show
Bug introduced by
The variable dlfUtils seems to be never declared. If this is a global, consider adding a /** global: dlfUtils */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
25
26
    /**
27
     * @type {number|undefined}
28
     * @private
29
     */
30
    this.width_ = dlfUtils.exists(opt_width) ? opt_width : undefined;
31
32
    /**
33
     * @type {number|undefined}
34
     * @private
35
     */
36
    this.height_ = dlfUtils.exists(opt_height) ? opt_height : undefined;
37
38
    /**
39
     * @type {number|undefined}
40
     * @private
41
     */
42
    this.offset_ = dlfUtils.exists(opt_offset) ? opt_offset : undefined;
43
};
44
45
/**
46
 * @param {number} width
47
 * @param {number} height
48
 * @param {number} hpos
49
 * @param {number} vpos
50
 * @private
51
 */
52
dlfAltoParser.prototype.generateId_ = function(width, height, hpos, vpos) {
53
    var heigt_ = isNaN(height) ? '0' : height;
54
    return '' + width + '_' + heigt_ + '_' + hpos + '_' + vpos;
55
};
56
57
/**
58
 * Parse from an alto element a OpenLayers feature object. This function does reproduce the parsing hierarchy of this parser.
59
 * @param {Element} node
60
 * @return {ol.Feature}
61
 * @private
62
 */
63
dlfAltoParser.prototype.parseAltoFeature_ = function(node) {
64
    var type = node.nodeName.toLowerCase(),
65
        feature;
66
67
    // first parse the node as feature
68
    if (type === 'printspace' || type === 'textblock' || type === 'textline' || node.hasAttribute('WIDTH')) {
69
        feature = this.parseFeatureWithGeometry_(node);
70
    } else {
71
        var feature = new ol.Feature();
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable feature already seems to be declared on line 65. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
Bug introduced by
The variable ol seems to be never declared. If this is a global, consider adding a /** global: ol */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
72
        feature.setProperties({'type': node.nodeName.toLowerCase()});
73
    };
74
75
    // parse child nodes
76
    if (type === 'page') {
77
        // try to update the general width and height for rescaling
78
        var width = feature.get('width'),
79
            height = feature.get('height');
80
81
        if ((dlfUtils.exists(width) && dlfUtils.exists(height)) && (!dlfUtils.exists(this.width_) && !dlfUtils.exists(this.width_))) {
0 ignored issues
show
Bug introduced by
The variable dlfUtils seems to be never declared. If this is a global, consider adding a /** global: dlfUtils */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
82
            this.width_ = width;
83
            this.height_ = height;
84
        }
85
86
        // add child features
87
        feature.setProperties({'printspace': this.parsePrintSpaceFeature_(node)});
88
    } else if (type === 'printspace') {
89
        // try to update the general width and height for rescaling
90
        var width = feature.get('width'),
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable width already seems to be declared on line 78. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
91
            height = feature.get('height');
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable height already seems to be declared on line 79. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
92
93
        if ((dlfUtils.exists(width) && dlfUtils.exists(height)) && (!dlfUtils.exists(this.width_) && !dlfUtils.exists(this.width_))) {
94
            this.width_ = width;
95
            this.height_ = height;
96
        }
97
98
        // add child features
99
        feature.setProperties({'textblocks': this.parseTextBlockFeatures_(node)});
100
    } else if (type === 'textblock') {
101
        feature.setProperties({'textlines': this.parseTextLineFeatures_(node)});
102
    } else if (type === 'textline') {
103
        feature.setProperties({'content': this.parseContentFeatures_(node)});
104
    }
105
106
    return feature;
107
};
108
109
/**
110
 * @param {XMLDocument|string} document
111
 * @return {Array.<ol.Feature>}
112
 */
113
dlfAltoParser.prototype.parseFeatures = function(document) {
114
    var parsedDoc = this.parseXML_(document),
115
        pageFeatures = [],
116
        pageElements = $(parsedDoc).find('Page');
117
118
    for (var i = 0; i < pageElements.length; i++) {
119
        // parse page feature
120
        var feature = this.parseAltoFeature_(pageElements[i]);
121
122
        /**
123
         * Attach function for a better access of of string elements
124
         * @return {Array}
125
         */
126
        feature.getStringFeatures = function() {
127
            var textblockFeatures = this.get('printspace').get('textblocks'),
128
                stringFeatures = [];
129
130
            textblockFeatures.forEach(function(textblock) {
131
132
                if (textblock !== undefined && textblock.get('textlines').length > 0) {
133
134
                    textblock.get('textlines').forEach(function(textline) {
135
136
                        if (textline !== undefined && textline.get('content').length > 0) {
137
138
                            textline.get('content').forEach(function(content) {
139
140
                                if (content !== undefined && content.get('type') === 'string') {
141
                                    stringFeatures.push(content);
142
                                }
143
144
                            });
145
                        }
146
147
                    });
148
149
                }
150
151
            });
152
153
            return stringFeatures;
154
        };
155
156
        /**
157
         * Add function for getting the text blocks
158
         * @return {Array}
159
         */
160
        feature.getTextblocks = function() {
161
            if (this.get('printspace') !== undefined && this.get('printspace').get('textblocks'))
162
                return this.get('printspace').get('textblocks')
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
163
            return [];
164
        };
165
166
        /**
167
         * Adding function for getting the textline
168
         * @return {Array}
169
         */
170
        feature.getTextlines = function() {
171
            var textlines = [];
172
            this.getTextblocks().forEach(function(textblock) {
173
                textlines = textlines.concat(textblock.get('textlines'));
174
            });
175
            return textlines;
176
        };
177
178
        pageFeatures.push(feature);
179
    };
180
181
    return pageFeatures;
182
};
183
184
/**
185
 * Parse from an alto element a OpenLayers feature object
186
 * @param {Element} node
187
 * @return {ol.Feature}
188
 * @private
189
 */
190
dlfAltoParser.prototype.parseFeatureWithGeometry_ = function(node) {
191
    var geometry = this.parseGeometry_(node),
192
        width = parseInt(node.getAttribute("WIDTH")),
193
        height = parseInt(node.getAttribute("HEIGHT")),
194
        hpos = parseInt(node.getAttribute("HPOS")),
195
        vpos = parseInt(node.getAttribute("VPOS")),
196
        type = node.nodeName.toLowerCase(),
197
        id = this.generateId_(width, height, hpos, vpos),
198
        feature = new ol.Feature(geometry);
0 ignored issues
show
Bug introduced by
The variable ol seems to be never declared. If this is a global, consider adding a /** global: ol */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
199
200
    feature.setId(id);
201
    feature.setProperties({
202
        'type':type,
203
        'width': width,
204
        'height': height,
205
        'hpos': hpos,
206
        'vpos': vpos
207
    });
208
209
    return feature;
210
};
211
212
/**
213
 * Parse from an alto element a OpenLayers geometry object
214
 * @param {Element} node
215
 * @return {ol.geom.Polygon|undefined}
216
 * @private
217
 */
218
dlfAltoParser.prototype.parseGeometry_ = function(node) {
219
    var width = parseInt(node.getAttribute("WIDTH")),
220
        height = parseInt(node.getAttribute("HEIGHT")),
221
        x1 = parseInt(node.getAttribute("HPOS")),
222
        y1 = parseInt(node.getAttribute("VPOS")),
223
        x2 = x1 + width,
224
        y2 = y1 + height,
225
        coordinatesWithoutScale = [[[x1, y1], [x2, y1], [x2, y2], [x1, y2], [x1, y1]]];
226
227
    if (isNaN(width) || isNaN(height))
228
        return undefined;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
229
230
    // return geometry without rescale
231
    if (!dlfUtils.exists(this.image_) || !dlfUtils.exists(this.width_))
0 ignored issues
show
Bug introduced by
The variable dlfUtils seems to be never declared. If this is a global, consider adding a /** global: dlfUtils */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
232
        return new ol.geom.Polygon(coordinatesWithoutScale);
0 ignored issues
show
Bug introduced by
The variable ol seems to be never declared. If this is a global, consider adding a /** global: ol */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
233
234
    // rescale coordinates
235
    var scale = this.image_.width / this.width_,
236
        displayedImageHeight = this.image_.height,
237
        offset = dlfUtils.exists(this.offset_) ? this.offset_ : 0,
238
        coordinatesRescale = [];
239
240
    for (var i = 0; i < coordinatesWithoutScale[0].length; i++) {
241
        coordinatesRescale.push([offset + ( scale * coordinatesWithoutScale[0][i][0]),
242
            displayedImageHeight - (scale * coordinatesWithoutScale[0][i][1])]);
243
    };
244
245
    return new ol.geom.Polygon([coordinatesRescale]);
246
};
247
248
/**
249
 * @param {Element} node
250
 * @return {ol.Feature|undefined}
251
 * @private
252
 */
253
dlfAltoParser.prototype.parsePrintSpaceFeature_ = function(node) {
254
    var printspace = $(node).find('PrintSpace');
255
256
    if (printspace.length === 0)
257
        return;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
258
    return this.parseAltoFeature_(printspace[0]);
259
};
260
261
/**
262
 * @param {Element} node
263
 * @return {Array.<ol.Feature>}
264
 * @private
265
 */
266
dlfAltoParser.prototype.parseTextBlockFeatures_ = function(node) {
267
    var textblockElements = $(node).find('TextBlock'),
268
        textblockFeatures = [];
269
270
    for (var i = 0; i < textblockElements.length; i++) {
271
        var feature = this.parseAltoFeature_(textblockElements[i]),
272
            textlines = feature.get('textlines'),
273
            fulltext = '';
274
275
        // aggregated fulltexts
276
        for (var j = 0; j < textlines.length; j++) {
277
            fulltext += textlines[j].get('fulltext') + '\n';
278
        };
279
        feature.setProperties({'fulltext':fulltext});
280
281
        textblockFeatures.push(feature);
282
    };
283
284
    return textblockFeatures;
285
};
286
287
/**
288
 * @param {Element} node
289
 * @return {Array.<ol.Feature>}
290
 * @private
291
 */
292
dlfAltoParser.prototype.parseTextLineFeatures_ = function(node) {
293
    var textlineElements = $(node).find('TextLine'),
294
        textlineFeatures = [];
295
296
    for (var i = 0; i < textlineElements.length; i++) {
297
        var feature = this.parseAltoFeature_(textlineElements[i]),
298
            fulltextElements = feature.get('content'),
299
            fulltext = '';
300
301
        // parse fulltexts
302
        for (var j = 0; j < fulltextElements.length; j++) {
303
            fulltext += fulltextElements[j].get('fulltext');
304
        };
305
        feature.setProperties({'fulltext':fulltext});
306
307
        textlineFeatures.push(feature);
308
    };
309
310
    return textlineFeatures;
311
};
312
313
/**
314
 * @param {Element} node
315
 * @return {Array.<ol.Feature>}
316
 * @private
317
 */
318
dlfAltoParser.prototype.parseContentFeatures_ = function(node) {
319
    var textlineContentElements = $(node).children(),
320
        textlineContentFeatures = [];
321
322
    for (var i = 0; i < textlineContentElements.length; i++) {
323
        var feature = this.parseFeatureWithGeometry_(textlineContentElements[i]),
324
            fulltext = '';
325
326
        // parse fulltexts
327
        switch (textlineContentElements[i].nodeName.toLowerCase()) {
328
            case 'string':
329
                fulltext = textlineContentElements[i].getAttribute('CONTENT');
330
                break;
331
            case 'sp':
332
                fulltext = ' ';
333
                break;
334
            case 'hyp':
335
                fulltext = '-';
336
                break;
337
            default:
338
                fulltext = '';
339
        };
340
        feature.setProperties({'fulltext':fulltext});
341
342
        textlineContentFeatures.push(feature);
343
    };
344
345
    return textlineContentFeatures;
346
};
347
348
349
350
/**
351
 *
352
 * @param {XMLDocument|string}
0 ignored issues
show
Documentation introduced by
The parameter * does not exist. Did you maybe forget to remove this comment?
Loading history...
353
 * @return {XMLDocument}
354
 * @private
355
 */
356
dlfAltoParser.prototype.parseXML_ = function(document) {
357
    if (typeof document === 'string' || document instanceof String) {
358
        return $.parseXML(document);
359
    };
360
    return document;
361
};
362