Passed
Push — main ( b5249e...5139df )
by Will
03:14
created

versions   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 144
Duplicated Lines 0 %

Test Coverage

Coverage 85.71%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 72
c 1
b 0
f 0
dl 0
loc 144
ccs 60
cts 70
cp 0.8571
rs 9.68
wmc 34

4 Methods

Rating   Name   Duplication   Size   Complexity  
B load() 0 29 9
B released() 0 25 7
C get() 0 66 14
A latest() 0 14 4
1
<?php
2
declare(strict_types = 1);
3
namespace hexydec\agentzero;
4
5
class versions {
6
7
	protected static ?array $versions = null;
8
9 95
	protected static function load(string $source, ?string $cache, int $life = 604800) : array|false {
10
11
		// cache for this session
12 95
		$data = self::$versions;
13 95
		if ($data === null) {
14
15
			// fetch from cache
16 95
			if (\file_exists($cache) && \filemtime($cache) > \time() - $life && ($json = \file_get_contents($cache)) !== false) {
0 ignored issues
show
Bug introduced by
It seems like $cache can also be of type null; however, parameter $filename of filemtime() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

16
			if (\file_exists($cache) && \filemtime(/** @scrutinizer ignore-type */ $cache) > \time() - $life && ($json = \file_get_contents($cache)) !== false) {
Loading history...
Bug introduced by
It seems like $cache can also be of type null; however, parameter $filename of file_get_contents() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

16
			if (\file_exists($cache) && \filemtime($cache) > \time() - $life && ($json = \file_get_contents(/** @scrutinizer ignore-type */ $cache)) !== false) {
Loading history...
Bug introduced by
It seems like $cache can also be of type null; however, parameter $filename of file_exists() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

16
			if (\file_exists(/** @scrutinizer ignore-type */ $cache) && \filemtime($cache) > \time() - $life && ($json = \file_get_contents($cache)) !== false) {
Loading history...
17
18
			// fetch from server
19 1
			} elseif (($json = \file_get_contents($source)) === false) {
20
				return false;
21
22
			// update cache
23 1
			} elseif ($cache !== null) {
24
25
				// create directory
26 1
				$dir = \dirname($cache);
27 1
				if (!\is_dir($dir) && \mkdir($dir, 0755)) {
28
29
					// cache file
30 1
					\file_put_contents($cache, $json);
31
				}
32
			}
33
34
			// decode JSON
35 95
			$data = \json_decode($json, true);
36
		}
37 95
		return $data ?? false;
38
	}
39
40 90
	protected static function latest(array $versions, ?\DateTime $now = null) : ?string {
41
42
		// no date restriction
43 90
		if ($now === null) {
44 90
			return \strval(\array_key_first($versions));
45
		} else {
46
			$date = \intval($now->format('Ymd'));
47
			foreach ($versions AS $key => $item) {
48
				if ($date < $item) {
49
					return \strval($key);
50
				}
51
			}
52
		}
53
		return null;
54
	}
55
56 89
	protected static function released(array $data, string $version) : ?string {
57 89
		$major = \intval($version);
58 89
		$len = 0;
59 89
		$i = 0;
60 89
		$vlen = \strlen($version);
61 89
		$released = null;
62 89
		foreach ($data AS $ver => $date) {
63 89
			if (\intval($ver) === $major) {
64 89
				$ver = \strval($ver); // cast as string to get letters, string keys cast to int when array keys
65 89
				$match = 0;
66 89
				for ($n = 0; $n < $vlen; $n++) {
67 89
					if ($version[$n] === ($ver[$n] ?? null)) {
68 89
						$match++;
69
					} else {
70 82
						break;
71
					}
72
				}
73 89
				if ($match > $len) {
74 89
					$len = $match;
75 89
					$released = $date;
76
				}
77
			}
78 89
			$i++;
79
		}
80 89
		return $released !== null ? (new \DateTime(\strval($released)))->format('Y-m-d') : null;
0 ignored issues
show
introduced by
The condition $released !== null is always false.
Loading history...
81
	}
82
83 95
	public static function get(string $browser, string $version, array $config) : array {
84 95
		if (($versions = self::load($config['source'], $config['cache'])) !== false) {
85 95
			$data = [];
86 95
			if (isset($versions[$browser])) {
87
88
				// get latest version of the browser
89 90
				$data['browserlatest'] = self::latest($versions[$browser]);
90
				
91
				// check if version is greater than latest version
92 90
				$major = \intval($version);
93 90
				$latest = \intval($data['browserlatest']);
94 90
				$first = \intval(\array_key_last($versions[$browser]));
95
96
				// version is way out of bounds (This happens sometimes, for example if the safari engine version is reported instead of the browser version)
97 90
				if ($latest + 3 < $major) {
98 25
					return [];
99
100
				// nightly build?
101 90
				} elseif ($latest + 3 === $major) {
102
					$data['browserstatus'] = 'nightly';
103
104
				// canary build
105 90
				} elseif ($latest + 2 === $major) {
106
					$data['browserstatus'] = 'canary';
107
108
				// beta release
109 90
				} elseif ($latest + 1 === $major) {
110
					$data['browserstatus'] = 'beta';
111
112
				// so old we don't have data for it
113 90
				} elseif ($major < $first) {
114 22
					$data['browserstatus'] = 'legacy';
115
116
				// find closes match for version
117
				} else {
118
119
					// get current version
120 89
					$data['browserreleased'] = self::released($versions[$browser], $version);
0 ignored issues
show
Bug introduced by
Are you sure the assignment to $data['browserreleased'] is correct as self::released($versions[$browser], $version) targeting hexydec\agentzero\versions::released() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
121
122
					// calculate status
123 89
					if (isset($data['browserreleased'])) {
124 89
						$current = \explode('.', $data['browserlatest'])[0] === \explode('.', $version)[0];
125 89
						$released = new \DateTime($data['browserreleased']);
126
127
						// legacy
128 89
						if ($released < \date_create('-5 years')) {
129 68
							$data['browserstatus'] = 'legacy';
130
131
						// outdated
132 64
						} elseif ($released < \date_create('-2 years')) {
133 55
							$data['browserstatus'] = 'outdated';
134
135
						// current
136 26
						} elseif ($current && ($released >= \date_create('-1 year') || $data['browserlatest'] === $version)) {
137 1
							$data['browserstatus'] = 'current';
138
139
						// previous
140
						} else {
141 25
							$data['browserstatus'] = 'previous';
142
						}
143
					}
144
				}
145
			}
146 95
			return $data;
147
		}
148
		return [];
149
	}
150
}