Passed
Pull Request — master (#9)
by ANTHONIUS
02:18
created

Backup::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 6
nc 1
nop 3
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
    /**
60
     * @var Parameters
61
     */
62
    private $parameters;
63
64
    public function __construct(
65
        Parameters $parameters,
66
        LoggerInterface $logger,
67
        OutputInterface $output
68
    ) {
69
        $this->parameters = $parameters;
70
        $this->logger = $logger;
71
        $this->output = $output;
72
        $this->backupDir = $parameters->get('dotfiles.backup_dir').'/var/backup';
73
        $this->manifestFile = $this->backupDir.'/manifest.php';
74
        $this->loadManifest();
75
    }
76
77
    public function getBackupDir()
78
    {
79
        return $this->backupDir;
80
    }
81
82
    public function getManifest()
83
    {
84
        return $this->manifest;
85
    }
86
87
    public static function getSubscribedEvents()
88
    {
89
        return array(
90
            Constant::EVENT_PRE_RESTORE => array('onPreRestore', -255),
91
        );
92
    }
93
94
    public function info()
95
    {
96
        $output = $this->output;
97
        if (!is_dir($this->backupDir)) {
98
            $output->writeln('No backup created yet');
99
100
            return;
101
        }
102
103
        $table = new Table($output);
104
        $table->setHeaders(array('Version', 'Machine', 'Created', 'File'));
105
        foreach ($this->manifest as $info) {
106
            $table->addRow(array(
107
                $info['version'],
108
                $info['machine'],
109
                $info['created'],
110
                $info['file'],
111
            ));
112
        }
113
        $table->render();
114
    }
115
116
    public function onPreRestore(RestoreEvent $event)
117
    {
118
        $files = $event->getFiles();
119
        $patches = $event->getPatches();
120
121
        $affectedFiles = array_merge(
122
            array_keys($files),
123
            array_keys($patches)
124
        );
125
        $affectedFiles = array_unique($affectedFiles);
126
127
        $homeDir = $this->parameters->get('dotfiles.home_dir');
128
129
        $zip = new \ZipArchive();
130
        $time = new \DateTime();
131
        $fileName = $this->backupDir.DIRECTORY_SEPARATOR.$time->format('Y-m-d-H-i-s').'.zip';
132
        $logger = $this->logger;
133
        Toolkit::ensureFileDir($fileName);
134
        $zip->open($fileName, \ZipArchive::CREATE);
135
        $logger->info('created backup in <comment>'.$fileName.'</comment>');
136
        foreach ($affectedFiles as $file) {
137
            $source = $homeDir.DIRECTORY_SEPARATOR.$file;
138
            if (is_file($source)) {
139
                $zip->addFile($source, $file);
140
                $logger->debug('added file to zip: '.$source);
141
            }
142
        }
143
        $zip->close();
144
        $this->addManifest($fileName);
145
    }
146
147
    private function addManifest($backupFile)
148
    {
149
        $time = date_create_from_format('Y-m-d-H-i-s', basename($backupFile, '.zip'));
150
        $machineName = $this->parameters->get('dotfiles.machine_name');
151
        $version = $this->lastVersion + 1;
152
        $this->manifest[] = array(
153
            'machine' => $machineName,
154
            'version' => $version,
155
            'created' => $time->format('Y-m-d H:i:s'),
156
            'file' => basename($backupFile),
157
        );
158
159
        $exported = var_export($this->manifest, true);
160
        $time = new \DateTime();
161
        $template = "<?php\n/* backup manifest updated: %s*/\n\$this->manifest = %s;";
162
        $contents = sprintf($template, $time->format('Y-m-d H:i:s'), $exported);
163
        file_put_contents($this->manifestFile, $contents, LOCK_EX);
164
        $this->loadManifest();
165
    }
166
167
    private function loadManifest()
168
    {
169
        if (is_file($file = $this->backupDir.'/manifest.php')) {
170
            include $file;
171
            $lastVersion = 0;
172
            foreach ($this->manifest as $manifest) {
173
                $version = $manifest['version'];
174
                if ($version > $lastVersion) {
175
                    $lastVersion = $version;
176
                }
177
            }
178
            $this->lastVersion = $lastVersion;
179
        }
180
    }
181
}
182