Completed
Push — master ( f127cc...510b68 )
by
unknown
01:57
created

Gravatar::validateOptions()   F

Complexity

Conditions 23
Paths 514

Size

Total Lines 80

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 552

Importance

Changes 0
Metric Value
dl 0
loc 80
ccs 0
cts 0
cp 0
rs 0.675
c 0
b 0
f 0
cc 23
nc 514
nop 1
crap 552

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Gravatar;
6
7
/**
8
 * Gravatar URL Builder.
9
 *
10
 * @author Márk Sági-Kazár <[email protected]>
11
 */
12
final class Gravatar
13
{
14
    /**
15
     * Gravatar endpoints.
16
     */
17
    private const HTTP_ENDPOINT = 'http://www.gravatar.com';
18
    private const HTTPS_ENDPOINT = 'https://secure.gravatar.com';
19
20
    /**
21
     * Minimum image size
22
     *
23
     * @var int
24
     */
25
    private const MINIMUM_IMAGE_SIZE = 1;
26
27
    /**
28
     * Maximum image size
29
     *
30
     * @var int
31
     */
32
    private const MAXIMUM_IMAGE_SIZE = 2048;
33
34 16
    /**
35
     * Default Image Keywords
36 16
     *
37 16
     * @var array
38 16
     */
39
    private const DEFAULT_IMAGE_KEYWORDS = [
40
        '404',
41
        'mp',
42
        'identicon',
43
        'monsterid',
44
        'wavatar',
45
        'retro',
46
        'robohash',
47
        'blank'
48
    ];
49 5
50
    /**
51 5
     * Image ratings
52 4
     *
53
     * @var array
54 4
     */
55 2
    private const IMAGE_RATINGS = [
56 2
        'g',
57
        'pg',
58 4
        'r',
59
        'x'
60
    ];
61
62
    /**
63
     * @var array
64
     */
65
    private $defaults = [];
66
67
    /**
68
     * Whether to use HTTPS endpoint.
69 10
     *
70
     * @var bool
71 10
     */
72
    private $secure;
73
74
    public function __construct(array $defaults = [], bool $secure = true)
75
    {
76
        $this->defaults = array_filter($defaults);
77
        $this->secure = $secure;
78
    }
79
80
    /**
81
     * Returns an Avatar URL.
82 3
     */
83
    public function avatar(string $email, array $options = [], ?bool $secure = null, bool $validateOptions = false): string
84 3
    {
85
        $url = 'avatar/'.$this->createEmailHash($email);
86
87
        $options = array_merge($this->defaults, array_filter($options));
88
89
        if ($validateOptions) {
90
            $this->validateOptions($options);
91
        }
92
93
        if (!empty($options)) {
94
            $url .= '?'.http_build_query($options);
95 3
        }
96
97 3
        return $this->buildUrl($url, $secure);
98
    }
99
100
    /**
101
     * Returns a profile URL.
102
     */
103
    public function profile(string $email, ?bool $secure = null): string
104
    {
105
        return $this->buildUrl($this->createEmailHash($email), $secure);
106
    }
107 15
108
    /**
109 15
     * Returns a vCard URL.
110 4
     */
111
    public function vcard(string $email, ?bool $secure = null): string
112
    {
113 11
        return $this->profile($email, $secure).'.vcf';
114
    }
115
116
    /**
117
     * Returns a QR Code URL.
118
     */
119
    public function qrCode(string $email, ?bool $secure = null): string
120
    {
121
        return $this->profile($email, $secure).'.qr';
122
    }
123
124 11
    /**
125
     * Creates a hash from an email address.
126 11
     */
127
    private function createEmailHash(string $email): string
128 11
    {
129
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
130 11
            throw new \InvalidArgumentException('Invalid email address');
131
        }
132
133
        return md5(strtolower(trim($email)));
134
    }
135
136
    private function validateOptions(array $options): array
