Test Failed
Push — master ( e493d7...b1ea68 )
by Petr
11:01
created

Processing   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 227
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 98
c 1
b 0
f 0
dl 0
loc 227
rs 10
wmc 22

7 Methods

Rating   Name   Duplication   Size   Complexity  
A upload() 0 12 2
A __construct() 0 14 1
A check() 0 17 1
A truncate() 0 14 3
A cancel() 0 12 3
B init() 0 45 8
A done() 0 18 4
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
    public function __construct(
47
        Uploader\Config $config,
48
        ?Interfaces\IUppTranslations $lang = null
49
    )
50
    {
51
        $this->uploadConfig = $config;
52
        $this->dataPack = new Uploader\DataPack(new Uploader\Data());
53
        $this->calculates = new Uploader\Calculates($config);
54
        $this->drivingFile = (new DrivingFile\Factory($lang))->getDrivingFile($config);
55
        $this->tempStorage = (new TemporaryStorage\Factory($lang))->getTemporaryStorage($config);
56
        $this->finalStorage = (new FinalStorage\Factory($lang))->getFinalStorage($config);
57
        $this->responseFactory = new Responses\Factory($lang);
58
        $this->checksumFactory = new Checksums\Factory($lang);
59
        $this->decoderFactory = new ContentDecoders\Factory($lang);
60
    }
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
    public function init(string $targetPath, string $targetFileName, int $length, string $clientData = '̈́'): Responses\BasicResponse
72
    {
73
        if (empty($targetFileName)) {
74
            throw new UploadException($this->getUppLang()->uppSentNameIsEmpty());
75
        }
76
        $initialData = $this->dataPack->fillSizes(
77
            $this->dataPack->create(
78
                $targetPath,
79
                $targetFileName,
80
                $length
81
            ),
82
            $this->calculates->calcParts($length),
83
            $this->calculates->getBytesPerPart(),
84
            0
85
        );
86
        $data = $this->tempStorage->fillData($this->dataPack->fillTempData(
87
            $initialData,
88
            $this->uploadConfig
89
        ));
90
91
        $alreadyKnown = false;
92
        if ($this->drivingFile->existsByData($data)) {
93
            $currentKey = $this->drivingFile->keyByData($data);
94
            if (!$this->uploadConfig->canContinue) {
95
                throw new UploadException($this->getUppLang()->uppDriveFileAlreadyExists($currentKey));
96
            }
97
            $data = $this->drivingFile->get($currentKey);
98
            $alreadyKnown = true;
99
        }
100
101
        if ($this->tempStorage->exists($data) && !$alreadyKnown) {
102
            $this->tempStorage->remove($data);
103
        }
104
105
        $response = $this->responseFactory->getResponse(Responses\Factory::RESPONSE_INIT);
106
        /** @var Responses\InitResponse $response */
107
        return $response
108
            ->setInitData(
109
                $data,
110
                $this->uploadConfig->decoder ? strval($this->uploadConfig->decoder) : 'base64',
111
                $this->uploadConfig->checksum ? strval($this->uploadConfig->checksum) : 'md5'
112
            )
113
            ->setBasics(
114
                $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
    public function check(string $serverData, int $segment, string $method, string $clientData = ''): Responses\BasicResponse
130
    {
131
        $data = $this->drivingFile->get($serverData);
132
        $checksumClass = $this->checksumFactory->getChecksum($method);
133
        $response = $this->responseFactory->getResponse(Responses\Factory::RESPONSE_CHECK);
134
        /** @var Responses\CheckResponse $response */
135
        return $response
136
            ->setChecksum(
137
                $checksumClass->getMethod(),
138
                $checksumClass->checksum(
139
                    $this->tempStorage->checksumData(
140
                        $data,
141
                        $this->calculates->bytesFromSegment($data, $segment)
142
                    )
143
                )
144
            )
145
            ->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
    public function truncate(string $serverData, int $segment, string $clientData = ''): Responses\BasicResponse
158
    {
159
        $data = $this->drivingFile->get($serverData);
160
        if ($data->lastKnownPart < $segment) {
161
            throw new UploadException($this->getUppLang()->uppSegmentOutOfBounds($segment));
162
        }
163
        if (!$this->tempStorage->truncate($data, $this->calculates->bytesFromSegment($data, $segment))) {
164
            throw new UploadException($this->getUppLang()->uppCannotTruncateFile($data->targetName));
165
        }
166
        $response = $this->responseFactory->getResponse(Responses\Factory::RESPONSE_TRUNCATE);
167
        /** @var Responses\LastKnownResponse $response */
168
        return $response
169
            ->setLastKnown($segment)
170
            ->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
    public function upload(string $serverData, string $content, string $method, string $clientData = ''): Responses\BasicResponse
184
    {
185
        $data = $this->drivingFile->get($serverData);
186
        if (!$this->tempStorage->upload($data, $this->decoderFactory->getDecoder($method)->decode($content))) {
187
            throw new UploadException($this->getUppLang()->uppCannotWriteFile($data->targetName));
188
        }
189
        $segment = $this->dataPack->nextSegment($data);
190
        $response = $this->responseFactory->getResponse(Responses\Factory::RESPONSE_TRUNCATE);
191
        /** @var Responses\LastKnownResponse $response */
192
        return $response
193
            ->setLastKnown($segment)
194
            ->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
    public function done(string $serverData, string $clientData = ''): Responses\BasicResponse
206
    {
207
        $data = $this->drivingFile->get($serverData);
208
        $key = $this->finalStorage->findName($data);
209
        if (!$this->finalStorage->store($key, $this->tempStorage->read($data))) {
210
            throw new UploadException($this->getUppLang()->uppCannotWriteFile($data->targetName));
211
        }
212
        if (!$this->tempStorage->remove($data)) {
213
            throw new UploadException($this->getUppLang()->uppCannotRemoveData($data->targetName));
214
        }
215
        if (!$this->drivingFile->removeByData($data)) {
216
            throw new UploadException($this->getUppLang()->uppDriveFileCannotRemove($data->targetName));
217
        }
218
        $response = $this->responseFactory->getResponse(Responses\Factory::RESPONSE_DONE);
219
        /** @var Responses\DoneResponse $response */
220
        return $response
221
            ->setFinalName($key)
222
            ->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
    public function cancel(string $serverData, string $clientData = ''): Responses\BasicResponse
234
    {
235
        $data = $this->drivingFile->get($serverData);
236
        if (!$this->tempStorage->remove($data)) {
237
            throw new UploadException($this->getUppLang()->uppCannotRemoveData($data->targetName));
238
        }
239
        if (!$this->drivingFile->removeByData($data)) {
240
            throw new UploadException($this->getUppLang()->uppDriveFileCannotRemove($data->targetName));
241
        }
242
        return $this->responseFactory
243
            ->getResponse(Responses\Factory::RESPONSE_CANCEL)
244
            ->setBasics($serverData, $clientData)
245
        ;
246
    }
247
}
248