Completed
Push — master ( 4a3db6...d83908 )
by recca
01:52
created

Api::chunksPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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