Processing::init()   B
last analyzed

Complexity

Conditions 8
Paths 6

Size

Total Lines 45
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 8

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 30
c 1
b 0
f 0
nc 6
nop 4
dl 0
loc 45
ccs 27
cts 27
cp 1
crap 8
rs 8.1954
1
<?php
2
3
namespace kalanis\UploadPerPartes\Target\Local;
4
5
6
use kalanis\UploadPerPartes\Traits\TLang;
7
use kalanis\UploadPerPartes\UploadException;
8
use kalanis\UploadPerPartes\Interfaces;
9
use kalanis\UploadPerPartes\Responses;
10
use kalanis\UploadPerPartes\Uploader;
11
12
13
/**
14
 * Class Processing
15
 * @package kalanis\UploadPerPartes\Target\Local
16
 * Main library for processing upload per-partes
17
 */
18
class Processing implements Interfaces\IOperations
19
{
20
    use TLang;
21
22
    /** @var Uploader\Config */
23
    protected Uploader\Config $uploadConfig;
24
    /** @var Uploader\DataPack */
25
    protected Uploader\DataPack $dataPack;
26
    /** @var Uploader\Calculates */
27
    protected Uploader\Calculates $calculates;
28
    /** @var DrivingFile\DrivingFile */
29
    protected DrivingFile\DrivingFile $drivingFile;
30
    /** @var TemporaryStorage\TemporaryStorage */
31
    protected TemporaryStorage\TemporaryStorage $tempStorage;
32
    /** @var FinalStorage\FinalStorage */
33
    protected FinalStorage\FinalStorage $finalStorage;
34
    /** @var Responses\Factory */
35
    protected Responses\Factory $responseFactory;
36
    /** @var Checksums\Factory */
37
    protected Checksums\Factory $checksumFactory;
38
    /** @var ContentDecoders\Factory */
39
    protected ContentDecoders\Factory $decoderFactory;
40
41
    /**
42
     * @param Uploader\Config $config
43
     * @param Interfaces\IUppTranslations|null $lang
44
     * @throws UploadException
45
     */
46 18
    public function __construct(
47
        Uploader\Config $config,
48
        ?Interfaces\IUppTranslations $lang = null
49
    )
50
    {
51 18
        $this->uploadConfig = $config;
52 18
        $this->dataPack = new Uploader\DataPack(new Uploader\Data());
53 18
        $this->calculates = new Uploader\Calculates($config);
54 18
        $this->drivingFile = (new DrivingFile\Factory($lang))->getDrivingFile($config);
55 18
        $this->tempStorage = (new TemporaryStorage\Factory($lang))->getTemporaryStorage($config);
56 18
        $this->finalStorage = (new FinalStorage\Factory($lang))->getFinalStorage($config);
57 18
        $this->responseFactory = new Responses\Factory($lang);
58 18
        $this->checksumFactory = new Checksums\Factory($lang);
59 18
        $this->decoderFactory = new ContentDecoders\Factory($lang);
60 18
    }
61
62
    /**
63
     * Upload file by parts, create driving file
64
     * @param string $targetPath
65
     * @param string $targetFileName posted file name
66
     * @param int<0, max> $length complete file size
67
     * @param string $clientData stored string from client
68
     * @throws UploadException
69
     * @return Responses\BasicResponse
70
     */
71 15
    public function init(string $targetPath, string $targetFileName, int $length, string $clientData = '̈́'): Responses\BasicResponse
72
    {
73 15
        if (empty($targetFileName)) {
74 1
            throw new UploadException($this->getUppLang()->uppSentNameIsEmpty());
75
        }
76 14
        $initialData = $this->dataPack->fillSizes(
77 14
            $this->dataPack->create(
78 14
                $targetPath,
79
                $targetFileName,
80
                $length
81
            ),
82 14
            $this->calculates->calcParts($length),
83 14
            $this->calculates->getBytesPerPart(),
84
            0
85
        );
86 14
        $data = $this->tempStorage->fillData($this->dataPack->fillTempData(
87 14
            $initialData,
88 14
            $this->uploadConfig
89
        ));
90
91 14
        $alreadyKnown = false;
92 14
        if ($this->drivingFile->existsByData($data)) {
93 2
            $currentKey = $this->drivingFile->keyByData($data);
94 2
            if (!$this->uploadConfig->canContinue) {
95 1
                throw new UploadException($this->getUppLang()->uppDriveFileAlreadyExists($currentKey));
96
            }
97 1
            $data = $this->drivingFile->get($currentKey);
98 1
            $alreadyKnown = true;
99
        }
100
101 14
        if ($this->tempStorage->exists($data) && !$alreadyKnown) {
102 1
            $this->tempStorage->remove($data);
103
        }
104
105 14
        $response = $this->responseFactory->getResponse(Responses\Factory::RESPONSE_INIT);
106
        /** @var Responses\InitResponse $response */
107
        return $response
108 14
            ->setInitData(
109 14
                $data,
110 14
                $this->uploadConfig->decoder ? strval($this->uploadConfig->decoder) : 'base64',
111 14
                $this->uploadConfig->checksum ? strval($this->uploadConfig->checksum) : 'md5'
112
            )
113 14
            ->setBasics(
114 14
                $this->drivingFile->storeByData($data),
115
                $clientData
116
            )
117
        ;
118
    }
119
120
    /**
121
     * Check already uploaded parts
122
     * @param string $serverData
123
     * @param int<0, max> $segment
124
     * @param string $method
125
     * @param string $clientData stored string from client
126
     * @throws UploadException
127
     * @return Responses\BasicResponse
128
     */
129 2
    public function check(string $serverData, int $segment, string $method, string $clientData = ''): Responses\BasicResponse
130
    {
131 2
        $data = $this->drivingFile->get($serverData);
132 2
        $checksumClass = $this->checksumFactory->getChecksum($method);
133 2
        $response = $this->responseFactory->getResponse(Responses\Factory::RESPONSE_CHECK);
134
        /** @var Responses\CheckResponse $response */
135
        return $response
136 2
            ->setChecksum(
137 2
                $checksumClass->getMethod(),
138 2
                $checksumClass->checksum(
139 2
                    $this->tempStorage->checksumData(
140 2
                        $data,
141 2
                        $this->calculates->bytesFromSegment($data, $segment)
142
                    )
143
                )
144
            )
145 1
            ->setBasics($this->drivingFile->storeByData($data), $clientData)
146
        ;
147
    }
148
149
    /**
150
     * Delete problematic segments
151
     * @param string $serverData stored string for server
152
     * @param int<0, max> $segment
153
     * @param string $clientData stored string from client
154
     * @throws UploadException
155
     * @return Responses\BasicResponse
156
     */
157 3
    public function truncate(string $serverData, int $segment, string $clientData = ''): Responses\BasicResponse
158
    {
159 3
        $data = $this->drivingFile->get($serverData);
160 3
        if ($data->lastKnownPart < $segment) {
161 1
            throw new UploadException($this->getUppLang()->uppSegmentOutOfBounds($segment));
162
        }
163 2
        if (!$this->tempStorage->truncate($data, $this->calculates->bytesFromSegment($data, $segment))) {
164 1
            throw new UploadException($this->getUppLang()->uppCannotTruncateFile($data->targetName));
165
        }
166 1
        $response = $this->responseFactory->getResponse(Responses\Factory::RESPONSE_TRUNCATE);
167
        /** @var Responses\LastKnownResponse $response */
168
        return $response
169 1
            ->setLastKnown($segment)
170 1
            ->setBasics($this->drivingFile->storeByData($this->dataPack->lastKnown($data, $segment)), $clientData)
171
        ;
172
    }
173
174
    /**
175
     * Upload file by parts, use driving file
176
     * @param string $serverData stored string for server
177
     * @param string $content binary content
178
     * @param string $method how the content is encoded
179
     * @param string $clientData stored string from client
180
     * @throws UploadException
181
     * @return Responses\BasicResponse
182
     */
183 4
    public function upload(string $serverData, string $content, string $method, string $clientData = ''): Responses\BasicResponse
184
    {
185 4
        $data = $this->drivingFile->get($serverData);
186 4
        if (!$this->tempStorage->upload($data, $this->decoderFactory->getDecoder($method)->decode($content))) {
187 1
            throw new UploadException($this->getUppLang()->uppCannotWriteFile($data->targetName));
188
        }
189 3
        $segment = $this->dataPack->nextSegment($data);
190 3
        $response = $this->responseFactory->getResponse(Responses\Factory::RESPONSE_TRUNCATE);
191
        /** @var Responses\LastKnownResponse $response */
192
        return $response
193 3
            ->setLastKnown($segment)
194 3
            ->setBasics($this->drivingFile->storeByData($this->dataPack->lastKnown($data, $segment)), $clientData)
195
        ;
196
    }
197
198
    /**
199
     * Upload file by parts, final status
200
     * @param string $serverData stored string for server
201
     * @param string $clientData stored string from client
202
     * @throws UploadException
203
     * @return Responses\BasicResponse
204
     */
205 6
    public function done(string $serverData, string $clientData = ''): Responses\BasicResponse
206
    {
207 6
        $data = $this->drivingFile->get($serverData);
208 5
        $key = $this->finalStorage->findName($data);
209 5
        if (!$this->finalStorage->store($key, $this->tempStorage->read($data))) {
210 1
            throw new UploadException($this->getUppLang()->uppCannotWriteFile($data->targetName));
211
        }
212 4
        if (!$this->tempStorage->remove($data)) {
213 1
            throw new UploadException($this->getUppLang()->uppCannotRemoveData($data->targetName));
214
        }
215 3
        if (!$this->drivingFile->removeByData($data)) {
216 1
            throw new UploadException($this->getUppLang()->uppDriveFileCannotRemove($data->targetName));
217
        }
218 2
        $response = $this->responseFactory->getResponse(Responses\Factory::RESPONSE_DONE);
219
        /** @var Responses\DoneResponse $response */
220
        return $response
221 2
            ->setFinalName($key)
222 2
            ->setBasics($serverData, $clientData)
223
        ;
224
    }
225
226
    /**
227
     * Upload file by parts, cancel process
228
     * @param string $serverData stored string for server
229
     * @param string $clientData stored string from client
230
     * @throws UploadException
231
     * @return Responses\BasicResponse
232
     */
233 6
    public function cancel(string $serverData, string $clientData = ''): Responses\BasicResponse
234
    {
235 6
        $data = $this->drivingFile->get($serverData);
236 5
        if (!$this->tempStorage->remove($data)) {
237 1
            throw new UploadException($this->getUppLang()->uppCannotRemoveData($data->targetName));
238
        }
239 4
        if (!$this->drivingFile->removeByData($data)) {
240 1
            throw new UploadException($this->getUppLang()->uppDriveFileCannotRemove($data->targetName));
241
        }
242 3
        return $this->responseFactory
243 3
            ->getResponse(Responses\Factory::RESPONSE_CANCEL)
244 3
            ->setBasics($serverData, $clientData)
245
        ;
246
    }
247
}
248