Passed
Push — master ( 893d1e...31005e )
by Kirill
03:35
created

ImageChecker   A

Complexity

Total Complexity 14

Size/Duplication

Total Lines 146
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 14
eloc 50
c 1
b 0
f 0
dl 0
loc 146
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A bigger() 0 7 3
A __construct() 0 3 1
A imageData() 0 8 2
A smaller() 0 8 3
A type() 0 16 4
A valid() 0 3 1
1
<?php
2
3
/**
4
 * Spiral Framework.
5
 *
6
 * @license   MIT
7
 * @author    Anton Titov (Wolfy-J)
8
 */
9
10
declare(strict_types=1);
11
12
namespace Spiral\Validation\Checker;
13
14
use Psr\Http\Message\UploadedFileInterface;
15
use Spiral\Core\Container\SingletonInterface;
16
use Spiral\Files\FilesInterface;
17
use Spiral\Streams\StreamableInterface;
18
use Spiral\Validation\AbstractChecker;
19
use Spiral\Validation\Checker\Traits\FileTrait;
20
21
/**
22
 * @inherit-messages
23
 */
24
final class ImageChecker extends AbstractChecker implements SingletonInterface
25
{
26
    use FileTrait;
27
28
    /**
29
     * Getimagesize constants.
30
     */
31
    public const WIDTH      = 0;
32
    public const HEIGHT     = 1;
33
    public const IMAGE_TYPE = 2;
34
35
    /**
36
     * {@inheritdoc}
37
     */
38
    public const MESSAGES = [
39
        'type'    => '[[Image format not supported.]]',
40
        'valid'   => '[[Image format not supported (allowed JPEG, PNG or GIF).]]',
41
        'smaller' => '[[Image size should not exceed {1}x{2}px.]]',
42
        'bigger'  => '[[The image dimensions should be at least {1}x{2}px.]]',
43
    ];
44
45
    /**
46
     * {@inheritdoc}
47
     */
48
    public const ALLOW_EMPTY_VALUES = ['type', 'valid'];
49
50
    /**
51
     * Known image types.
52
     *
53
     * @var array
54
     */
55
    public const IMAGE_TYPES = [
56
        'null',
57
        'gif',
58
        'jpeg',
59
        'png',
60
        'swf',
61
        'psd',
62
        'bmp',
63
        'tiff',
64
        'tiff',
65
        'jpc',
66
        'jp2',
67
        'jpx',
68
        'jb2',
69
        'swc',
70
        'iff',
71
        'wbmp',
72
        'xbm',
73
    ];
74
75
    /**
76
     * @param FilesInterface $files
77
     */
78
    public function __construct(FilesInterface $files)
79
    {
80
        $this->files = $files;
81
    }
82
83
    /**
84
     * Check if image in a list of allowed image types.
85
     *
86
     * @param string|UploadedFileInterface|StreamableInterface $file
87
     * @param array|string                                     $types
88
     * @return bool
89
     */
90
    public function type($file, $types): bool
91
    {
92
        $image = $this->imageData($file);
93
        if ($image === false) {
94
            return false;
95
        }
96
97
        if (!is_array($types)) {
98
            $types = array_slice(func_get_args(), 1);
99
        }
100
101
        if (!isset(self::IMAGE_TYPES[$image[self::IMAGE_TYPE]])) {
102
            return false;
103
        }
104
105
        return in_array(self::IMAGE_TYPES[$image[self::IMAGE_TYPE]], $types, true);
106
    }
107
108
    /**
109
     * Shortcut to check if image has valid type (JPEG, PNG and GIF are allowed).
110
     *
111
     * @param string|UploadedFileInterface|StreamableInterface $file
112
     * @return bool
113
     */
114
    public function valid($file): bool
115
    {
116
        return $this->type($file, ['jpeg', 'png', 'gif']);
117
    }
118
119
    /**
120
     * Check if image smaller that specified rectangle (height check if optional).
121
     *
122
     * @param string|UploadedFileInterface|StreamableInterface $file
123
     * @param int                                              $width
124
     * @param int                                              $height Optional.
125
     * @return bool
126
     */
127
    public function smaller($file, int $width, int $height): bool
128
    {
129
        if (empty($image = $this->imageData($file))) {
130
            return false;
131
        }
132
133
        return $image[self::WIDTH] <= $width
134
            && $image[self::HEIGHT] <= $height;
135
    }
136
137
    /**
138
     * Check if image is bigger that specified rectangle (height check is optional).
139
     *
140
     * @param string|UploadedFileInterface|StreamableInterface $file
141
     * @param int                                              $width
142
     * @param int|null                                         $height Optional.
143
     * @return bool
144
     */
145
    public function bigger($file, int $width, int $height = null): bool
146
    {
147
        if (empty($image = $this->imageData($file))) {
148
            return false;
149
        }
150
151
        return $image[self::WIDTH] >= $width && $image[self::HEIGHT] >= $height;
152
    }
153
154
    /**
155
     * Internal method, return image details fetched by getimagesize() or false.
156
     *
157
     * @param string|mixed $file
158
     * @return array|bool
159
     *
160
     * @see getimagesize()
161
     */
162
    protected function imageData($file)
163
    {
164
        $filename = $this->resolveFilename($file);
165
        if (empty($filename)) {
166
            return false;
167
        }
168
169
        return @getimagesize($filename);
170
    }
171
}
172