ActionPostAbstract::upload()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 11
ccs 0
cts 6
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 6
nc 2
nop 0
crap 6
1
<?php
2
namespace Staticus\Middlewares;
3
4
use League\Flysystem\FilesystemInterface;
5
use Staticus\Diactoros\DownloadedFile;
6
use Staticus\Diactoros\Response\FileUploadedResponse;
7
use Staticus\Exceptions\ErrorException;
8
use Staticus\Resources\Middlewares\PrepareResourceMiddlewareAbstract;
9
use Staticus\Resources\ResourceDOInterface;
10
use Staticus\Diactoros\Response\FileContentResponse;
11
use Zend\Diactoros\Response\EmptyResponse;
12
use Psr\Http\Message\ResponseInterface;
13
use Psr\Http\Message\ServerRequestInterface;
14
use Staticus\Resources\File\ResourceDO;
15
use Zend\Diactoros\UploadedFile;
16
17
abstract class ActionPostAbstract extends MiddlewareAbstract
18
{
19
    const RECREATE_COMMAND = 'recreate';
20
    const URI_COMMAND = 'uri';
21
22
    /**
23
     * Generator provider
24
     * @var mixed
25
     */
26
    protected $generator;
27
28
    /**
29
     * @var ResourceDOInterface|ResourceDO
30
     */
31
    protected $resourceDO;
32
    /**
33
     * @var FilesystemInterface
34
     */
35
    protected $filesystem;
36
37
    public function __construct(
38
        ResourceDOInterface $resourceDO, FilesystemInterface $filesystem, $fractal)
39
    {
40
        $this->resourceDO = $resourceDO;
41
        $this->filesystem = $filesystem;
42
        $this->generator = $fractal;
43
    }
44
45
    /**
46
     * @param ServerRequestInterface $request
47
     * @param ResponseInterface $response
48
     * @param callable|null $next
49
     * @return EmptyResponse
50
     * @throws \Exception
51
     */
52
    public function __invoke(
53
        ServerRequestInterface $request,
54
        ResponseInterface $response,
55
        callable $next = null
56
    )
57
    {
58
        parent::__invoke($request, $response, $next);
59
        $this->response = $this->action();
60
61
        return $this->next();
62
    }
63
64
    abstract protected function generate(ResourceDOInterface $resourceDO);
65
66
    protected function action()
67
    {
68
        $headers = [
69
            'Content-Type' => $this->resourceDO->getMimeType(),
70
        ];
71
        $filePath = $this->resourceDO->getFilePath();
72
        $fileExists = is_file($filePath);
73
        $recreate = PrepareResourceMiddlewareAbstract::getParamFromRequest(static::RECREATE_COMMAND, $this->request);
74
        $uri = PrepareResourceMiddlewareAbstract::getParamFromRequest(static::URI_COMMAND, $this->request);
75
        $recreate = $fileExists && $recreate;
76
        $this->resourceDO->setNew(!$fileExists);
77
        if (!$fileExists || $recreate) {
78
            $this->resourceDO->setRecreate($recreate);
79
            $upload = $this->upload();
80
81
            // Upload must be with high priority
82
            if ($upload) {
83
84
                /** @see \Zend\Diactoros\Response::$phrases */
85
                return new FileUploadedResponse($upload, 201, $headers);
86
            } elseif ($uri) {
87
                $upload = $this->download($this->resourceDO, $uri);
88
89
                /** @see \Zend\Diactoros\Response::$phrases */
90
                return new FileUploadedResponse($upload, 201, $headers);
91
            } else {
92
                $body = $this->generate($this->resourceDO);
93
94
                /** @see \Zend\Diactoros\Response::$phrases */
95
                return new FileContentResponse($body, 201, $headers);
96
            }
97
98
        }
99
100
        /** @see \Zend\Diactoros\Response::$phrases */
101
        return new EmptyResponse(304, $headers);
102
    }
103
104
    /**
105
     * @return UploadedFile|null
106
     */
107
    protected function upload()
108
    {
109
        $uploaded = $this->request->getUploadedFiles();
110
        $uploaded = current($uploaded);
111
        if ($uploaded instanceof UploadedFile) {
112
113
            return $uploaded;
114
        }
115
116
        return null;
117
    }
118
119
    /**
120
     * @param ResourceDOInterface $resourceDO
121
     * @param string $uri
122
     * @return DownloadedFile
123
     * @throws ErrorException
124
     * @throws \Exception
125
     */
126
    protected function download(ResourceDOInterface $resourceDO, $uri)
127
    {
128
        // ------------
129
        // @todo refactoring: move downloading code from here to separate service!
130
        // ------------
131
        $dir = DATA_DIR . 'download' . DIRECTORY_SEPARATOR;
132
        $file = $this->resourceDO->getUuid() . '_' . time() . '_' . mt_rand(100, 200) . '.tmp';
133
        if(!@mkdir($dir) && !is_dir($dir)) {
134
            throw new ErrorException('Can\'t create the directory: ' . $dir);
135
        }
136
        if (is_file($file)) {
137
            if(!unlink($file)) {
138
                throw new ErrorException('Can\'t remove old file: ' . $dir . $file);
139
            }
140
        }
141
        $resource = fopen($dir . $file, 'w+');
142
        if (!$resource) {
143
            throw new ErrorException('Can\'t create the file for writting: ' . $dir . $file);
144
        }
145
        $uriEnc = str_replace(' ', '%20', $uri);
146
        $headers = [
147
            "Accept: " . $resourceDO->getMimeType(),
148
            "Cache-Control: no-cache",
149
            "Pragma: no-cache",
150
        ];
151
        $curlHandle = curl_init($uriEnc);
152
        if (!$curlHandle) {
153
            throw new ErrorException('Curl error for uri: ' . $uri . ': cannot create resource');
154
        }
155
        curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
156
        curl_setopt($curlHandle, CURLOPT_TIMEOUT, static::CURL_TIMEOUT);
157
        // Save curl result to the file
158
        curl_setopt($curlHandle, CURLOPT_FILE, $resource);
159
        curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $headers);
160
        curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, true);
161
        curl_setopt($curlHandle, CURLOPT_MAXREDIRS, 2);
162
        curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, false);
163
        curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, false);
164
        // get curl response
165
        curl_exec($curlHandle);
166
        if (curl_errno($curlHandle)) {
167
            $error = curl_error($curlHandle);
168
            curl_close($curlHandle);
169
            fclose($resource);
170
            throw new ErrorException('Curl error for uri: ' . $uri . '; ' . $error);
171
        }
172
        $size = (int)curl_getinfo($curlHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
173
        curl_close($curlHandle);
174
        fclose($resource);
175
        // ------------
176
177
        $downloaded = new DownloadedFile(
178
            $dir . $file
179
            , $size
180
            , UPLOAD_ERR_OK
181
            , $resourceDO->getName() . '.' . $resourceDO->getType()
182
            , $resourceDO->getMimeType()
183
        );
184
185
        return $downloaded;
186
    }
187
}
188