Completed
Push — master ( 82a55c...f6a4e4 )
by Sebastian
05:58
created

Capacity::getFilesToDelete()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 27
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 27
ccs 13
cts 13
cp 1
rs 8.439
c 0
b 0
f 0
cc 5
eloc 13
nc 4
nop 2
crap 5
1
<?php
2
namespace phpbu\App\Backup\Cleaner;
3
4
use phpbu\App\Backup\Collector;
5
use phpbu\App\Backup\Target;
6
use phpbu\App\Result;
7
use phpbu\App\Util\Arr;
8
use phpbu\App\Util\Str;
9
use RuntimeException;
10
11
/**
12
 * Cleanup backup directory.
13
 *
14
 * Removes oldest backup till the given capacity isn't exceeded anymore.
15
 *
16
 * @package    phpbu
17
 * @subpackage Backup
18
 * @author     Sebastian Feldmann <[email protected]>
19
 * @copyright  Sebastian Feldmann <[email protected]>
20
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
21
 * @link       http://phpbu.de/
22
 * @since      Class available since Release 1.0.0
23
 */
24
class Capacity extends Abstraction implements Simulator
25
{
26
    /**
27
     * Original XML value
28
     *
29
     * @var string
30
     */
31
    protected $capacityRaw;
32
33
    /**
34
     * Capacity in bytes.
35
     *
36
     * @var mixed <integer|double>
37
     */
38
    protected $capacityBytes;
39
40
    /**
41
     * Delete current backup as well
42
     *
43
     * @var bool
44
     */
45
    protected $deleteTarget;
46
47
    /**
48
     * Setup the the Cleaner.
49
     *
50
     * @see    \phpbu\App\Backup\Cleanup::setup()
51
     * @param  array $options
52
     * @throws \phpbu\App\Backup\Cleaner\Exception
53
     */
54 9
    public function setup(array $options)
55
    {
56 9
        if (!isset($options['size'])) {
57 1
            throw new Exception('option \'size\' is missing');
58
        }
59
        try {
60 8
            $bytes = Str::toBytes($options['size']);
61 1
        } catch (RuntimeException $e) {
62 1
            throw new Exception($e->getMessage());
63
        }
64 7
        $this->deleteTarget  = Str::toBoolean(Arr::getValue($options, 'deleteTarget', 'false'), false);
65 7
        $this->capacityRaw   = $options['size'];
66 7
        $this->capacityBytes = $bytes;
67 7
    }
68
69
    /**
70
     * Simulate the cleanup execution.
71
     *
72
     * @param \phpbu\App\Backup\Target    $target
73
     * @param \phpbu\App\Backup\Collector $collector
74
     * @param \phpbu\App\Result           $result
75
     */
76 2
    public function simulate(Target $target, Collector $collector, Result $result)
77
    {
78 2
        $target->setSize('20000000');
79 2
        $result->debug('assuming backup size 20MB');
80
81
        // because there is no target file on disc to read
82
        // we have to deactivate the target handling
83
        // so $targetFile->getMTime or $targetFile->getSize will not be called
84 2
        if ($this->deleteTarget) {
85 1
            $this->deleteTarget = false;
86 1
            $result->debug('target will be deleted as well');
87 1
            $result->debug('delete ' . $target->getPathname());
88
        }
89 2
        parent::simulate($target, $collector, $result);
90 2
    }
91
92
    /**
93
     * Return list of files to delete.
94
     *
95
     * @param  \phpbu\App\Backup\Target    $target
96
     * @param  \phpbu\App\Backup\Collector $collector
97
     * @return \phpbu\App\Backup\File\Local[]
98
     * @throws \phpbu\App\Exception
99
     */
100 6
    protected function getFilesToDelete(Target $target, Collector $collector)
101
    {
102 6
        $files  = $this->getDeletableBackups($target, $collector);
103 6
        $size   = $target->getSize();
104 6
        $delete = [];
105
106
        // sum up the size of all backups
107
        /** @var \phpbu\App\Backup\File\Local $file */
108 6
        foreach ($files as $file) {
109 6
            $size += $file->getSize();
110
        }
111
112
        // check if backups exceed capacity?
113 6
        if ($this->isCapacityExceeded($size)) {
114
            // sort backups by date, oldest first, key 'YYYYMMDDHHIISS-NR-PATH'
115 5
            ksort($files);
116
117 5
            while ($this->isCapacityExceeded($size) && count($files) > 0) {
118
                // get oldest backup from list, move it to delete list
119 5
                $file = array_shift($files);
120 5
                $size -= $file->getSize();
121 5
                $delete[] = $file;
122
            }
123
        }
124
125 6
        return $delete;
126
    }
127
128
    /**
129
     * Return a list of all deletable backups, including the currently created one if configured.
130
     *
131
     * @param  \phpbu\App\Backup\Target    $target
132
     * @param  \phpbu\App\Backup\Collector $collector
133
     * @return \phpbu\App\Backup\File\Local[]
134
     */
135 6
    protected function getDeletableBackups(Target $target, Collector $collector): array
136
    {
137 6
        $files = $collector->getBackupFiles();
138
        // should the currently created backup be deleted as well?
139 6
        if ($this->deleteTarget) {
140 1
            $file          = $target->toFile();
141 1
            $index         = date('YmdHis', $file->getMTime()) . '-' . count($files) . '-' . $file->getPathname();
142 1
            $files[$index] = $file;
143
        }
144 6
        return $files;
145
    }
146
147
    /**
148
     * Is a given size bigger than the configured capacity limit.
149
     *
150
     * @param  int|double $currentCapacity
151
     * @return bool
152
     */
153 6
    protected function isCapacityExceeded($currentCapacity): bool
154
    {
155 6
        return $currentCapacity > $this->capacityBytes;
156
    }
157
}
158