Passed
Push — main ( b74a3d...1ce707 )
by Will
12:35
created

versions::get()   C

Complexity

Conditions 12
Paths 10

Size

Total Lines 61
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 12.4677

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 29
c 1
b 0
f 0
nc 10
nop 3
dl 0
loc 61
ccs 23
cts 27
cp 0.8519
crap 12.4677
rs 6.9666

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
47
		}
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return string. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
48
	}
49
50 90
	protected static function released(array $data, string $version) : ?string {
51 90
		$major = \intval($version);
52 90
		$len = 0;
53 90
		$i = 0;
54 90
		$vlen = \strlen($version);
55 90
		$released = null;
56 90
		foreach ($data AS $ver => $date) {
57 90
			if (\intval($ver) === $major) {
58 89
				$ver = \strval($ver); // cast as string to get letters, string keys cast to int when array keys
59 89
				$match = 0;
60 89
				for ($n = 0; $n < $vlen; $n++) {
61 89
					if ($version[$n] === ($ver[$n] ?? null)) {
62 89
						$match++;
63
					} else {
64 82
						break;
65
					}
66
				}
67 89
				if ($match > $len) {
68 89
					$len = $match;
69 89
					$released = $date;
70
				}
71
			}
72 90
			$i++;
73
		}
74 90
		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...
75
	}
76
77 95
	public static function get(string $browser, string $version, array $config) : array {
78 95
		if (($versions = self::load($config['source'], $config['cache'])) !== false) {
79 95
			$data = [];
80 95
			if (isset($versions[$browser])) {
81
82
				// get latest version of the browser
83 90
				$data['browserlatest'] = self::latest($versions[$browser]);
84
				
85
				// check if version is greater than latest version
86 90
				$major = \intval($version);
87 90
				$latest = \intval($data['browserlatest']);
88
89
				// version is way out of bounds (This happens sometimes, for example if the safari engine version is reported instead of the browser version)
90 90
				if ($latest + 3 < $major) {
91 25
					return [];
92
93
				// nightly build?
94 90
				} elseif ($latest + 3 === $major) {
95
					$data['browserstatus'] = 'nightly';
96
97
				// canary build
98 90
				} elseif ($latest + 2 === $major) {
99
					$data['browserstatus'] = 'canary';
100
101
				// beta release
102 90
				} elseif ($latest + 1 === $major) {
103
					$data['browserstatus'] = 'beta';
104
105
				// find closes match for version
106
				} else {
107
108
					// get current version
109 90
					$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...
110
111
					// calculate status
112 90
					if (isset($data['browserreleased'])) {
113 89
						$current = \explode('.', $data['browserlatest'])[0] === \explode('.', $version)[0];
114 89
						$released = new \DateTime($data['browserreleased']);
115
116
						// legacy
117 89
						if ($released < \date_create('-3 years')) {
118 77
							$data['browserstatus'] = 'legacy';
119
120
						// current
121 53
						} elseif ($current && ($released >= \date_create('-1 year') || $data['browserlatest'] === $version)) {
122 1
							$data['browserstatus'] = 'current';
123
124
						// previous
125
						} else {
126 89
							$data['browserstatus'] = 'previous';
127
						}
128
129
					// version wasn't listed - ancient
130
					} else {
131 25
						$data['browserstatus'] = 'legacy';
132
					}
133
				}
134
			}
135 95
			return $data;
136
		}
137
		return [];
138
	}
139
}