1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Spiral Framework. |
4
|
|
|
* |
5
|
|
|
* @license MIT |
6
|
|
|
* @author Anton Titov (Wolfy-J) |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
namespace Spiral\Validation\Checkers; |
10
|
|
|
|
11
|
|
|
use Interop\Container\ContainerInterface; |
12
|
|
|
use Spiral\Core\Container\SingletonInterface; |
13
|
|
|
use Spiral\Files\FilesInterface; |
14
|
|
|
use Spiral\Validation\Checkers\Traits\FileTrait; |
15
|
|
|
use Spiral\Validation\Prototypes\AbstractChecker; |
16
|
|
|
|
17
|
|
|
/** |
18
|
|
|
* Image based validations. |
19
|
|
|
*/ |
20
|
|
|
class ImageChecker extends AbstractChecker implements SingletonInterface |
21
|
|
|
{ |
22
|
|
|
use FileTrait; |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Getimagesize constants. |
26
|
|
|
*/ |
27
|
|
|
const WIDTH = 0; |
28
|
|
|
const HEIGHT = 1; |
29
|
|
|
const IMAGE_TYPE = 2; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* {@inheritdoc} |
33
|
|
|
*/ |
34
|
|
|
protected $messages = [ |
35
|
|
|
'type' => '[[Image does not supported.]]', |
36
|
|
|
'valid' => '[[Image does not supported (allowed JPEG, PNG or GIF).]]', |
37
|
|
|
'smaller' => '[[Image size should not exceed {0}x{1}px.]]', |
38
|
|
|
'bigger' => '[[The image dimensions should be at least {0}x{1}px.]]', |
39
|
|
|
]; |
40
|
|
|
|
41
|
|
|
/** |
42
|
|
|
* Known image types. |
43
|
|
|
* |
44
|
|
|
* @var array |
45
|
|
|
*/ |
46
|
|
|
protected $imageTypes = [ |
47
|
|
|
'null', |
48
|
|
|
'gif', |
49
|
|
|
'jpeg', |
50
|
|
|
'png', |
51
|
|
|
'swf', |
52
|
|
|
'psd', |
53
|
|
|
'bmp', |
54
|
|
|
'tiff', |
55
|
|
|
'tiff', |
56
|
|
|
'jpc', |
57
|
|
|
'jp2', |
58
|
|
|
'jpx', |
59
|
|
|
'jb2', |
60
|
|
|
'swc', |
61
|
|
|
'iff', |
62
|
|
|
'wbmp', |
63
|
|
|
'xbm', |
64
|
|
|
]; |
65
|
|
|
|
66
|
|
|
/** |
67
|
|
|
* @param FilesInterface $files |
68
|
|
|
* @param ContainerInterface $container |
69
|
|
|
*/ |
70
|
|
|
public function __construct(FilesInterface $files, ContainerInterface $container = null) |
71
|
|
|
{ |
72
|
|
|
$this->files = $files; |
73
|
|
|
|
74
|
|
|
parent::__construct($container); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Check if image in a list of allowed image types. |
79
|
|
|
* |
80
|
|
|
* @param mixed $filename |
81
|
|
|
* @param array|mixed $types |
82
|
|
|
* |
83
|
|
|
* @return bool |
84
|
|
|
*/ |
85
|
|
|
public function type($filename, $types): bool |
86
|
|
|
{ |
87
|
|
|
if (empty($image = $this->imageData($filename))) { |
88
|
|
|
return false; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
if (!is_array($types)) { |
92
|
|
|
$types = array_slice(func_get_args(), 1); |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
return in_array($this->imageTypes[$image[self::IMAGE_TYPE]], $types); |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* Shortcut to check if image has valid type (JPEG, PNG and GIF are allowed). |
100
|
|
|
* |
101
|
|
|
* @param mixed $filename |
102
|
|
|
* |
103
|
|
|
* @return bool |
104
|
|
|
*/ |
105
|
|
|
public function valid($filename): bool |
106
|
|
|
{ |
107
|
|
|
return $this->type($filename, ['jpeg', 'png', 'gif']); |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* Check if image smaller that specified rectangle (height check if optional). |
112
|
|
|
* |
113
|
|
|
* @param mixed $filename |
114
|
|
|
* @param int $width |
115
|
|
|
* @param int $height Optional. |
116
|
|
|
* |
117
|
|
|
* @return bool |
118
|
|
|
*/ |
119
|
|
View Code Duplication |
public function smaller($filename, int $width, int $height = null): bool |
|
|
|
|
120
|
|
|
{ |
121
|
|
|
if (empty($image = $this->imageData($filename))) { |
122
|
|
|
return false; |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
if ($image[self::WIDTH] >= $width) { |
126
|
|
|
return false; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
if (!empty($height) && $image[self::HEIGHT] >= $height) { |
130
|
|
|
return false; |
131
|
|
|
} |
132
|
|
|
|
133
|
|
|
return true; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Check if image is bigger that specified rectangle (height check is optional). |
138
|
|
|
* |
139
|
|
|
* @param mixed $filename |
140
|
|
|
* @param int $width |
141
|
|
|
* @param int $height Optional. |
142
|
|
|
* |
143
|
|
|
* @return bool |
144
|
|
|
*/ |
145
|
|
View Code Duplication |
public function bigger($filename, int $width, int $height = null): bool |
|
|
|
|
146
|
|
|
{ |
147
|
|
|
if (empty($image = $this->imageData($filename))) { |
148
|
|
|
return false; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
if ($image[self::WIDTH] < $width) { |
152
|
|
|
return false; |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
if (!empty($height) && $image[self::HEIGHT] < $height) { |
156
|
|
|
return false; |
157
|
|
|
} |
158
|
|
|
|
159
|
|
|
return true; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Internal method, return image details fetched by getimagesize() or false. |
164
|
|
|
* |
165
|
|
|
* @see getimagesize() |
166
|
|
|
* |
167
|
|
|
* @param string|mixed $filename |
168
|
|
|
* |
169
|
|
|
* @return array|bool |
170
|
|
|
*/ |
171
|
|
|
protected function imageData($filename) |
172
|
|
|
{ |
173
|
|
|
try { |
174
|
|
|
return getimagesize($this->filename($filename)); |
175
|
|
|
} catch (\Exception $e) { |
176
|
|
|
//We can simply invalidate image if system can't read it |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
return false; |
180
|
|
|
} |
181
|
|
|
} |
182
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.