Passed
Push — master ( c7c8df...03432c )
by Darko
12:27
created

TempWorkspaceService::ensureMainTempPath()   B

Complexity

Conditions 7
Paths 18

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 10
c 1
b 0
f 0
dl 0
loc 20
rs 8.8333
cc 7
nc 18
nop 3
1
<?php
2
3
namespace App\Services;
4
5
use Illuminate\Support\Facades\File;
6
use Illuminate\Support\Str;
7
8
class TempWorkspaceService
9
{
10
    /**
11
     * Ensure the main temp path exists and is namespaced by groupID or guidChar.
12
     * Returns the resolved main temp path.
13
     */
14
    public function ensureMainTempPath(string $basePath, string $guidChar = '', string $groupID = ''): string
15
    {
16
        // Normalize separator at end
17
        if (! Str::endsWith($basePath, ['/', '\\'])) {
18
            $basePath .= '/';
19
        }
20
21
        if ($groupID !== '') {
22
            $basePath .= $groupID.'/';
23
        } elseif ($guidChar !== '') {
24
            $basePath .= $guidChar.'/';
25
        }
26
27
        if (! File::isDirectory($basePath)) {
28
            if (! File::makeDirectory($basePath, 0777, true, true) && ! File::isDirectory($basePath)) {
29
                throw new \RuntimeException(sprintf('Directory "%s" was not created', $basePath));
30
            }
31
        }
32
33
        return $basePath;
34
    }
35
36
    /**
37
     * Create a per-release temp folder and return its path.
38
     */
39
    public function createReleaseTempFolder(string $mainTmpPath, string $guid): string
40
    {
41
        $tmpPath = rtrim($mainTmpPath, '/\\').'/'.$guid.'/';
42
        if (! File::isDirectory($tmpPath)) {
43
            if (! File::makeDirectory($tmpPath, 0777, true, false) && ! File::isDirectory($tmpPath)) {
44
                // Try again once in case of transient FS issues
45
                if (! File::makeDirectory($tmpPath, 0777, true, false) && ! File::isDirectory($tmpPath)) {
46
                    throw new \RuntimeException('Unable to create directory: '.$tmpPath);
47
                }
48
            }
49
        }
50
51
        return $tmpPath;
52
    }
53
54
    /**
55
     * Delete files recursively. If $preserveRoot is true, only clear contents of $path.
56
     */
57
    public function clearDirectory(string $path, bool $preserveRoot = true): void
58
    {
59
        if ($path === '' || ! File::exists($path)) {
60
            return;
61
        }
62
63
        if (File::isDirectory($path)) {
64
            // Delete all files recursively
65
            foreach (File::allFiles($path) as $file) {
66
                File::delete($file->getPathname());
67
            }
68
            // Delete sub-directories
69
            foreach (File::directories($path) as $dir) {
70
                File::deleteDirectory($dir);
71
            }
72
            if (! $preserveRoot) {
73
                File::deleteDirectory($path);
74
            }
75
        } elseif (File::isFile($path)) {
76
            File::delete($path);
77
        }
78
    }
79
80
    /**
81
     * List files under a directory.
82
     * If $pattern is provided, return an array of preg_match($pattern, $relativePath, $matches) arrays,
83
     * where $matches[0] is the ABSOLUTE path for convenience (remaining capture groups preserved if present).
84
     * Otherwise return an array of SplFileInfo.
85
     *
86
     * @return array<int, array<int,string>|\SplFileInfo>
87
     */
88
    public function listFiles(string $path, string $pattern = ''): array
89
    {
90
        try {
91
            $files = File::allFiles($path);
92
        } catch (\Throwable $e) {
93
            throw new \RuntimeException('ERROR: Could not open temp dir: '.$e->getMessage());
94
        }
95
96
        if ($pattern !== '') {
97
            $filtered = [];
98
            $base = rtrim($path, '/\\');
99
            foreach ($files as $file) {
100
                $relative = $file->getRelativePathname();
101
                if (preg_match($pattern, $relative, $matches)) {
102
                    // Overwrite full match with absolute path to make downstream file ops straightforward
103
                    $matches[0] = $base.'/'.$relative;
104
                    $filtered[] = $matches;
105
                }
106
            }
107
108
            return $filtered;
109
        }
110
111
        return $files;
112
    }
113
}
114