Completed
Push — master ( ad9675...44a00f )
by Arne
02:30
created

FilesystemUtility::parseTime()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace Storeman;
4
5
abstract class FilesystemUtility
6
{
7
    /**
8
     * Does the same thing as its php core counterpart but returns atime, ctime and mtime in full precision.
9
     *
10
     * @param string $path
11
     * @return array
12
     * @throws \RuntimeException
13
     */
14
    public static function lstat(string $path): array
15
    {
16
        exec('stat ' . escapeshellarg('-c%D;%i;%f;%h;%u;%g;%t;%s;%x;%y;%z;%B;%b') . ' ' . escapeshellarg($path) . ' 2>&1', $output, $exitCode);
17
18
        if ($exitCode !== 0)
19
        {
20
            throw new \RuntimeException();
21
        }
22
23
        $array = str_getcsv($output[0], ';');
24
25
        $stat = [
26
            'dev' => hexdec($array[0]),
27
            'ino' => (int)$array[1],
28
            'mode' => hexdec($array[2]),
29
            'nlink' => (int)$array[3],
30
            'uid' => (int)$array[4],
31
            'gid' => (int)$array[5],
32
            'rdev' => hexdec($array[6]),
33
            'size' => (int)$array[7],
34
            'atime' => static::parseTime($array[8]),
35
            'mtime' => static::parseTime($array[9]),
36
            'ctime' => static::parseTime($array[10]),
37
            'blksize' => (int)$array[11],
38
            'blocks' => (int)$array[12],
39
        ];
40
41
        // for full compatibility
42
        $stat[0] = $stat['dev'];
43
        $stat[1] = $stat['ino'];
44
        $stat[2] = $stat['mode'];
45
        $stat[3] = $stat['nlink'];
46
        $stat[4] = $stat['uid'];
47
        $stat[5] = $stat['gid'];
48
        $stat[6] = $stat['rdev'];
49
        $stat[7] = $stat['size'];
50
        $stat[8] = $stat['atime'];
51
        $stat[9] = $stat['mtime'];
52
        $stat[10] = $stat['ctime'];
53
        $stat[11] = $stat['blksize'];
54
        $stat[12] = $stat['blocks'];
55
56
        return $stat;
57
    }
58
59
    /**
60
     * Parses strings like this: 2018-07-11 00:40:23.636828641 +0200
61
     * Returns unix timestamp with sub-second resolution as float.
62
     *
63
     * @param string $timeString
64
     * @return float
65
     */
66
    public static function parseTime(string $timeString): float
67
    {
68
        $fractionStringEnd = strpos($timeString, ' ', 19);
69
        $reducedPrecisionString = substr($timeString, 0, 19) . substr($timeString, $fractionStringEnd);
70
71
        $time = (float)\DateTime::createFromFormat('Y-m-d H:i:s O', $reducedPrecisionString)->getTimestamp();
72
        $time += (float)substr($timeString, 19, $fractionStringEnd - 19);
73
74
        return $time;
75
    }
76
77
    /**
78
     * Rebuilds time string like this from given unixtime: 2018-07-11 00:40:23.636828641 +0200
79
     *
80
     * @param float $timestamp
81
     * @param int $decimals
82
     * @param \DateTimeZone $timeZone
83
     * @return string
84
     */
85
    public static function buildTime(float $timestamp, int $decimals = 9, \DateTimeZone $timeZone = null): string
86
    {
87
        $dateTime = \DateTime::createFromFormat('U', (int)$timestamp);
88
        $timestampString = sprintf("%.{$decimals}f", $timestamp);
89
90
        if ($timeZone)
91
        {
92
            $dateTime->setTimezone($timeZone);
93
        }
94
95
        $string = $dateTime->format('Y-m-d H:i:s');
96
        $string .= substr($timestampString, strpos($timestampString, '.'));
97
        $string .= " {$dateTime->format('O')}";
98
99
        return $string;
100
    }
101
}
102