MultiPartTransformer   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 162
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 6
dl 0
loc 162
ccs 0
cts 82
cp 0
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
B transform() 0 24 5
A needsTransforming() 0 4 1
A isPartFile() 0 4 1
A getPartFiles() 0 19 4
B breakup() 0 32 5
A startPart() 0 6 1
A endPart() 0 4 1
1
<?php
2
3
namespace TreeHouse\Feeder\Resource\Transformer;
4
5
use TreeHouse\Feeder\Reader\ReaderInterface;
6
use TreeHouse\Feeder\Resource\FileResource;
7
use TreeHouse\Feeder\Resource\ResourceCollection;
8
use TreeHouse\Feeder\Resource\ResourceInterface;
9
use TreeHouse\Feeder\Transport\FileTransport;
10
use TreeHouse\Feeder\Writer\WriterInterface;
11
12
class MultiPartTransformer implements ResourceTransformerInterface
13
{
14
    /**
15
     * @var ReaderInterface
16
     */
17
    protected $reader;
18
19
    /**
20
     * @var WriterInterface
21
     */
22
    protected $writer;
23
24
    /**
25
     * @var int
26
     */
27
    protected $size;
28
29
    /**
30
     * @var int|null
31
     */
32
    protected $maxParts;
33
34
    /**
35
     * @param ReaderInterface $reader
36
     * @param WriterInterface $writer
37
     * @param int             $size
38
     * @param int             $maxParts
39
     */
40
    public function __construct(ReaderInterface $reader, WriterInterface $writer, $size = 1000, $maxParts = null)
41
    {
42
        $this->reader = $reader;
43
        $this->writer = $writer;
44
        $this->size = $size;
45
        $this->maxParts = $maxParts;
46
    }
47
48
    /**
49
     * @inheritdoc
50
     */
51
    public function transform(ResourceInterface $resource, ResourceCollection $collection)
52
    {
53
        // break up again
54
        $files = $this->breakup($resource);
55
56
        $resources = [];
57
        foreach ($files as $file) {
58
            $transport = FileTransport::create($file);
59
            $transport->setDestination($file);
60
            $resources[] = new FileResource($transport);
61
62
            if (($this->maxParts > 0) && (sizeof($resources) >= $this->maxParts)) {
63
                break;
64
            }
65
        }
66
67
        if ($resources) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $resources of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
68
            $collection->unshiftAll($resources);
69
70
            return $collection->shift();
71
        }
72
73
        return $resource;
74
    }
75
76
    /**
77
     * @inheritdoc
78
     */
79
    public function needsTransforming(ResourceInterface $resource)
80
    {
81
        return !$this->isPartFile($resource);
82
    }
83
84
    /**
85
     * @param ResourceInterface $resource
86
     *
87
     * @return int
88
     */
89
    protected function isPartFile(ResourceInterface $resource)
90
    {
91
        return preg_match('/\.part(\d+)$/', $resource->getFile()->getBasename());
92
    }
93
94
    /**
95
     * @param ResourceInterface $resource
96
     *
97
     * @return array
98
     */
99
    protected function getPartFiles(ResourceInterface $resource)
100
    {
101
        $files = [];
102
103
        $originalFile = $resource->getFile();
104
        $regex = sprintf('/^%s\.part(\d+)$/', preg_quote($originalFile->getBasename(), '/'));
105
        $finder = new \DirectoryIterator($originalFile->getPath());
106
107
        /** @var $file \SplFileInfo */
108
        foreach ($finder as $file) {
109
            if ($file->isFile() && preg_match($regex, $file->getBaseName(), $matches)) {
110
                $files[(int) $matches[1]] = $file->getPathname();
111
            }
112
        }
113
114
        ksort($files);
115
116
        return $files;
117
    }
118
119
    /**
120
     * @param ResourceInterface $resource
121
     *
122
     * @return array
123
     */
124
    protected function breakup(ResourceInterface $resource)
125
    {
126
        $originalFile = $resource->getFile();
127
        $baseFile = $originalFile->getPathname();
128
129
        $this->reader->setResources(new ResourceCollection([$resource]));
130
131
        $partCount = 0;
132
        $started = false;
133
        while ($this->reader->valid()) {
134
            if ($this->reader->key() % $this->size === 0) {
135
                if ($this->reader->key() > 0) {
136
                    $this->endPart();
137
                }
138
139
                $file = sprintf('%s.part%s', $baseFile, ++$partCount);
140
                $this->startPart($file);
141
                $started = true;
142
            }
143
144
            $this->writer->write($this->reader->current());
145
            $this->writer->flush();
146
147
            $this->reader->next();
148
        }
149
        
150
        if ($started) {
151
            $this->endPart();
152
        }
153
154
        return $this->getPartFiles($resource);
155
    }
156
157
    /**
158
     * @param string $file
159
     */
160
    protected function startPart($file)
161
    {
162
        $this->writer = clone($this->writer);
163
        $this->writer->setFile(new \SplFileObject($file, 'w'));
164
        $this->writer->start();
165
    }
166
167
    /**
168
     */
169
    protected function endPart()
170
    {
171
        $this->writer->end();
172
    }
173
}
174