Completed
Branch 09branch (1e97b6)
by Anton
02:49
created

ImageChecker::smaller()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

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