137
    {
138
        // Image size
139
        if (array_key_exists('s', $options)) {
140
            $size = filter_var($options['s'], FILTER_VALIDATE_INT);
141
142
            if ($size === false) {
143
                throw new \InvalidArgumentException('The size parameter ' . $options['s'] . ' is not an integer.');
144
            }
145
146
            if ($size < self::MINIMUM_IMAGE_SIZE || $size > self::MAXIMUM_IMAGE_SIZE) {
147
                throw new \InvalidArgumentException('The parameter ' . $options['s'] . ' is outside the allowed range of ' . self::MINIMUM_IMAGE_SIZE . ' to ' . self::MAXIMUM_IMAGE_SIZE . '.');
148
            }
149
        }
150
151
        if (array_key_exists('size', $options)) {
152
            $size = filter_var($options['size'], FILTER_VALIDATE_INT);
153
154
            if ($size === false) {
155
                throw new \InvalidArgumentException('The size parameter ' . $options['size'] . ' is not an integer.');
156
            }
157
158
            if ($size < self::MINIMUM_IMAGE_SIZE || $size > self::MAXIMUM_IMAGE_SIZE) {
159
                throw new \InvalidArgumentException('The size parameter ' . $options['size'] . ' is outside the allowed range of ' . self::MINIMUM_IMAGE_SIZE . ' to ' . self::MAXIMUM_IMAGE_SIZE . '.');
160
            }
161
        }
162
163
        // Default image
164
        if (array_key_exists('d', $options)) {
165
            $defaultImage = $options['d'];
166
167
            if (filter_var($defaultImage, FILTER_VALIDATE_URL) === false && !in_array(strtolower($defaultImage), self::DEFAULT_IMAGE_KEYWORDS)) {
168
                throw new \InvalidArgumentException('The default image parameter ' . $options['d'] . ' is not a URL or one of the allowed image keywords.');
169
            }
170
        }
171
172
        if (array_key_exists('default', $options)) {
173
            $defaultImage = $options['default'];
174
175
            if (filter_var($defaultImage, FILTER_VALIDATE_URL) === false && !in_array(strtolower($defaultImage), self::DEFAULT_IMAGE_KEYWORDS)) {
176
                throw new \InvalidArgumentException('The default image parameter ' . $options['default'] . ' is not a URL or one of the allowed image keywords.');
177
            }
178
        }
179
180
        // Force Default
181
        if (array_key_exists('f', $options)) {
182
            $forceDefault = $options['f'];
183
184
            if ($forceDefault !== 'y') {
185
                throw new \InvalidArgumentException('The force default parameter ' . $options['f'] . ' is invalid.');
186
            }
187
        }
188
189
        if (array_key_exists('forcedefault', $options)) {
190
            $forceDefault = $options['forcedefault'];
191
192
            if ($forceDefault !== 'y') {
193
                throw new \InvalidArgumentException('The force default parameter ' . $options['forcedefault'] . ' is invalid.');
194
            }
195
        }
196
197
        // Rating
198
        if (array_key_exists('r', $options)) {
199
            $rating = strtolower($options['r']);
200
201
            if (!in_array($rating, self::IMAGE_RATINGS)) {
202
                throw new \InvalidArgumentException('The rating parameter ' . $options['r'] . ' is invalid.');
203
            }
204
        }
205
206
        if (array_key_exists('rating', $options)) {
207
            $rating = strtolower($options['rating']);
208
209
            if (!in_array($rating, self::IMAGE_RATINGS)) {
210
                throw new \InvalidArgumentException('The rating parameter ' . $options['rating'] . ' is invalid.');
211
            }
212
        }
213
214
        return $options;
215
    }
216
217
    /**
218
     * Builds the URL based on the given parameters.
219
     */
220
    private function buildUrl(string $resource, ?bool $secure): string
221
    {
222
        $secure = isset($secure) ? (bool) $secure : $this->secure;
223
224
        $endpoint = $secure ? self::HTTPS_ENDPOINT : self::HTTP_ENDPOINT;
225
226
        return sprintf('%s/%s', $endpoint, $resource);
227
    }
228
}
229