Completed
Push — master ( 8a7993...1a063d )
by Nikola
05:00
created

LocalDestination::pushFile()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 8
rs 9.4286
cc 2
eloc 5
nc 2
nop 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\FileInterface;
19
use RunOpenCode\Backup\Exception\DestinationException;
20
use Symfony\Component\Filesystem\Filesystem;
21
use Symfony\Component\Finder\Finder;
22
23
/**
24
 * Class LocalDestination
25
 *
26
 * Stream destination is local, mountable, destination.
27
 *
28
 * @package RunOpenCode\Backup\Destination
29
 */
30
class LocalDestination extends BaseDestination
31
{
32
    /**
33
     * @var string
34
     */
35
    protected $directory;
36
37
    /**
38
     * @var Filesystem
39
     */
40
    private $filesystem;
41
42 14
    public function __construct($directory, Filesystem $filesystem = null)
43
    {
44 14
        $this->directory = rtrim($directory, '/\\');
45 14
        $this->filesystem = is_null($filesystem) ? new Filesystem() : $filesystem;
46
47 14
        if (!$this->filesystem->exists($this->directory)) {
48
49 10
            $this->filesystem->mkdir($this->directory);
50
51 12
        } elseif (!is_dir($this->directory)) {
52
            throw new \RuntimeException(sprintf('Provided location "%s" is not directory.', $this->directory));
53 10
        } elseif (!is_writable($this->directory)) {
54
            throw new \RuntimeException(sprintf('Provided location "%s" is not writeable.', $this->directory));
55
        }
56 14
    }
57
58
    /**
59
     * {@inheritdoc}
60
     */
61
    public function delete($name)
62
    {
63
        try {
64
            $this->filesystem->remove(sprintf('%s%s%s', rtrim($this->directory, DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR, $name));
65
        } catch (\Exception $e) {
66
            throw new DestinationException(sprintf('Unable to remove backup "%s" from stream destination "%s".', $name, $this->directory), 0, $e);
67
        }
68
69
        if (!is_null($this->backups)) {
70
            unset($this->backups[$name]);
71
        }
72
    }
73
74
    /**
75
     * {@inheritdoc}
76
     */
77 14
    public function push(BackupInterface $backup)
78
    {
79 14
        $backupDirectory = $this->directory . DIRECTORY_SEPARATOR . $backup->getName();
80
81
        try {
82 14
            $this->filesystem->mkdir($backupDirectory);
83 7
        } catch (\Exception $e) {
84
            throw new DestinationException(sprintf('Unable to create backup directory "%s" for backup "%s" in local destination.', $backupDirectory, $backup->getName()));
85
        }
86
87 14
        $removedBackupFiles = $this->getFiles($backupDirectory);
88
89
        /**
90
         * @var FileInterface $backupFile
91
         */
92 14
        foreach ($backup->getFiles() as $backupFile) {
93
94 14
            if (isset($removedBackupFiles[$backupFile->getRelativePath()])) {
95 2
                unset($removedBackupFiles[$backupFile->getRelativePath()]);
96 1
            }
97
98
            try {
99 14
                $this->filesystem->copy($backupFile->getPath(), sprintf('%s%s%s', $backupDirectory, DIRECTORY_SEPARATOR, $backupFile->getRelativePath()));
100 7
            } catch (\Exception $e) {
101 7
                throw new DestinationException(sprintf('Unable to backup file "%s" to destination "%s".', $backupFile->getPath(), $this->directory), 0, $e);
102
            }
103 7
        }
104
105
        /**
106
         * @var FileInterface $removedBackupFile
107
         */
108 14
        foreach ($removedBackupFiles as $removedBackupFile) {
109
110 2
            $path = $backupDirectory . DIRECTORY_SEPARATOR . $removedBackupFile->getRelativePath();
111
112
            try {
113 2
                $this->filesystem->remove($path);
114 1
            } catch (\Exception $e) {
115 1
                throw new DestinationException(sprintf('Unable to cleanup backup destination "%s" after backup process, file "%s" could not be removed.', $backupDirectory, $path), 0, $e);
116
            }
117 7
        }
118
119 14
        $this->removeEmptyDirectories($backupDirectory);
120
121 14
        if (!empty($this->backups)) {
122
            $this->backups[] = $backup;
123
        }
124 14
    }
125
126
127
    /**
128
     * {@inheritdoc}
129
     */
130 14
    protected function getFiles($path)
131
    {
132 14
        $result = array();
133
134 14
        foreach (Finder::create()->in($path)->files() as $file) {
135 10
            $file = File::fromSplFileInfo($file, $path);
136 10
            $result[$file->getRelativePath()] = $file;
137 7
        }
138
139 14
        return $result;
140
    }
141
142
    /**
143
     * {@inheritdoc}
144
     */
145 10
    protected function load()
146
    {
147 10
        $this->backups = array();
148
149
        /**
150
         * @var \SplFileInfo $backupDirectory
151
         */
152 10
        foreach (Finder::create()->in($this->directory)->depth(0)->directories()->sortByModifiedTime() as $backupDirectory) {
153
154 10
            $backup = new Backup($backupDirectory->getBasename(), $this->getFiles($backupDirectory->getPathname()), 0, $backupDirectory->getCTime(), $backupDirectory->getMTime());
155
156 10
            $this->backups[$backup->getName()] = $backup;
157 5
        }
158 10
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163 14
    protected function removeEmptyDirectories($backupDirectory)
164
    {
165
        /**
166
         * @var \SplFileInfo $dir
167
         */
168 14
        foreach (Finder::create()->directories()->in($backupDirectory)->depth(0) as $dir) {
169
170 2
            if (Finder::create()->files()->in($dir->getPathname())->count() > 0) {
171 2
                $this->removeEmptyDirectories($dir->getPathname());
172 1
            } else {
173 2
                $this->filesystem->remove($dir->getPathname());
174
            }
175 7
        }
176 14
    }
177
}
178