Test Setup Failed
Push — feature/code_improvement ( 4d8315...7e1ceb )
by Thierry
03:35
created

FileUpload::readFromTempFile()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 0
dl 0
loc 15
rs 9.7666
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * FileUpload.php - This class implements file upload with Ajax.
5
 *
6
 * @package jaxon-core
0 ignored issues
show
Coding Style introduced by
Package name "jaxon-core" is not valid; consider "Jaxoncore" instead
Loading history...
7
 * @author Thierry Feuzeu <[email protected]>
8
 * @copyright 2017 Thierry Feuzeu <[email protected]>
9
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
10
 * @link https://github.com/jaxon-php/jaxon-core
11
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
12
13
namespace Jaxon\Request\Plugin;
14
15
use Jaxon\Jaxon;
16
use Jaxon\Plugin\Request as RequestPlugin;
17
use Jaxon\Request\Support\UploadedFile;
18
use Jaxon\Request\Support\FileUpload as Support;
19
use Jaxon\Response\UploadResponse;
20
use Exception;
21
use Closure;
22
23
class FileUpload extends RequestPlugin
0 ignored issues
show
Coding Style introduced by
Missing doc comment for class FileUpload
Loading history...
24
{
25
    use \Jaxon\Features\Config;
26
    use \Jaxon\Features\Validator;
27
    use \Jaxon\Features\Translator;
28
29
    /**
30
     * The uploaded files copied in the user dir
31
     *
32
     * @var array
33
     */
34
    protected $aUserFiles = [];
35
36
    /**
37
     * The name of file containing upload data
38
     *
39
     * @var string
40
     */
41
    protected $sTempFile = '';
42
43
    /**
44
     * The subdir where uploaded files are stored
45
     *
46
     * @var string
47
     */
48
    protected $sUploadSubdir = '';
49
50
    /**
51
     * Is the current request an HTTP upload
52
     *
53
     * @var boolean
54
     */
55
    protected $bRequestIsHttpUpload = false;
56
57
    /**
58
     * HTTP file upload support
59
     *
60
     * @var Support
61
     */
62
    protected $xSupport = null;
63
64
    /**
65
     * The constructor
66
     *
67
     * @param Support       $xSupport       HTTP file upload support
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 7 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 7 found
Loading history...
68
     */
69
    public function __construct(Support $xSupport)
70
    {
71
        $this->xSupport = $xSupport;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
72
        $this->sUploadSubdir = uniqid() . DIRECTORY_SEPARATOR;
73
74
        if(array_key_exists('jxnupl', $_POST))
75
        {
76
            $this->sTempFile = $_POST['jxnupl'];
77
        }
78
        elseif(array_key_exists('jxnupl', $_GET))
79
        {
80
            $this->sTempFile = $_GET['jxnupl'];
81
        }
82
    }
83
84
    /**
85
     * Set the uploaded file name sanitizer
86
     *
87
     * @param Closure       $cSanitizer            The closure
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 7 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 12 found
Loading history...
88
     *
89
     * @return void
90
     */
91
    public function sanitizer(Closure $cSanitizer)
92
    {
93
        $this->xSupport->setNameSanitizer($cSanitizer);
94
    }
95
96
    /**
97
     * Get the uploaded files
98
     *
99
     * @return array
100
     */
101
    public function files()
102
    {
103
        return $this->aUserFiles;
104
    }
105
106
    /**
107
     * Make sure the upload dir exists and is writable
108
     *
109
     * @param string        $sUploadDir             The filename
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 8 found
Loading history...
Coding Style introduced by
Expected 4 spaces after parameter name; 13 found
Loading history...
110
     * @param string        $sUploadSubDir          The filename
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 8 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 10 found
Loading history...
111
     *
112
     * @return string
113
     */
114
    private function _makeUploadDir($sUploadDir, $sUploadSubDir)
115
    {
116
        $sUploadDir = rtrim(trim($sUploadDir), '/\\') . DIRECTORY_SEPARATOR;
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $sUploadDir. This often makes code more readable.
Loading history...
117
        // Verify that the upload dir exists and is writable
118
        if(!is_writable($sUploadDir))
119
        {
120
            throw new \Jaxon\Exception\Error($this->trans('errors.upload.access'));
121
        }
122
        $sUploadDir .= $sUploadSubDir;
123
        if(!file_exists($sUploadDir) && !@mkdir($sUploadDir))
124
        {
125
            throw new \Jaxon\Exception\Error($this->trans('errors.upload.access'));
126
        }
127
        return $sUploadDir;
128
    }
129
130
    /**
131
     * Get the path to the upload dir
132
     *
133
     * @param string        $sFieldId               The filename
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 8 found
Loading history...
Coding Style introduced by
Expected 1 spaces after parameter name; 15 found
Loading history...
134
     *
135
     * @return string
136
     */
137
    protected function getUploadDir($sFieldId)
138
    {
139
        // Default upload dir
140
        $sDefaultUploadDir = $this->getOption('upload.default.dir');
141
        $sUploadDir = $this->getOption('upload.files.' . $sFieldId . '.dir', $sDefaultUploadDir);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 8 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
142
143
        return $this->_makeUploadDir($sUploadDir, $this->sUploadSubdir);
144
    }
145
146
    /**
147
     * Get the path to the upload temp dir
148
     *
149
     * @return string
150
     */
151
    protected function getUploadTempDir()
152
    {
153
        // Default upload dir
154
        $sUploadDir = $this->getOption('upload.default.dir');
155
156
        return $this->_makeUploadDir($sUploadDir, 'tmp' . DIRECTORY_SEPARATOR);
157
    }
158
159
    /**
160
     * Get the path to the upload temp file
161
     *
162
     * @return string
163
     */
164
    protected function getUploadTempFile()
165
    {
166
        $sUploadDir = $this->getOption('upload.default.dir');
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
167
        $sUploadDir = rtrim(trim($sUploadDir), '/\\') . DIRECTORY_SEPARATOR;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
168
        $sUploadDir .= 'tmp' . DIRECTORY_SEPARATOR;
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 5 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
169
        $sUploadTempFile = $sUploadDir . $this->sTempFile . '.json';
170
        if(!is_readable($sUploadTempFile))
171
        {
172
            throw new \Jaxon\Exception\Error($this->trans('errors.upload.access'));
173
        }
174
        return $sUploadTempFile;
175
    }
176
177
    /**
178
     * Read uploaded files info from HTTP request data
179
     *
180
     * @return void
181
     */
182
    protected function readFromHttpData()
183
    {
184
        // Check validity of the uploaded files
185
        $aTempFiles = $this->xSupport->getUploadedFiles();
186
187
        // Copy the uploaded files from the temp dir to the user dir
188
        foreach($aTempFiles as $sVarName => $aFiles)
189
        {
190
            $this->aUserFiles[$sVarName] = [];
191
            // Get the path to the upload dir
192
            $sUploadDir = $this->getUploadDir($sVarName);
193
194
            foreach($aFiles as $aFile)
195
            {
196
                // Set the user file data
197
                $xUploadedFile = UploadedFile::fromHttpData($sUploadDir, $aFile);
198
                // All's right, move the file to the user dir.
199
                move_uploaded_file($aFile["tmp_name"], $xUploadedFile->path());
200
                $this->aUserFiles[$sVarName][] = $xUploadedFile;
201
            }
202
        }
203
    }
204
205
    /**
206
     * Save uploaded files info to a temp file
207
     *
208
     * @return void
209
     */
210
    protected function saveToTempFile()
211
    {
212
        // Convert uploaded file to an array
213
        $aFiles = [];
214
        foreach($this->aUserFiles as $sVarName => $aUserFiles)
215
        {
216
            $aFiles[$sVarName] = [];
217
            foreach($aUserFiles as $aUserFile)
218
            {
219
                $aFiles[$sVarName][] = $aUserFile->toTempData();
220
            }
221
        }
222
        // Save upload data in a temp file
223
        $sUploadDir = $this->getUploadTempDir();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 6 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
224
        $this->sTempFile = uniqid();
225
        file_put_contents($sUploadDir . $this->sTempFile . '.json', json_encode($aFiles));
226
    }
227
228
    /**
229
     * Read uploaded files info from a temp file
230
     *
231
     * @return void
232
     */
233
    protected function readFromTempFile()
234
    {
235
        // Upload temp file
236
        $sUploadTempFile = $this->getUploadTempFile();
237
        $aFiles = json_decode(file_get_contents($sUploadTempFile), true);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 10 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
238
        foreach($aFiles as $sVarName => $aUserFiles)
239
        {
240
            $this->aUserFiles[$sVarName] = [];
241
            foreach($aUserFiles as $aUserFile)
242
            {
243
                $this->aUserFiles[$sVarName][] = UploadedFile::fromTempData($aUserFile);
244
            }
245
        }
246
        unlink($sUploadTempFile);
247
    }
248
249
    /**
250
     * Return the name of this plugin
251
     *
252
     * @return string
253
     */
254
    public function getName()
255
    {
256
        return Jaxon::FILE_UPLOAD;
257
    }
258
259
    /**
260
     * Generate a hash for the registered browser events
261
     *
262
     * @return string
263
     */
264
    public function generateHash()
265
    {
266
        return '';
267
    }
268
269
    /**
270
     * Generate client side javascript code for the registered browser events
271
     *
272
     * @return string
273
     */
274
    public function getScript()
275
    {
276
        return '';
277
    }
278
279
    /**
280
     * Inform this plugin that other plugin can process the current request
281
     *
282
     * @return void
283
     */
284
    public function noRequestPluginFound()
285
    {
286
        if(count($_FILES) > 0)
287
        {
288
            $this->bRequestIsHttpUpload = true;
289
        }
290
    }
291
292
    /**
293
     * Check if this plugin can process the incoming Jaxon request
294
     *
295
     * @return boolean
296
     */
297
    public function canProcessRequest()
298
    {
299
        return (count($_FILES) > 0 || ($this->sTempFile));
300
    }
301
302
    /**
303
     * Process the uploaded files into the HTTP request
304
     *
305
     * @return boolean
306
     */
307
    public function processRequest()
308
    {
309
        if(!$this->canProcessRequest())
310
        {
311
            return false;
312
        }
313
314
        if(count($_FILES) > 0)
315
        {
316
            // Ajax or Http request with upload
317
            $this->readFromHttpData();
318
319
            if($this->bRequestIsHttpUpload)
320
            {
321
                // Process an HTTP upload request
322
                // This requires to set the response to be returned.
323
                $xResponse = new UploadResponse();
324
                try
325
                {
326
                    $this->saveToTempFile();
327
                    $xResponse->setUploadedFile($this->sTempFile);
328
                }
329
                catch(Exception $e)
330
                {
331
                    $xResponse->setErrorMessage($e->getMessage());
332
                }
333
                jaxon()->di()->getResponseManager()->append($xResponse);
334
            }
335
        }
336
        elseif(($this->sTempFile))
337
        {
338
            // Ajax request following and HTTP upload
339
            $this->readFromTempFile();
340
        }
341
342
        return true;
343
    }
344
}
345