File::getMetadata()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 11
nc 1
nop 0
dl 0
loc 15
ccs 12
cts 12
cp 1
crap 1
rs 9.9
c 1
b 0
f 0
1
<?php declare(strict_types=1);
2
3
namespace Formularium\Validator;
4
5
use Formularium\Datatype;
6
use Formularium\Exception\ValidatorException;
7
use Formularium\Model;
8
use Formularium\MetadataParameter;
9
use Formularium\ValidatorInterface;
10
use Formularium\Metadata;
11
12
/**
13
 * File validation
14
 */
15
class File implements ValidatorInterface
16
{
17
    const MAX_SIZE = 'maxSize';
18
19
    /**
20
     * Key for extension. Value can be array or string.
21
     */
22
    const ACCEPT = 'accept';
23
    const ACCEPT_AUDIO = 'audio/*';
24
    const ACCEPT_IMAGE = 'image/*';
25
    const ACCEPT_VIDEO = 'video/*';
26
27 4
    protected static function size(string $value, array $options = []): void
28
    {
29 4
        $max_size = $options[self::MAX_SIZE] ?? 0;
30 4
        if ($max_size > 0 && filesize($value) > $max_size) {
31 1
            throw new ValidatorException(
32 1
                'File too big. Maximum size: ' . $max_size
33
            );
34
        }
35 3
    }
36
37 2
    protected static function accept(string $value, array $options = []): void
38
    {
39 2
        $accept = $options[self::ACCEPT];
40 2
        if (!is_array($accept)) {
41 2
            $accept = [$accept];
42
        }
43
44
        /**
45
         * @var array $accept
46
         */
47 2
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
48 2
        if ($finfo === false) {
49
            throw new ValidatorException(
50
                'Cannot load fileinfo'
51
            );
52
        }
53 2
        $mime = finfo_file($finfo, $value);
54
55 2
        $valid = false;
56 2
        foreach ($accept as $a) {
57
            switch ($a) {
58 2
                case self::ACCEPT_AUDIO:
59
                    $validMimes = [
60 1
                        'audio/aac',
61
                        'audio/mpeg',
62
                        'audio/ogg',
63
                        'audio/wav',
64
                        'audio/webm',
65
                    ];
66 1
                    if (in_array($mime, $validMimes)) {
67
                        $valid = true;
68
                        break;
69
                    }
70 1
                break;
71 1
                case self::ACCEPT_IMAGE:
72
                    $validMimes = [
73 1
                        'image/jpg',
74
                        'image/jpeg',
75
                        'image/gif',
76
                        'image/png',
77
                        'image/webp'
78
                    ];
79 1
                    if (in_array($mime, $validMimes)) {
80 1
                        $valid = true;
81 1
                        break;
82
                    }
83
                break;
84
                case self::ACCEPT_VIDEO:
85
                    $validMimes = [
86
                        'video/x-flv',
87
                        'video/mp4',
88
                        'video/mpeg',
89
                        'application/x-mpegURL',
90
                        'video/MP2T',
91
                        'video/3gpp',
92
                        'video/ogg',
93
                        'video/quicktime',
94
                        'video/x-msvideo',
95
                        'video/x-ms-wmv',
96
                        'video/webm',
97
                    ];
98
                    if (in_array($mime, $validMimes)) {
99
                        $valid = true;
100
                        break;
101
                    }
102
                break;
103
            }
104
        }
105
106
        // TODO: 'accept' renderable
107
108 2
        if (!$valid) {
109 1
            throw new ValidatorException(
110 1
                'Not an accepted file'
111
            );
112
        }
113 1
    }
114
115 5
    public static function validate($value, array $options = [], ?Model $model = null)
116
    {
117 5
        if (!file_exists($value)) {
118 1
            throw new ValidatorException(
119 1
                'Not a file' . $value
120
            );
121
        }
122
123 4
        self::size($value, $options);
124
125 3
        if ($options[self::ACCEPT] ?? false) {
126 2
            self::accept($value, $options);
127
        }
128
129 2
        return $value;
130
    }
131
132 1
    public static function getMetadata(): Metadata
133
    {
134 1
        return new Metadata(
135 1
            'File',
136 1
            "File validations.",
137
            [
138 1
                new MetadataParameter(
139 1
                    self::MAX_SIZE,
140 1
                    'Int',
141 1
                    'Maximum file size in bytes'
142
                ),
143 1
                new MetadataParameter(
144 1
                    self::ACCEPT,
145 1
                    '[String]',
146 1
                    'Acceptable types'
147
                )
148
            ]
149
        );
150
    }
151
}
152