Completed
Push — master ( f4226f...4a3db6 )
by recca
04:15
created

Api::__construct()   B

Complexity

Conditions 8
Paths 128

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 8

Importance

Changes 0
Metric Value
dl 0
loc 15
ccs 12
cts 12
cp 1
rs 7
c 0
b 0
f 0
cc 8
eloc 10
nc 128
nop 3
crap 8
1
<?php
2
3
namespace Recca0120\Upload;
4
5
use Illuminate\Http\Request;
6
use Recca0120\Upload\Filesystem;
7
use Illuminate\Http\JsonResponse;
8
use Recca0120\Upload\Contracts\Api as ApiContract;
9
use Symfony\Component\HttpFoundation\File\UploadedFile;
10
use Recca0120\Upload\Exceptions\ChunkedResponseException;
11
12
abstract class Api implements ApiContract
13
{
14
    /**
15
     * TMPFILE_EXTENSION.
16
     *
17
     * @var string
18
     */
19
    const TMPFILE_EXTENSION = '.part';
20
21
    /**
22
     * $request.
23
     *
24
     * @var \Illuminate\Http\Request
25
     */
26
    protected $request;
27
28
    /**
29
     * $filesystem.
30
     *
31
     * @var \Recca0120\Upload\Filesystem
32
     */
33
    protected $filesystem;
34
35
    /**
36
     * $config.
37
     *
38
     * @var array
39
     */
40
    protected $config;
41
42
    /**
43
     * __construct.
44
     *
45
     * @param array $config
46
     * @param \Illuminate\Http\Request $request
47
     * @param \Recca0120\Upload\Filesystem $filesystem
48
     */
49 19
    public function __construct($config = [], Request $request = null, Filesystem $filesystem = null)
50
    {
51 19
        $this->request = $request ?: Request::capture();
52 19
        $this->filesystem = $filesystem ?: new Filesystem();
53
54 19
        $config['chunks'] = empty($config['chunks']) === false ? $config['chunks'] : sys_get_temp_dir().'/chunks';
55 19
        $config['storage'] = empty($config['storage']) === false ? $config['storage'] : 'storage/temp';
56 19
        $config['domain'] = empty($config['domain']) === false ? $config['domain'] : $this->request->root();
57 19
        $config['path'] = empty($config['path']) === false ? $config['path'] : 'storage/temp';
58
59 19
        foreach (['chunks', 'storage', 'domain', 'path'] as $key) {
60 19
            $config[$key] = rtrim($config[$key], '/').'/';
61 19
        }
62 19
        $this->config = $config;
63 19
    }
64
65
    /**
66
     * chunksPath.
67
     *
68
     * @return string
69
     */
70 8
    public function chunksPath()
71
    {
72 8
        return $this->config['chunks'];
73
    }
74
75
    /**
76
     * storagePath.
77
     *
78
     * @return string
79
     */
80 8
    public function storagePath()
81
    {
82 8
        return $this->config['storage'];
83
    }
84
85
    /**
86
     * domain.
87
     *
88
     * @return string
89
     */
90 1
    public function domain()
91
    {
92 1
        return $this->config['domain'];
93
    }
94
95
    /**
96
     * path.
97
     *
98
     * @return string
99
     */
100 1
    public function path()
101
    {
102 1
        return $this->config['path'];
103
    }
104
105
    /**
106
     * makeDirectory.
107
     *
108
     * @return $this
109
     */
110 8
    public function makeDirectory($path)
111
    {
112 8
        if ($this->filesystem->isDirectory($path) === false) {
113 1
            $this->filesystem->makeDirectory($path, 0777, true, true);
114 1
        }
115
116 8
        return $this;
117
    }
118
119
    /**
120
     * cleanDirectory.
121
     */
122 6
    public function cleanDirectory($path)
123
    {
124 6
        $time = time();
125 6
        $maxFileAge = 3600;
126 6
        $files = (array) $this->filesystem->files($path);
127 6
        foreach ($files as $file) {
128 1
            if ($this->filesystem->isFile($file) === true &&
129 1
                $this->filesystem->lastModified($file) < ($time - $maxFileAge)
130 1
            ) {
131 1
                $this->filesystem->delete($file);
132 1
            }
133 6
        }
134 6
    }
135
136
    /**
137
     * receiveChunkedFile.
138
     *
139
     * @param string $originalName
140
     * @param string|resource $input
141
     * @param int $start
142
     * @param bool $completed
143
     * @param array $options
144
     * @return \Symfony\Component\HttpFoundation\File\UploadedFile
145
     *
146
     * @throws \Recca0120\Upload\Exceptions\ChunkedResponseException
147
     */
148 5
    protected function receiveChunkedFile($originalName, $input, $start, $completed = false, $options = [])
149
    {
150 5
        $tmpfilename = $this->filesystem->tmpfilename(
151 5
            $originalName, $this->request->get('token')
152 5
        );
153 5
        $chunkFile = $this->chunksPath().$tmpfilename.static::TMPFILE_EXTENSION;
154 5
        $storageFile = $this->storagePath().$tmpfilename;
155 5
        $this->filesystem->appendStream($chunkFile, $input, $start);
156 5
        if ($completed === false) {
157 2
            throw new ChunkedResponseException(
158 2
                empty($options['headers']) === false ? $options['headers'] : []
159 2
            );
160
        }
161 3
        $this->filesystem->move($chunkFile, $storageFile);
162
163 3
        return $this->filesystem->createUploadedFile(
164 3
            $storageFile,
165 3
            $originalName,
166 3
            empty($options['mimeType']) === false ? $options['mimeType'] : $this->filesystem->mimeType($originalName),
167 3
            $this->filesystem->size($storageFile)
168 3
        );
169
    }
170
171
    /**
172
     * receive.
173
     *
174
     * @param string $inputName
175
     * @return \Symfony\Component\HttpFoundation\File\UploadedFile
176
     *
177
     * @throws \Recca0120\Upload\Exceptions\ChunkedResponseException
178
     */
179 7
    public function receive($inputName)
180
    {
181 7
        $chunksPath = $this->chunksPath();
182 7
        $storagePath = $this->storagePath();
183 7
        $uploadedFile = $this->makeDirectory($chunksPath)
184 7
            ->makeDirectory($storagePath)
185 7
            ->doReceive($inputName);
186 5
        $this->cleanDirectory($chunksPath);
187
188 5
        return $uploadedFile;
189
    }
190
191
    /**
192
     * doReceive.
193
     *
194
     * @param string $inputName
195
     * @return \Symfony\Component\HttpFoundation\File\UploadedFile
196
     *
197
     * @throws \Recca0120\Upload\Exceptions\ChunkedResponseException
198
     */
199
    abstract protected function doReceive($inputName);
200
201
    /**
202
     * deleteUploadedFile.
203
     *
204
     * @param \Symfony\Component\HttpFoundation\File\UploadedFile
205
     * @return $this
206
     */
207 1
    public function deleteUploadedFile(UploadedFile $uploadedFile)
208
    {
209 1
        $file = $uploadedFile->getPathname();
210 1
        if ($this->filesystem->isFile($file) === true) {
211 1
            $this->filesystem->delete($file);
212 1
        }
213
214 1
        return $this;
215
    }
216
217
    /**
218
     * completedResponse.
219
     *
220
     * @param \Illuminate\Http\JsonResponse $response
221
     * @return \Illuminate\Http\JsonResponse
222
     */
223 1
    public function completedResponse(JsonResponse $response)
224
    {
225 1
        return $response;
226
    }
227
}
228