Helper   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 134
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 2
dl 0
loc 134
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A extractFromUploadedFileInterface() 0 15 1
A extractFromSymfonyFile() 0 14 1
A remapFilesArray() 0 15 2
C normalizeFiles() 0 63 16
1
<?php
2
declare(strict_types=1);
3
4
namespace Sirius\Upload\Util;
5
6
class Helper
7
{
8
    const PSR7_UPLOADED_FILE_CLASS = '\Psr\Http\Message\UploadedFileInterface';
9
    const SYMFONY_UPLOADED_FILE_CLASS = 'Symfony\Component\HttpFoundation\File\UploadedFile';
10
11
    /**
12
     * We do not type-hint or import the class since it may not be used
13
     *
14
     * @param \Psr\Http\Message\UploadedFileInterface $file
15
     *
16
     * @return array
17
     */
18
    public static function extractFromUploadedFileInterface($file)
19
    {
20
        /** @var \Psr\Http\Message\UploadedFileInterface $file */
21
        $tempName = tempnam(sys_get_temp_dir(), 'srsupld_');
22
        $file->moveTo($tempName);
23
        $result = [
24
            'name'     => $file->getClientFilename(),
25
            'tmp_name' => $tempName,
26
            'type'     => $file->getClientMediaType(),
27
            'error'    => $file->getError(),
28
            'size'     => $file->getSize()
29
        ];
30
31
        return $result;
32
    }
33
34
    public static function extractFromSymfonyFile($file)
35
    {
36
        /** @var \Symfony\Component\HttpFoundation\File\UploadedFile $file */
37
38
        $result = [
39
            'name'     => $file->getClientOriginalName(),
40
            'tmp_name' => $file->getPathname(),
41
            'type'     => $file->getMimeType(),
42
            'error'    => $file->getError(),
43
            'size'     => $file->getSize()
44
        ];
45
46
        return $result;
47
    }
48
49
    public static function remapFilesArray(array $files): array
50
    {
51
        $result = [];
52
        foreach (array_keys($files['name']) as $k) {
53
            $result[$k] = [
54
                'name'     => $files['name'][$k],
55
                'type'     => @$files['type'][$k],
56
                'size'     => @$files['size'][$k],
57
                'error'    => @$files['error'][$k],
58
                'tmp_name' => $files['tmp_name'][$k]
59
            ];
60
        }
61
62
        return $result;
63
    }
64
65
    /**
66
     * Fixes the $_FILES array problem and ensures the result is an array of files
67
     *
68
     * PHP's $_FILES variable is not properly formated for iteration when
69
     * multiple files are uploaded under the same name
70
     * @see http://www.php.net/manual/en/features.file-upload.php
71
     *
72
     * @param array|Symfony\Component\HttpFoundation\File\UploadedFile|\Psr\Http\Message\UploadedFileInterface $files
73
     *
74
     * @return array
75
     */
76
    public static function normalizeFiles($files): array
77
    {
78
        if (empty($files)) {
79
            return [];
80
        }
81
82
        if (is_object($files)) {
83
            if (is_subclass_of($files, self::PSR7_UPLOADED_FILE_CLASS)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if self::PSR7_UPLOADED_FILE_CLASS can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
84
                return [self::extractFromUploadedFileInterface($files)];
85
            }
86
            if (get_class($files) == self::SYMFONY_UPLOADED_FILE_CLASS) {
87
                return [self::extractFromSymfonyFile($files)];
88
            }
89
        }
90
91
        // If caller passed in an array of objects (Either PSR7 or Symfony)
92
        if (is_array($files) && is_object(reset($files))) {
93
            if (is_subclass_of(reset($files), self::PSR7_UPLOADED_FILE_CLASS)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if self::PSR7_UPLOADED_FILE_CLASS can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
94
                $result = [];
95
                foreach ($files as $file) {
96
                    $result[] = self::extractFromUploadedFileInterface($file);
97
                }
98
99
                return $result;
100
            }
101
102
            if (get_class(reset($files)) == self::SYMFONY_UPLOADED_FILE_CLASS) {
103
                $result = [];
104
                foreach ($files as $file) {
105
                    $result[] = self::extractFromSymfonyFile($file);
106
                }
107
108
                return $result;
109
            }
110
        }
111
112
        // The caller passed $_FILES['some_field_name']
113
        if (isset($files['name'])) {
114
            // we have a single file
115
            if (! is_array($files['name'])) {
116
                return [$files];
117
            } else {
118
                // we have list of files, which PHP messes up
119
                return Helper::remapFilesArray($files);
0 ignored issues
show
Bug introduced by
It seems like $files defined by parameter $files on line 76 can also be of type object<Psr\Http\Message\UploadedFileInterface>; however, Sirius\Upload\Util\Helper::remapFilesArray() does only seem to accept array, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
120
            }
121
        } else {
122
            // The caller passed $_FILES
123
            $keys = array_keys($files);
124
            if (isset($keys[0]) && isset($files[$keys[0]]['name'])) {
125
                if (! is_array($files[$keys[0]]['name'])) {
126
                    // $files is in the correct format already, even in the
127
                    // case it contains a single element.
128
                    return $files;
129
                } else {
130
                    // we have list of files, which PHP messes up
131
                    return Helper::remapFilesArray($files[$keys[0]]);
132
                }
133
            }
134
        }
135
136
        // If we got here, the $file argument is wrong
137
        return [];
138
    }
139
}
140