Completed
Push — master ( c3c62a...f55912 )
by Nikola
03:31
created

StreamDestination::has()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 8
ccs 5
cts 5
cp 1
rs 9.4286
cc 2
eloc 4
nc 2
nop 1
crap 2
1
<?php
2
/*
3
 * This file is part of the Backup package, an RunOpenCode project.
4
 *
5
 * (c) 2015 RunOpenCode
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * This project is fork of "kbond/php-backup", for full credits info, please
11
 * view CREDITS file that was distributed with this source code.
12
 */
13
namespace RunOpenCode\Backup\Destination;
14
15
use RunOpenCode\Backup\Backup\Backup;
16
use RunOpenCode\Backup\Backup\File;
17
use RunOpenCode\Backup\Contract\BackupInterface;
18
use RunOpenCode\Backup\Contract\DestinationInterface;
19
use RunOpenCode\Backup\Exception\DestinationException;
20
use Symfony\Component\Filesystem\Filesystem;
21
use Symfony\Component\Finder\Finder;
22
23
/**
24
 * Class StreamDestination
25
 *
26
 * Stream destination is local, mountable, destination.
27
 *
28
 * @package RunOpenCode\Backup\Destination
29
 */
30
class StreamDestination implements DestinationInterface
31
{
32
    /**
33
     * @var BackupInterface[]
34
     */
35
    protected $backups;
36
37
    /**
38
     * @var string
39
     */
40
    protected $directory;
41
42
    /**
43
     * @var Filesystem
44
     */
45
    private $filesystem;
46
47 4
    public function __construct($directory, Filesystem $filesystem = null)
48
    {
49 4
        $this->directory = $directory;
50 4
        $this->filesystem = is_null($filesystem) ? new Filesystem() : $filesystem;
51
52 4
        if (!$this->filesystem->exists($this->directory)) {
53
54 2
            $this->filesystem->mkdir($this->directory);
55
56 4
        } elseif (!is_dir($this->directory)) {
57
            throw new \RuntimeException(sprintf('Provided location "%s" is not directory.', $this->directory));
58 4
        } elseif (!is_writable($this->directory)) {
59
            throw new \RuntimeException(sprintf('Provided location "%s" is not writeable.', $this->directory));
60
        }
61 4
    }
62
63
    /**
64
     * {@inheritdoc}
65
     */
66 4
    public function push(BackupInterface $backup)
67
    {
68 4
        $backupDirectory = sprintf('%s%s%s', rtrim($this->directory, DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR, $backup->getName());
69 4
        $this->filesystem->mkdir($backupDirectory);
70
71 4
        $existingBackupFiles = array();
72
73 4
        foreach (Finder::create()->in($backupDirectory)->files() as $existingFile) {
74 2
            $file = File::fromLocal($existingFile, $backupDirectory);
75 2
            $existingBackupFiles[$file->getRelativePath()] = $file->getPath();
76 4
        }
77
78 4
        foreach ($backup->getFiles() as $backupFile) {
79
80
            try {
81 4
                $this->filesystem->copy($backupFile->getPath(), $filePath = sprintf('%s%s%s', $backupDirectory, DIRECTORY_SEPARATOR, $backupFile->getRelativePath()));
82 4
                $this->filesystem->touch($filePath, $backupFile->getModifiedAt()->getTimestamp());
83 4
            } catch (\Exception $e) {
84
                throw new DestinationException(sprintf('Unable to backup file "%s" to destination "%s".', $backupFile->getPath(), $this->directory), 0, $e);
85
            }
86
87 4
            if (array_key_exists($backupFile->getRelativePath(), $existingBackupFiles) && $existingBackupFiles[$backupFile->getRelativePath()]) {
88 2
                unset($existingBackupFiles[$backupFile->getRelativePath()]);
89 2
            }
90 4
        }
91
92 4
        $this->filesystem->remove($existingBackupFiles);
93 4
        $this->removeEmptyDirectories($backupDirectory);
94
95 4
        if (!empty($this->backups)) {
96
            $this->backups[] = $backup;
97
        }
98 4
    }
99
100
    /**
101
     * {@inheritdoc}
102
     */
103 2
    public function getIterator()
104
    {
105 2
        if (is_null($this->backups)) {
106
            $this->load();
107
        }
108
109 2
        return new \ArrayIterator($this->backups);
110
    }
111
112
    /**
113
     * {@inheritdoc}
114
     */
115 4
    public function get($name)
116
    {
117 4
        if (is_null($this->backups)) {
118
            $this->load();
119
        }
120
121 4
        return $this->backups[$name];
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     */
127 4
    public function has($name)
128
    {
129 4
        if (is_null($this->backups)) {
130 4
            $this->load();
131 4
        }
132
133 4
        return array_key_exists($name, $this->backups);
134
    }
135
136
    /**
137
     * {@inheritdoc}
138
     */
139
    public function delete($name)
140
    {
141
        try {
142
            $this->filesystem->remove(sprintf('%s%s%s', rtrim($this->directory, DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR, $name));
143
        } catch (\Exception $e) {
144
            throw new DestinationException(sprintf('Unable to remove backup "%s" from stream destination "%s".', $name, $this->directory), 0, $e);
145
        }
146
147
        if (!is_null($this->backups)) {
148
            unset($this->backups[$name]);
149
        }
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155
    public function all()
156
    {
157
        if (is_null($this->backups)) {
158
            $this->load();
159
        }
160
161
        return $this->backups;
162
    }
163
164
    /**
165
     * Load backups from destination.
166
     *
167
     * @return BackupInterface[]
168
     */
169 4
    protected function load()
170
    {
171 4
        $this->backups = array();
172
173
        /**
174
         * @var \SplFileInfo $backupDirectory
175
         */
176 4
        foreach (Finder::create()->in($this->directory)->depth(0)->directories()->sortByModifiedTime() as $backupDirectory) {
177
178 4
            $backup = new Backup($backupDirectory->getBasename(), array(), 0, $backupDirectory->getCTime(), $backupDirectory->getMTime());
179
180
            /**
181
             * @var \SplFileInfo $backupFile
182
             */
183 4
            foreach (Finder::create()->in($backupDirectory->getPathname())->files() as $backupFile) {
184
185 4
                $backup->addFile(File::fromSplFileInfo($backupFile, $backupDirectory->getPathname()));
186 4
            }
187
188 4
            $this->backups[$backup->getName()] = $backup;
189 4
        }
190 4
    }
191
192
    /**
193
     * Remove empty directories from destination.
194
     *
195
     * @param $backupDirectory
196
     */
197 4
    protected function removeEmptyDirectories($backupDirectory)
198
    {
199
        /**
200
         * @var \SplFileInfo $dir
201
         */
202 4
        foreach (Finder::create()->directories()->in($backupDirectory)->depth(0) as $dir) {
203
204 2
            if (Finder::create()->files()->in($dir->getPathname())->count() > 0) {
205 2
                $this->removeEmptyDirectories($dir->getPathname());
206 2
            } else {
207 2
                $this->filesystem->remove($dir->getPathname());
208
            }
209 4
        }
210 4
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215 2
    public function count()
216
    {
217 2
        return count($this->getIterator());
218
    }
219
}
220