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

versions::get()   C

Complexity

Conditions 14
Paths 12

Size

Total Lines 66
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 14.4207

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 14
eloc 32
c 1
b 0
f 0
nc 12
nop 3
dl 0
loc 66
ccs 27
cts 31
cp 0.871
crap 14.4207
rs 6.2666

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
}