Completed
Push — master ( db462f...236d2e )
by Sebastian
03:01
created

Target::getFilenameRaw()   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
c 0
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
namespace phpbu\App\Backup;
3
4
use phpbu\App\Backup\File\Local;
5
use phpbu\App\Exception;
6
use phpbu\App\Util\Cli;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, phpbu\App\Backup\Cli.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

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