Passed
Branch master (a02de7)
by Mihail
02:35
created

get_version_array()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 5
c 1
b 0
f 1
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 10
cc 3
nc 2
nop 1
crap 3
1
<?php declare(strict_types=1);
2
3
const INVALID_VERSION_ARRAY = ['0.0.0', '0', '0'];
4
const SEMVER_REGEX = '/^([0-9]+\.[0-9]+\.[0-9]+)(?:\-([a-z0-9-]+(?:\.[a-z0-9-]+)*))?(?:\+([a-z0-9-]+(?:\.[a-z0-9-]+)*))?$/i';
5
6
/**
7
 * Returns the Koded version number from VERSION file.
8
 *
9
 * @param array $version
10
 * @return string SemVer-compliant version
11
 * @see http://semver.org/
12
 */
13
function get_version(array $version = []): string
14
{
15 13
    $v = get_complete_version($version);
16
    // Most common format (X.Y.Z)
17 13
    if (empty($v[1]) && empty($v[2])) {
18 2
        return $v[0];
19
    }
20
    // Special case when pre-release is ALPHA and build is empty
21 11
    if ('alpha' === strtolower($v[1]) && empty($v[2])) {
22 1
        $v[2] = get_git_changeset();
23 1
        return sprintf('%s-%s+%s', ...$v);
24
    }
25 10
    if (empty($v[2])) {
26 4
        return sprintf('%s-%s', ...$v);
27
    }
28 6
    if (empty($v[1])) {
29 2
        $v[1] = $v[2];
30 2
        return sprintf('%s+%s', ...$v);
31
    }
32 4
    return sprintf('%s-%s+%s', ...$v);
33
}
34
35
/**
36
 * @internal
37
 *
38
 * Returns the version parts in array.
39
 *
40
 * @param string $version
41
 * @return array If version is not parsed by the semver rules, returns 0-filled array
42
 */
43
function get_version_array(string $version): array
44
{
45 44
    if (!preg_match(SEMVER_REGEX, \trim($version), $match)) {
46 5
        return INVALID_VERSION_ARRAY;
47
    }
48 39
    array_shift($match);
49 39
    $match = array_replace(INVALID_VERSION_ARRAY, $match);
50 39
    return array_map(fn($v) => empty($v) ? '0' : $v, $match);
51
}
52
53
/**
54
 * @internal
55
 *
56
 * Returns the array version of the Koded version.
57
 * Checks the correctness of the provided version array.
58
 *
59
 * @param array $version
60
 * @return array Koded segmented version as array
61
 */
62
function get_complete_version(array $version): array
63
{
64 15
    if (false === empty($version)) {
65 14
        assert(3 === \count($version), 'version array should have exactly 3 parts');
66 14
        assert('' !== $version[1], 'pre-release is empty, should be zero or valid identifier');
67 14
        assert('' !== $version[2], 'build-metadata is empty, should be zero or valid identifier');
68 14
        return $version;
69
    }
70
//    if ('VERSION' !== VERSION && is_array(VERSION)) {
71 1
    if (defined('VERSION') && is_array(VERSION)) {
0 ignored issues
show
Bug introduced by
The constant VERSION was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
72
        return get_version_array(join('-', array_filter(VERSION)));
73
    }
74 1
    if ($version = @file_get_contents(__DIR__ . '/../../VERSION')) {
75
        return get_version_array($version);
76
    }
77 1
    return INVALID_VERSION_ARRAY;
78
}
79
80
/**
81
 * @internal
82
 *
83
 * Returns the the major version from VERSION file.
84
 *
85
 * @param array $version
86
 * @return int The major version
87
 */
88
function get_major_version(array $version): int
89
{
90 1
    return (int)get_complete_version($version)[0];
91
}
92
93
/**
94
 * @internal
95
 *
96
 * The result is the UTC timestamp of the changeset in "YmDHis" format.
97
 * This value is not guaranteed to be unique, but it is sufficient
98
 * for generating the development version numbers.
99
 *
100
 * @return string Returns the numeric identifier of the latest GIT changeset,
101
 * or root directory modification time on failure
102
 */
103
function get_git_changeset(): string
104
{
105 1
    $format = 'YmdHis';
106 1
    $gitlog = proc_open('git log --pretty=format:%ct --quiet -l HEAD', [
107 1
        ['pipe', 'r'],
108
        ['pipe', 'w'],
109
        ['pipe', 'w'],
110 1
    ], $pipes, __DIR__);
111 1
    if (false === is_resource($gitlog)) {
112
        return date($format, filemtime(__DIR__ . '/.'));
113
    }
114 1
    stream_set_blocking($pipes[2], false);
115 1
    $timestamp = stream_get_contents($pipes[1]);
116 1
    $timestamp = explode(PHP_EOL, $timestamp)[0] ?? '';
117
    // cleanup; avoid a deadlock
118 1
    fclose($pipes[0]);
119 1
    fclose($pipes[1]);
120 1
    fclose($pipes[2]);
121 1
    proc_close($gitlog);
122 1
    if (empty($timestamp)) {
123 1
        return date($format, filemtime(__DIR__ . '/.'));
124
    }
125
    // UNIX timestamps are stored in UTC
126
    return date_create_immutable('@' . $timestamp)->format($format);
127
}
128