Passed
Push — main ( a3578d...cf5a21 )
by Filipe
01:23 queued 31s
created

FileTools::calculateSize()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 7
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 14
ccs 8
cts 8
cp 1
crap 3
rs 10
1
<?php
2
3
/**
4
 * This file is part of fswatch
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
declare(strict_types=1);
11
12
namespace Slick\FsWatch;
13
14
/**
15
 * FileTools
16
 *
17
 * @package Slick\FsWatch
18
 */
19
final class FileTools
20
{
21
22
    /**
23
     * Normalizes a file path by replacing backslashes with forward slashes,
24
     * removing trailing slashes, and converting Windows drive letter prefixes to forward slashes.
25
     *
26
     * @param string $path The file path to normalize.
27
     * @return string The normalized file path.
28
     */
29 15
    public function normalizePath(string $path): string
30
    {
31 15
        $path = rtrim(str_replace('\\', '/', $path), '/');
32 15
        $path = (string) preg_replace('/\w:\//i', '/', $path);
33 15
        return is_dir($path) === true ? $path.'/' : $path;
34
    }
35
36
    /**
37
     * Calculates the total size of a directory or file.
38
     *
39
     * @param string $path The path of the directory or file.
40
     * @return int The total size in bytes.
41
     */
42 8
    public function calculateSize(string $path): int
43
    {
44 8
        $result = 0;
45 8
        $path = $this->normalizePath($path);
46
47 8
        if (is_dir($path)) {
48 1
            return $this->calculateDirectorySize($path);
49
        }
50
51 7
        if (is_file($path)) {
52 7
            $result += intval(sprintf('%u', filesize($path)));
53
        }
54
55 7
        return $result;
56
    }
57
58 1
    private function calculateDirectorySize(string $path): int
59
    {
60 1
        $handle = opendir($path);
61 1
        $result = 0;
62 1
        while ($handle && ($file = readdir($handle)) !== false) {
63 1
            if ($file === '.' || $file === '..') {
64 1
                continue;
65
            }
66
67 1
                $filePath = $path .  $file;
68 1
            if (is_dir($filePath)) {
69 1
                $result += $this->calculateSize($filePath);
70 1
                continue;
71
            }
72
73 1
                $result += intval(sprintf('%u', filesize($filePath)));
74
        }
75 1
            unset($handle);
76 1
        return $result;
77
    }
78
79
    /**
80
     * Flattens a size map recursively into a one-dimensional array.
81
     *
82
     * @param array<string, mixed> $map The size map to flatten.
83
     * @param string $glue The separator to use between the keys in the flattened array. Default is '/'.
84
     *
85
     * @return array<string, int> The flattened size map.
86
     */
87 4
    public function flattenSizeMap(array $map, string $glue = '/'): array
88
    {
89 4
        $flattened = [];
90 4
        $this->flattenMap('', $map, $flattened, $glue);
91 4
        return $flattened;
92
    }
93
94
    /**
95
     * Recursively flattens a map into a one-dimensional array.
96
     *
97
     * @param string $path The current path in the map.
98
     * @param array<string, mixed> $map The map to flatten.
99
     * @param array<string, mixed> &$flattened The flattened map.
100
     * @param string $glue The separator to use between the keys in the flattened array.
101
     *
102
     * @return void
103
     */
104 4
    private function flattenMap(string $path, array $map, array &$flattened, string $glue): void
105
    {
106 4
        foreach ($map as $key => $value) {
107 4
            $newKey = ltrim($path.$glue.$key, '/');
108 4
            if (is_array($value)) {
109 4
                $this->flattenMap($newKey, $value, $flattened, $glue);
110 4
                continue;
111
            }
112 4
            $flattened[$newKey] = $value;
113
        }
114
    }
115
}
116