FileSelection::selectedFiles()   B
last analyzed

Complexity

Conditions 7
Paths 17

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 17
nop 0
dl 0
loc 32
rs 8.4746
c 0
b 0
f 0
1
<?php
2
3
namespace Spatie\Backup\Tasks\Backup;
4
5
use Illuminate\Support\Collection;
6
use Illuminate\Support\Str;
7
use Symfony\Component\Finder\Finder;
8
9
class FileSelection
10
{
11
    /** @var \Illuminate\Support\Collection */
12
    protected $includeFilesAndDirectories;
13
14
    /** @var \Illuminate\Support\Collection */
15
    protected $excludeFilesAndDirectories;
16
17
    /** @var bool */
18
    protected $shouldFollowLinks = false;
19
20
    /**
21
     * @param array|string $includeFilesAndDirectories
22
     *
23
     * @return \Spatie\Backup\Tasks\Backup\FileSelection
24
     */
25
    public static function create($includeFilesAndDirectories = []): self
26
    {
27
        return new static($includeFilesAndDirectories);
28
    }
29
30
    /**
31
     * @param array|string $includeFilesAndDirectories
32
     */
33
    public function __construct($includeFilesAndDirectories = [])
34
    {
35
        $this->includeFilesAndDirectories = collect($includeFilesAndDirectories);
36
37
        $this->excludeFilesAndDirectories = collect();
38
    }
39
40
    /**
41
     * Do not included the given files and directories.
42
     *
43
     * @param array|string $excludeFilesAndDirectories
44
     *
45
     * @return \Spatie\Backup\Tasks\Backup\FileSelection
46
     */
47
    public function excludeFilesFrom($excludeFilesAndDirectories): self
48
    {
49
        $this->excludeFilesAndDirectories = $this->excludeFilesAndDirectories->merge($this->sanitize($excludeFilesAndDirectories));
50
51
        return $this;
52
    }
53
54
    public function shouldFollowLinks(bool $shouldFollowLinks): self
55
    {
56
        $this->shouldFollowLinks = $shouldFollowLinks;
57
58
        return $this;
59
    }
60
61
    /**
62
     * @return \Generator|string[]
63
     */
64
    public function selectedFiles()
65
    {
66
        if ($this->includeFilesAndDirectories->isEmpty()) {
67
            return [];
68
        }
69
70
        $finder = (new Finder())
71
            ->ignoreDotFiles(false)
72
            ->ignoreVCS(false);
73
74
        if ($this->shouldFollowLinks) {
75
            $finder->followLinks();
76
        }
77
78
        foreach ($this->includedFiles() as $includedFile) {
79
            yield $includedFile;
80
        }
81
82
        if (! count($this->includedDirectories())) {
83
            return;
84
        }
85
86
        $finder->in($this->includedDirectories());
87
88
        foreach ($finder->getIterator() as $file) {
89
            if ($this->shouldExclude($file)) {
90
                continue;
91
            }
92
93
            yield $file->getPathname();
94
        }
95
    }
96
97
    protected function includedFiles(): array
98
    {
99
        return $this->includeFilesAndDirectories->filter(function ($path) {
100
            return is_file($path);
101
        })->toArray();
102
    }
103
104
    protected function includedDirectories(): array
105
    {
106
        return $this->includeFilesAndDirectories->reject(function ($path) {
107
            return is_file($path);
108
        })->toArray();
109
    }
110
111
    protected function shouldExclude(string $path): bool
112
    {
113
        foreach ($this->excludeFilesAndDirectories as $excludedPath) {
114
            if (Str::startsWith(realpath($path), $excludedPath)) {
115
                return true;
116
            }
117
        }
118
119
        return false;
120
    }
121
122
    /**
123
     * @param string|array $paths
124
     *
125
     * @return \Illuminate\Support\Collection
126
     */
127
    protected function sanitize($paths): Collection
128
    {
129
        return collect($paths)
130
            ->reject(function ($path) {
131
                return $path === '';
132
            })
133
            ->flatMap(function ($path) {
134
                return glob($path);
135
            })
136
            ->map(function ($path) {
137
                return realpath($path);
138
            })
139
            ->reject(function ($path) {
140
                return $path === false;
141
            });
142
    }
143
}
144