Completed
Push — master ( 1bc9a7...f5328c )
by Sebastian
03:12
created

Target::getSuffixToAppend()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

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