Passed
Push — develop ( 76f958...62a091 )
by Nikolay
14:43 queued 24s
created

sites/admin-cabinet/assets/js/src/main/version-compare.js   A

Complexity

Total Complexity 17
Complexity/F 4.25

Size

Lines of Code 53
Function Count 4

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
wmc 17
eloc 31
c 0
b 0
f 0
dl 0
loc 53
rs 10
mnd 13
bc 13
fnc 4
bpm 3.25
cpm 4.25
noi 1
1
/*
2
 * MikoPBX - free phone system for small business
3
 * Copyright (C) 2017-2020 Alexey Portnov and Nikolay Beketov
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along with this program.
16
 * If not, see <https://www.gnu.org/licenses/>.
17
 */
18
19
/**
20
 * Compares two software version numbers (e.g. "1.7.1" or "1.2b").
21
 *
22
 * This function was born in http://stackoverflow.com/a/6832721.
23
 *
24
 * @param {string} v1 The first version to be compared.
25
 * @param {string} v2 The second version to be compared.
26
 * @param {object} [options] Optional flags that affect comparison behavior:
27
 * lexicographical: (true/[false]) compares each part of the version strings lexicographically instead of naturally;
28
 *                  this allows suffixes such as "b" or "dev" but will cause "1.10" to be considered smaller than "1.2".
29
 * zeroExtend: ([true]/false) changes the result if one version string has less parts than the other. In
30
 *             this case the shorter string will be padded with "zero" parts instead of being considered smaller.
31
 *
32
 * @returns {number|NaN}
33
 * - 0 if the versions are equal
34
 * - a negative integer iff v1 < v2
35
 * - a positive integer iff v1 > v2
36
 * - NaN if either version string is in the wrong format
37
 */
38
39
function versionCompare(v1, v2, options) {
40
	const lexicographical = (options && options.lexicographical) || false,
41
		zeroExtend = (options && options.zeroExtend) || true;
42
43
	let v1parts = (v1 || "0").split('.'),
44
		v2parts = (v2 || "0").split('.');
45
46
	function isValidPart(x) {
47
		return (lexicographical ? /^\d+[A-Za-zαß]*$/ : /^\d+[A-Za-zαß]?$/).test(x);
48
	}
49
50
	if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) {
51
		return NaN;
52
	}
53
54
	if (zeroExtend) {
55
		while (v1parts.length < v2parts.length) v1parts.push("0");
56
		while (v2parts.length < v1parts.length) v2parts.push("0");
57
	}
58
59
	if (!lexicographical) {
60
		v1parts = v1parts.map(function(x){
61
			const match = (/[A-Za-zαß]/).exec(x);
62
			return Number(match ? x.replace(match[0], "." + x.charCodeAt(match.index)):x);
63
		});
64
		v2parts = v2parts.map(function(x){
65
			const match = (/[A-Za-zαß]/).exec(x);
66
			return Number(match ? x.replace(match[0], "." + x.charCodeAt(match.index)):x);
67
		});
68
	}
69
70
	for (let i = 0; i < v1parts.length; ++i) {
71
		if (v2parts.length === i) {
72
			return 1;
73
		}
74
75
		if (v1parts[i] === v2parts[i]) {
76
			continue;
0 ignored issues
show
Unused Code introduced by
This continue has no effect on the loop flow and can be removed.
Loading history...
77
		}
78
		else if (v1parts[i] > v2parts[i]) {
79
			return 1;
80
		}
81
		else {
82
			return -1;
83
		}
84
	}
85
86
	if (v1parts.length !== v2parts.length) {
87
		return -1;
88
	}
89
90
	return 0;
91
}