Passed
Push — master ( 7b5fb9...4a31d5 )
by Eugene
03:17
created

ActionPostAbstract::download()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 55
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 55
ccs 0
cts 39
cp 0
rs 7.8235
cc 7
eloc 38
nc 8
nop 2
crap 56

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
    const CURL_TIMEOUT = 15;
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 View Code Duplication
    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
        set_time_limit(self::CURL_TIMEOUT);
132
        $dir = DATA_DIR . 'download' . DIRECTORY_SEPARATOR;
133
        $file = $this->resourceDO->getUuid() . '_' . time() . '_' . mt_rand(100, 200) . '.tmp';
134
        if(!@mkdir($dir) && !is_dir($dir)) {
135
            throw new ErrorException('Can\'t create the directory: ' . $dir);
136
        }
137
        if (is_file($file)) {
138
            if(!unlink($file)) {
139
                throw new ErrorException('Can\'t remove old file: ' . $dir . $file);
140
            }
141
        }
142
        $resource = fopen($dir . $file, 'w+');
143
        if (!$resource) {
144
            throw new ErrorException('Can\'t create the file for writting: ' . $dir . $file);
145
        }
146
        $uriEnc = str_replace(' ', '%20', $uri);
147
        $headers = [
148
            "Accept: " . $resourceDO->getMimeType(),
149
            "Cache-Control: no-cache",
150
            "Pragma: no-cache",
151
        ];
152
        $curlHandle = curl_init($uriEnc);
153
        curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, 1);
154
        curl_setopt($curlHandle, CURLOPT_TIMEOUT, static::CURL_TIMEOUT);
155
        // Save curl result to the file
156
        curl_setopt($curlHandle, CURLOPT_FILE, $resource);
157
        curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $headers);
158
        curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, true);
159
        // get curl response
160
        curl_exec($curlHandle);
161
        if (curl_errno($curlHandle)) {
162
            curl_close($curlHandle);
163
            fclose($resource);
164
            throw new ErrorException('Curl error for uri: ' . $uri . '; ' . curl_error($curlHandle));
165
        }
166
        $size = (int)curl_getinfo($curlHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
167
        curl_close($curlHandle);
168
        fclose($resource);
169
        // ------------
170
171
        $downloaded = new DownloadedFile(
172
            $dir . $file
173
            , $size
174
            , UPLOAD_ERR_OK
175
            , $resourceDO->getName() . '.' . $resourceDO->getType()
176
            , $resourceDO->getMimeType()
177
        );
178
179
        return $downloaded;
180
    }
181
}