Completed
Pull Request — master (#9)
by ANTHONIUS
02:53
created

Backup::getBackupDir()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
eloc 1
nc 1
nop 0
1
<?php
2
3
/*
4
 * This file is part of the dotfiles project.
5
 *
6
 *     (c) Anthonius Munthi <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Dotfiles\Core\Processor;
13
14
use Dotfiles\Core\Constant;
15
use Dotfiles\Core\DI\Parameters;
16
use Dotfiles\Core\Event\RestoreEvent;
17
use Dotfiles\Core\Util\BackupManifest;
18
use Dotfiles\Core\Util\Toolkit;
19
use Psr\Log\LoggerInterface;
20
use Symfony\Component\Console\Helper\Table;
21
use Symfony\Component\Console\Output\OutputInterface;
22
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
23
24
/**
25
 * Backing up all related files before restore process.
26
 */
27
class Backup implements EventSubscriberInterface
28
{
29
    /**
30
     * @var string
31
     */
32
    private $backupDir;
33
34
    /**
35
     * @var int
36
     */
37
    private $lastVersion = 0;
38
39
    /**
40
     * @var LoggerInterface
41
     */
42
    private $logger;
43
44
    /**
45
     * @var BackupManifest
46
     */
47
    private $manifest;
48
49
    /**
50
     * @var string
51
     */
52
    private $manifestFile;
53
54
    /**
55
     * @var OutputInterface
56
     */
57
    private $output;
58
    /**
59
     * @var Parameters
60
     */
61
    private $parameters;
62
63
    public function __construct(
64
        Parameters $parameters,
65
        LoggerInterface $logger,
66
        OutputInterface $output
67
    ) {
68
        $this->parameters = $parameters;
69
        $this->logger = $logger;
70
        $this->output = $output;
71
        $this->backupDir = $parameters->get('dotfiles.backup_dir').'/var/backup';
72
        $this->manifestFile = $this->backupDir.'/manifest.php';
73
        $this->loadManifest();
74
    }
75
76
    public function getBackupDir()
77
    {
78
        return $this->backupDir;
79
    }
80
81
    public function getManifest()
82
    {
83
        return $this->manifest;
84
    }
85
86
    public static function getSubscribedEvents()
87
    {
88
        return array(
89
            Constant::EVENT_PRE_RESTORE => array('onPreRestore', -255),
90
        );
91
    }
92
93
    public function info()
94
    {
95
        $output = $this->output;
96
        if (!is_dir($this->backupDir)) {
97
            $output->writeln('No backup created yet');
98
99
            return;
100
        }
101
102
        $table = new Table($output);
103
        $table->setHeaders(array('Version', 'Machine', 'Created', 'File'));
104
        foreach ($this->manifest as $info) {
105
            $table->addRow(array(
106
                $info['version'],
107
                $info['machine'],
108
                $info['created'],
109
                $info['file'],
110
            ));
111
        }
112
        $table->render();
113
    }
114
115
    public function onPreRestore(RestoreEvent $event)
116
    {
117
        $files = $event->getFiles();
118
        $patches = $event->getPatches();
119
120
        $affectedFiles = array_merge(
121
            array_keys($files),
122
            array_keys($patches)
123
        );
124
        $affectedFiles = array_unique($affectedFiles);
125
126
        $homeDir = $this->parameters->get('dotfiles.home_dir');
127
128
        $zip = new \ZipArchive();
129
        $time = new \DateTime();
130
        $fileName = $this->backupDir.DIRECTORY_SEPARATOR.$time->format('Y-m-d-H-i-s').'.zip';
131
        $logger = $this->logger;
132
        Toolkit::ensureFileDir($fileName);
133
        $zip->open($fileName, \ZipArchive::CREATE);
134
        $logger->info('created backup in <comment>'.$fileName.'</comment>');
135
        foreach ($affectedFiles as $file) {
136
            $source = $homeDir.DIRECTORY_SEPARATOR.$file;
137
            if (is_file($source)) {
138
                $zip->addFile($source, $file);
139
                $logger->debug('added file to zip: '.$source);
140
            }
141
        }
142
        $zip->close();
143
        $this->addManifest($fileName);
144
    }
145
146
    private function addManifest($backupFile)
147
    {
148
        $time = date_create_from_format('Y-m-d-H-i-s', basename($backupFile, '.zip'));
149
        $machineName = $this->parameters->get('dotfiles.machine_name');
150
        $version = $this->lastVersion + 1;
151
        $this->manifest[] = array(
152
            'machine' => $machineName,
153
            'version' => $version,
154
            'created' => $time->format('Y-m-d H:i:s'),
155
            'file' => basename($backupFile),
156
        );
157
158
        $exported = var_export($this->manifest, true);
159
        $time = new \DateTime();
160
        $template = "<?php\n/* backup manifest updated: %s*/\n\$this->manifest = %s;";
161
        $contents = sprintf($template, $time->format('Y-m-d H:i:s'), $exported);
162
        file_put_contents($this->manifestFile, $contents, LOCK_EX);
163
        $this->loadManifest();
164
    }
165
166
    private function loadManifest()
167
    {
168
        if (is_file($file = $this->backupDir.'/manifest.php')) {
169
            include $file;
170
            $lastVersion = 0;
171
            foreach ($this->manifest as $manifest) {
172
                $version = $manifest['version'];
173
                if ($version > $lastVersion) {
174
                    $lastVersion = $version;
175
                }
176
            }
177
            $this->lastVersion = $lastVersion;
178
        }
179
    }
180
}
181