Completed
Push — master ( 9bc3b7...a15851 )
by Harry
02:46
created

MergeFiles::contract()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 50
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 7

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 50
ccs 29
cts 29
cp 1
rs 6.7272
cc 7
eloc 31
nc 5
nop 3
crap 7
1
<?php
2
3
namespace Graze\DataFile\Modify\Contract;
4
5
use DirectoryIterator;
6
use Graze\DataFile\Helper\GetOptionTrait;
7
use Graze\DataFile\Helper\OptionalLoggerTrait;
8
use Graze\DataFile\Helper\Process\ProcessFactoryAwareInterface;
9
use Graze\DataFile\Helper\Process\ProcessTrait;
10
use Graze\DataFile\Modify\Compress\CompressionType;
11
use Graze\DataFile\Modify\MakeDirectory;
12
use Graze\DataFile\Node\FileNodeCollectionInterface;
13
use Graze\DataFile\Node\FileNodeInterface;
14
use Graze\DataFile\Node\LocalFile;
15
use Psr\Log\LoggerAwareInterface;
16
use Psr\Log\LogLevel;
17
use Symfony\Component\Process\Exception\ProcessFailedException;
18
19
class MergeFiles implements FileContractorInterface, LoggerAwareInterface, ProcessFactoryAwareInterface
20
{
21
    use GetOptionTrait;
22
    use OptionalLoggerTrait;
23
    use ProcessTrait;
24
25
    /**
26
     * @param FileNodeCollectionInterface $files
27
     *
28
     * @return bool
29
     */
30 11
    public function canContract(FileNodeCollectionInterface $files)
31
    {
32 11
        foreach ($files->getIterator() as $file) {
33 10
            if (!($file instanceof LocalFile) ||
34 10
                !($file->exists()) ||
35 10
                ($file->getCompression() != CompressionType::NONE)
36
            ) {
37 10
                return false;
38
            }
39
        }
40 10
        return true;
41
    }
42
43
    /**
44
     * Do the expansion and return a collection
45
     *
46
     * @param FileNodeCollectionInterface $files
47
     * @param FileNodeInterface           $file
48
     * @param array                       $options :keepOldFiles <bool> (Default: true) Keep the old files after merging
49
     *
50
     * @return FileNodeInterface
51
     */
52 7
    public function contract(
53
        FileNodeCollectionInterface $files,
54
        FileNodeInterface $file,
55
        array $options = []
56
    ) {
57 7
        $this->options = $options;
58 7
        if (!$this->canContract($files)) {
59 1
            throw new \InvalidArgumentException("The supplied files are not valid");
60
        }
61 6
        if (!($file instanceof LocalFile)) {
62 1
            throw new \InvalidArgumentException("The supplied file should be a local file");
63
        }
64
65 5
        $this->log(LogLevel::INFO, "Merging files in collection $files into: {$file}");
66
67
        $filePaths = $files->map(function (LocalFile $item) {
68 5
            return $item->getPath();
69 5
        });
70
71 5
        $cmd = sprintf(
72 5
            'cat %s > %s',
73 5
            implode(' ', $filePaths),
74 5
            $file->getPath()
75
        );
76
77 5
        $maker = new MakeDirectory();
78 5
        $maker->makeDirectory($file);
79
80 5
        $process = $this->getProcess($cmd);
81 5
        $process->run();
82
83 5
        if (!$process->isSuccessful()) {
84 1
            throw new ProcessFailedException($process);
85
        }
86
87 4
        if (!$this->getOption('keepOldFiles', true)) {
88 2
            $this->log(LogLevel::DEBUG, "Deleting old files in collection $files");
89 2
            $files->map(function (LocalFile $item) {
90 2
                if ($item->exists()) {
91 2
                    $item->delete();
92
                }
93 2
                $count = iterator_count(new DirectoryIterator($item->getDirectory()));
94 2
                if ($count == 2) {
95 2
                    rmdir($item->getDirectory());
96
                }
97 2
            });
98
        }
99
100 4
        return $file;
101
    }
102
}
103