Completed
Push — master ( 326b3e...061c53 )
by Freek
09:13
created

FileSelection::getSelectedFiles()   B

Complexity

Conditions 6
Paths 13

Size

Total Lines 29
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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