Completed
Push — master ( 7d452a...6f6502 )
by Freek
02:08
created

FileSelection::selectedFiles()   C

Complexity

Conditions 7
Paths 17

Size

Total Lines 33
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 18
nc 17
nop 0
dl 0
loc 33
rs 6.7272
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
        foreach ($this->includedFiles() as $includedFile) {
86
            yield $includedFile;
87
        }
88
89
        if (! count($this->includedDirectories())) {
90
            return;
91
        }
92
93
        $finder->in($this->includedDirectories());
94
95
        foreach ($finder->getIterator() as $file) {
96
            if ($this->shouldExclude($file)) {
97
                continue;
98
            }
99
100
            yield $file->getPathname();
101
        }
102
    }
103
104
    protected function includedFiles(): array
105
    {
106
        return $this->includeFilesAndDirectories->filter(function ($path) {
107
            return is_file($path);
108
        })->toArray();
109
    }
110
111
    protected function includedDirectories(): array
112
    {
113
        return $this->includeFilesAndDirectories->reject(function ($path) {
114
            return is_file($path);
115
        })->toArray();
116
    }
117
118
    protected function shouldExclude(string $path): bool
119
    {
120
        foreach ($this->excludeFilesAndDirectories as $excludedPath) {
121
            if (starts_with(realpath($path), $excludedPath)) {
122
                return true;
123
            }
124
        }
125
126
        return false;
127
    }
128
129
    /**
130
     * @param string|array $paths
131
     *
132
     * @return \Illuminate\Support\Collection
133
     */
134
    protected function sanitize($paths): Collection
135
    {
136
        return collect($paths)
137
            ->reject(function ($path) {
138
                return $path === '';
139
            })
140
            ->flatMap(function ($path) {
141
                return glob($path);
142
            })
143
            ->map(function ($path) {
144
                return realpath($path);
145
            })
146
            ->reject(function ($path) {
147
                return $path === false;
148
            });
149
    }
150
}
151