Completed
Push — master ( 3eed6d...7635b2 )
by Sebastian
04:09 queued 01:07
created

Target::shouldBeCompressed()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
namespace phpbu\App\Backup;
3
4
use phpbu\App\Exception;
5
use phpbu\App\Util\Str;
6
7
/**
8
 * Backup Target class.
9
 *
10
 * @package    phpbu
11
 * @subpackage Backup
12
 * @author     Sebastian Feldmann <[email protected]>
13
 * @copyright  Sebastian Feldmann <[email protected]>
14
 * @license    https://opensource.org/licenses/MIT The MIT License (MIT)
15
 * @link       https://phpbu.de/
16
 * @since      Class available since Release 1.0.0
17
 */
18
class Target
19
{
20
    /**
21
     * Absolute path to the directory where to store the backup.
22
     *
23
     * @var string
24
     */
25
    private $path;
26
27
    /**
28
     * Path to the backup with potential date placeholders like %d.
29
     *
30
     * @var string
31
     */
32
    private $pathRaw;
33
34
    /**
35
     * Indicates if the path changes over time.
36
     *
37
     * @var bool
38
     */
39
    private $pathIsChanging = false;
40
41
    /**
42
     * Part of the path without placeholders
43
     *
44
     * @var string
45
     */
46
    private $pathNotChanging;
47
48
    /**
49
     * List of directories containing date placeholders
50
     *
51
     * @var string[]
52
     */
53
    private $pathElementsChanging = [];
54
55
    /**
56
     * Backup filename.
57
     *
58
     * @var string
59
     */
60
    private $filename;
61
62
    /**
63
     * Filename with potential date placeholders like %d.
64
     *
65
     * @var string
66
     */
67
    private $filenameRaw;
68
69
    /**
70
     * List of custom file suffixes f.e. 'tar'
71
     *
72
     * @var string[]
73
     */
74
    private $fileSuffixes = [];
75
76
    /**
77
     * Indicates if the filename changes over time.
78
     *
79
     * @var bool
80
     */
81
    private $filenameIsChanging = false;
82
83
    /**
84
     * Target MIME type
85
     *
86
     * @var string
87
     */
88
    private $mimeType = 'text/plain';
89
90
    /**
91
     * Size in bytes
92
     *
93
     * @var int
94
     */
95
    private $size;
96
97
    /**
98
     * Should the file be compressed.
99
     *
100
     * @var bool
101
     */
102
    private $compress = false;
103
104
    /**
105
     * File compression.
106
     *
107
     * @var \phpbu\App\Backup\Target\Compression
108
     */
109
    private $compression;
110
111
    /**
112
     * Should the file be encrypted.
113
     *
114
     * @var bool
115
     */
116
    private $crypt = false;
117
118
    /**
119
     * File crypter.
120
     *
121
     * @var \phpbu\App\Backup\Crypter
122
     */
123
    private $crypter;
124
125
    /**
126
     * Constructor.
127
     *
128
     * @param  string  $path
129
     * @param  string  $filename
130
     * @param  integer $time
131
     * @throws \phpbu\App\Exception
132
     */
133 48
    public function __construct($path, $filename, $time = null)
134
    {
135 48
        $this->setPath($path, $time);
136 48
        $this->setFile($filename, $time);
137 48
    }
138
139
    /**
140
     * Directory setter.
141
     *
142
     * @param  string $path
143
     * @param  int    $time
144
     * @throws \phpbu\App\Exception
145
     */
146 48
    public function setPath($path, $time = null)
147
    {
148 48
        $this->pathRaw = $path;
149 48
        if (Str::isContainingPlaceholder($path)) {
150 10
            $this->pathIsChanging = true;
151 10
            $this->detectChangingPathElements($path);
152
            // replace potential date placeholder
153 10
            $path = Str::replaceDatePlaceholders($path, $time);
154
        } else {
155 38
            $this->pathNotChanging = $path;
156
        }
157 48
        $this->path = rtrim($path, DIRECTORY_SEPARATOR);
158 48
    }
159
160
    /**
161
     * Find path elements that can change because of placeholder usage.
162
     *
163
     * @param string $path
164
     */
165 10
    private function detectChangingPathElements(string $path)
166
    {
167
        // path should be absolute so we remove the root slash to prevent empty first element
168 10
        $dirs = explode('/', substr($path, 1));
169
170
        // check all path elements for placeholders
171
        // this is important to effectively generate search regex to collect backups
172 10
        $this->pathNotChanging = '';
173 10
        $foundChangingElement  = false;
174 10
        foreach ($dirs as $d) {
175
            // already found placeholder or found one right now
176
            // if not add directory to not changing part of the path
177 10
            if ($foundChangingElement || Str::isContainingPlaceholder($d)) {
178 10
                $this->pathElementsChanging[] = $d;
179 10
                $foundChangingElement         = true;
180
            } else {
181 10
                $this->pathNotChanging .= DIRECTORY_SEPARATOR . $d;
182
            }
183
        }
184 10
    }
185
186
    /**
187
     * Filename setter.
188
     *
189
     * @param string $file
190
     * @param int    $time
191
     */
192 48
    public function setFile($file, $time = null)
193
    {
194 48
        $this->filenameRaw = $file;
195 48
        if (Str::isContainingPlaceholder($file)) {
196 27
            $this->filenameIsChanging = true;
197 27
            $file                     = Str::replaceDatePlaceholders($file, $time);
198
        }
199 48
        $this->filename = $file;
200 48
    }
201
202
    /**
203
     * Append another suffix to the filename.
204
     *
205
     * @param string $suffix
206
     */
207 3
    public function appendFileSuffix(string $suffix)
208
    {
209 3
        $this->fileSuffixes[] = $suffix;
210 3
    }
211
212
    /**
213
     * Checks if the backup target directory is writable.
214
     * Creates the Directory if it doesn't exist.
215
     *
216
     * @throws \phpbu\App\Exception
217
     */
218 11
    public function setupPath()
219
    {
220
        // if directory doesn't exist, create it
221 11
        if (!is_dir($this->path)) {
222 2
            $reporting = error_reporting();
223 2
            error_reporting(0);
224 2
            $created = mkdir($this->path, 0755, true);
225 2
            error_reporting($reporting);
226 2
            if (!$created) {
227 1
                throw new Exception(sprintf('cant\'t create directory: %s', $this->path));
228
            }
229
        }
230 10
        if (!is_writable($this->path)) {
231 1
            throw new Exception(sprintf('no write permission for directory: %s', $this->path));
232
        }
233 9
    }
234
235
    /**
236
     * Target file MIME type setter.
237
     *
238
     * @param string $mime
239
     */
240 1
    public function setMimeType(string $mime)
241
    {
242 1
        $this->mimeType = $mime;
243 1
    }
244
245
    /**
246
     * Return the path to the backup file.
247
     *
248
     * @return string
249
     */
250 3
    public function getPath() : string
251
    {
252 3
        return $this->path;
253
    }
254
255
    /**
256
     * Return the path to the backup file.
257
     *
258
     * @return string
259
     */
260 1
    public function getPathRaw() : string
261
    {
262 1
        return $this->pathRaw;
263
    }
264
265
    /**
266
     * Return the name to the backup file.
267
     *
268
     * @param  bool $plain
269
     * @return string
270
     */
271 19
    public function getFilename(bool $plain = false) : string
272
    {
273 19
        return $this->filename . $this->getFilenameSuffix($plain);
274
    }
275
276
    /**
277
     * Return the name of the backup file without compressor or encryption suffix.
278
     *
279
     * @return string
280
     */
281 1
    public function getFilenamePlain() : string
282
    {
283 1
        return $this->getFilename(true);
284
    }
285
286
    /**
287
     * Return the raw name of the backup file incl. date placeholder.
288
     *
289
     * @param  bool $plain
290
     * @return string
291
     */
292 8
    public function getFilenameRaw($plain = false) : string
293
    {
294 8
        return $this->filenameRaw . $this->getFilenameSuffix($plain);
295
    }
296
297
    /**
298
     * Return custom file suffix like '.tar'.
299
     *
300
     * @param  bool $plain
301
     * @return string
302
     */
303 19
    public function getFilenameSuffix($plain = false) : string
304
    {
305 19
        return $this->getSuffixToAppend() . ($plain ? '' : $this->getCompressionSuffix() . $this->getCrypterSuffix());
306
    }
307
308
    /**
309
     * Return added suffixes.
310
     *
311
     * @return string
312
     */
313 19
    public function getSuffixToAppend() : string
314
    {
315 19
        return count($this->fileSuffixes) ? '.' . implode('.', $this->fileSuffixes) : '';
316
    }
317
318
    /**
319
     * Return the compressor suffix.
320
     *
321
     * @return string
322
     */
323 17
    public function getCompressionSuffix() : string
324
    {
325 17
        return $this->shouldBeCompressed() ? '.' . $this->compression->getSuffix() : '';
326
    }
327
328
    /**
329
     * Return the crypter suffix.
330
     *
331
     * @return string
332
     */
333 17
    public function getCrypterSuffix() : string
334
    {
335 17
        return $this->shouldBeEncrypted() ? '.' . $this->crypter->getSuffix() : '';
336
    }
337
338
    /**
339
     * Return file MIME type.
340
     *
341
     * @return string
342
     */
343 3
    public function getMimeType() : string
344
    {
345 3
        $mimeType = $this->mimeType;
346 3
        if ($this->shouldBeCompressed()) {
347 1
            $mimeType = $this->compression->getMimeType();
348
        }
349 3
        return $mimeType;
350
    }
351
352
    /**
353
     * Size setter.
354
     *
355
     * @param int $size
356
     */
357 1
    public function setSize(int $size)
358
    {
359 1
        $this->size = $size;
360 1
    }
361
362
    /**
363
     * Return the actual file size in bytes.
364
     *
365
     * @return int
366
     * @throws \phpbu\App\Exception
367
     */
368 3
    public function getSize() : int
369
    {
370 3
        if (null === $this->size) {
371 2
            if (!file_exists($this)) {
372 1
                throw new Exception(sprintf('target file \'%s\' doesn\'t exist', $this->getFilename()));
373
            }
374 1
            $this->size = filesize($this);
375
        }
376 2
        return $this->size;
377
    }
378
379
    /**
380
     * Target file exists already.
381
     *
382
     * @param  bool $plain
383
     * @return bool
384
     */
385 1
    public function fileExists(bool $plain = false) : bool
386
    {
387 1
        return file_exists($this->getPathname($plain));
388
    }
389
390
    /**
391
     * Return as backup file object.
392
     *
393
     * @return \phpbu\App\Backup\File
394
     */
395 1
    public function toFile() : File
396
    {
397 1
        return new File(new \SplFileInfo($this->getPathname()));
398
    }
399
400
    /**
401
     * Return path and filename of the backup file.
402
     *
403
     * @param  bool $plain
404
     * @return string
405
     */
406 13
    public function getPathname(bool $plain = false) : string
407
    {
408 13
        return $this->path . DIRECTORY_SEPARATOR . $this->getFilename($plain);
409
    }
410
411
    /**
412
     * Return path and plain filename of the backup file.
413
     *
414
     * @return string
415
     */
416 1
    public function getPathnamePlain() : string
417
    {
418 1
        return $this->getPathname(true);
419
    }
420
421
    /**
422
     * Is dirname configured with any date placeholders.
423
     *
424
     * @return bool
425
     */
426 3
    public function hasChangingPath() : bool
427
    {
428 3
        return $this->pathIsChanging;
429
    }
430
431
    /**
432
     * Return the part of the path that is not changing.
433
     *
434
     * @return string
435
     */
436 8
    public function getPathThatIsNotChanging() : string
437
    {
438 8
        return $this->pathNotChanging;
439
    }
440
441
    /**
442
     * Changing path elements getter.
443
     *
444
     * @return array
445
     */
446 6
    public function getChangingPathElements() : array
447
    {
448 6
        return $this->pathElementsChanging;
449
    }
450
451
    /**
452
     * Return amount of changing path elements.
453
     *
454
     * @return int
455
     */
456 11
    public function countChangingPathElements() : int
457
    {
458 11
        return count($this->pathElementsChanging);
459
    }
460
461
    /**
462
     * Filename configured with any date placeholders.
463
     *
464
     * @return bool
465
     */
466 2
    public function hasChangingFilename() : bool
467
    {
468 2
        return $this->filenameIsChanging;
469
    }
470
471
    /**
472
     * Disable file compression.
473
     */
474 2
    public function disableCompression()
475
    {
476 2
        $this->compress = false;
477 2
    }
478
479
    /**
480
     * Enable file compression.
481
     *
482
     * @throws \phpbu\App\Exception
483
     */
484 2
    public function enableCompression()
485
    {
486 2
        if (null == $this->compression) {
487 1
            throw new Exception('can\'t enable compression without a compressor');
488
        }
489 1
        $this->compress = true;
490 1
    }
491
492
    /**
493
     * Compression setter.
494
     *
495
     * @param \phpbu\App\Backup\Target\Compression $compression
496
     */
497 19
    public function setCompression(Target\Compression $compression)
498
    {
499 19
        $this->compression = $compression;
500 19
        $this->compress    = true;
501 19
    }
502
503
    /**
504
     * Compressor getter.
505
     *
506
     * @return \phpbu\App\Backup\Target\Compression
507
     */
508 1
    public function getCompression() : Target\Compression
509
    {
510 1
        return $this->compression;
511
    }
512
513
    /**
514
     * Is a compressor set?
515
     *
516
     * @return bool
517
     */
518 22
    public function shouldBeCompressed() : bool
519
    {
520 22
        return $this->compress !== false;
521
    }
522
523
    /**
524
     * Crypter setter.
525
     *
526
     * @param \phpbu\App\Backup\Crypter $crypter
527
     */
528 3
    public function setCrypter(Crypter $crypter)
529
    {
530 3
        $this->crypter = $crypter;
531 3
        $this->crypt   = true;
532 3
    }
533
534
    /**
535
     * Crypter getter.
536
     *
537
     * @return \phpbu\App\Backup\Crypter
538
     */
539 1
    public function getCrypter() : Crypter
540
    {
541 1
        return $this->crypter;
542
    }
543
544
    /**
545
     * Disable file encryption.
546
     */
547 1
    public function disableEncryption()
548
    {
549 1
        $this->crypt = false;
550 1
    }
551
552
    /**
553
     * Is a crypter set?
554
     *
555
     * @return bool
556
     */
557 18
    public function shouldBeEncrypted() : bool
558
    {
559 18
        return $this->crypt !== false;
560
    }
561
562
    /**
563
     * Magic to string method.
564
     *
565
     * @return string
566
     */
567 2
    public function __toString() : string
568
    {
569 2
        return $this->getPathname();
570
    }
571
}
572