Completed
Push — develop ( 57c5de...3d9762 )
by ARCANEDEV
42:56 queued 29:00
created

AbstractNoCaptcha::checkIsNotEmpty()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 0
loc 6
rs 10
c 0
b 0
f 0
ccs 4
cts 4
cp 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arcanedev\NoCaptcha;
6
7
use Arcanedev\NoCaptcha\Utilities\Request;
8
use Illuminate\Support\HtmlString;
9
use Psr\Http\Message\ServerRequestInterface;
10
11
/**
12
 * Class     AbstractNoCaptcha
13
 *
14
 * @author   ARCANEDEV <[email protected]>
15
 */
16
abstract class AbstractNoCaptcha implements Contracts\NoCaptcha
17
{
18
    /* -----------------------------------------------------------------
19
     |  Constants
20
     | -----------------------------------------------------------------
21
     */
22
23
    const CAPTCHA_NAME = 'g-recaptcha-response';
24
25
    /* -----------------------------------------------------------------
26
     |  Properties
27
     | -----------------------------------------------------------------
28
     */
29
30
    /**
31
     * The shared key between your site and ReCAPTCHA
32
     *
33
     * @var string
34
     */
35
    protected $secret;
36
37
    /**
38
     * Your site key
39
     *
40
     * @var string
41
     */
42
    protected $siteKey;
43
44
    /**
45
     * Forces the widget to render in a specific language.
46
     * Auto-detects the user's language if unspecified.
47
     *
48
     * @var string
49
     */
50
    protected $lang;
51
52
    /**
53
     * HTTP Request Client
54
     *
55
     * @var \Arcanedev\NoCaptcha\Contracts\Utilities\Request
56
     */
57
    protected $request;
58
59
    /**
60
     * ReCaptcha's response.
61
     *
62
     * @var \Arcanedev\NoCaptcha\Utilities\ResponseV3|null
63
     */
64
    protected $response;
65
66
    /**
67
     * Use the global domain.
68
     *
69
     * @var bool
70
     */
71
    public static $useGlobalDomain = false;
72
73
    /* -----------------------------------------------------------------
74
     |  Constructor
75
     | -----------------------------------------------------------------
76
     */
77
78
    /**
79
     * NoCaptcha constructor.
80
     *
81
     * @param  string       $secret
82
     * @param  string       $siteKey
83
     * @param  string|null  $lang
84
     */
85 220
    public function __construct($secret, $siteKey, $lang = null)
86
    {
87 220
        $this->setSecret($secret);
88 204
        $this->setSiteKey($siteKey);
89 188
        $this->setLang($lang);
90
91 188
        $this->setRequestClient(new Request);
92 188
    }
93
94
    /* -----------------------------------------------------------------
95
     |  Getters & Setters
96
     | -----------------------------------------------------------------
97
     */
98
99
    /**
100
     * Set the secret key.
101
     *
102
     * @param  string  $secret
103
     *
104
     * @return $this
105
     */
106 220
    protected function setSecret($secret)
107
    {
108 220
        self::checkKey('secret key', $secret);
109
110 204
        $this->secret = $secret;
111
112 204
        return $this;
113
    }
114
115
    /**
116
     * Get the site key.
117
     *
118
     * @return string
119
     */
120 24
    public function getSiteKey()
121
    {
122 24
        return $this->siteKey;
123
    }
124
125
    /**
126
     * Set Site key.
127
     *
128
     * @param  string  $siteKey
129
     *
130
     * @return $this
131
     */
132 204
    protected function setSiteKey($siteKey)
133
    {
134 204
        self::checkKey('site key', $siteKey);
135
136 188
        $this->siteKey = $siteKey;
137
138 188
        return $this;
139
    }
140
141
    /**
142
     * Set language code.
143
     *
144
     * @param  string  $lang
145
     *
146
     * @return $this
147
     */
148 188
    public function setLang($lang)
149
    {
150 188
        $this->lang = $lang;
151
152 188
        return $this;
153
    }
154
155
    /**
156
     * Get language code.
157
     *
158
     * @return string|null
159
     */
160 44
    public function getLang()
161
    {
162 44
        return $this->lang;
163
    }
164
165
    /**
166
     * Set HTTP Request Client.
167
     *
168
     * @param  \Arcanedev\NoCaptcha\Contracts\Utilities\Request  $request
169
     *
170
     * @return $this
171
     */
172 188
    public function setRequestClient(Contracts\Utilities\Request $request)
173
    {
174 188
        $this->request = $request;
175
176 188
        return $this;
177
    }
178
179
    /**
180
     * Get the last response.
181
     *
182
     * @return \Arcanedev\NoCaptcha\Utilities\AbstractResponse|null
183
     */
184 4
    public function getLastResponse()
185
    {
186 4
        return $this->response;
187
    }
188
189
    /**
190
     * Get the client url.
191
     *
192
     * @return string
193
     */
194 48
    public static function getClientUrl()
195
    {
196 48
        return static::$useGlobalDomain
197 8
            ? 'https://www.recaptcha.net/recaptcha/api.js'
198 48
            : 'https://www.google.com/recaptcha/api.js';
199
    }
200
201
    /**
202
     * Get the verification url.
203
     *
204
     * @return string
205
     */
206 40
    public static function getVerificationUrl()
207
    {
208 40
        return static::$useGlobalDomain
209 8
            ? 'https://www.recaptcha.net/recaptcha/api/siteverify'
210 40
            : 'https://www.google.com/recaptcha/api/siteverify';
211
    }
212
213
    /* -----------------------------------------------------------------
214
     |  Main Methods
215
     | -----------------------------------------------------------------
216
     */
217
218
    /**
219
     * Verify Response.
220
     *
221
     * @param  string  $response
222
     * @param  string  $clientIp
223
     *
224
     * @return \Arcanedev\NoCaptcha\Utilities\AbstractResponse|mixed
225
     */
226 32
    public function verify($response, $clientIp = null)
227
    {
228 32
        return $this->response = $this->sendVerifyRequest([
229 32
            'secret'   => $this->secret,
230 32
            'response' => $response,
231 32
            'remoteip' => $clientIp
232
        ]);
233
    }
234
235
    /**
236
     * Calls the reCAPTCHA siteverify API to verify whether the user passes CAPTCHA
237
     * test using a PSR-7 ServerRequest object.
238
     *
239
     * @param  \Psr\Http\Message\ServerRequestInterface  $request
240
     *
241
     * @return \Arcanedev\NoCaptcha\Utilities\AbstractResponse
242
     */
243 8
    public function verifyRequest(ServerRequestInterface $request)
244
    {
245 8
        $body   = $request->getParsedBody();
246 8
        $server = $request->getServerParams();
247
248 8
        return $this->verify(
249 8
            $body[self::CAPTCHA_NAME] ?? '',
250 8
            $server['REMOTE_ADDR'] ?? null
251
        );
252
    }
253
254
    /**
255
     * Send verify request to API and get response.
256
     *
257
     * @param  array  $query
258
     *
259
     * @return \Arcanedev\NoCaptcha\Contracts\Utilities\Response
260
     */
261 32
    protected function sendVerifyRequest(array $query = [])
262
    {
263 32
        $query = array_filter($query);
264 32
        $json  = $this->request->send(
265 32
            $this->getVerificationUrl().'?'.http_build_query($query)
266
        );
267
268 32
        return $this->parseResponse($json);
269
    }
270
271
    /**
272
     * Parse the response.
273
     *
274
     * @param  string  $json
275
     *
276
     * @return \Arcanedev\NoCaptcha\Contracts\Utilities\Response|mixed
277
     */
278
    abstract protected function parseResponse($json);
279
280
    /* -----------------------------------------------------------------
281
     |  Check Methods
282
     | -----------------------------------------------------------------
283
     */
284
285
    /**
286
     * Check if has lang.
287
     *
288
     * @return bool
289
     */
290 40
    protected function hasLang()
291
    {
292 40
        return ! empty($this->getLang());
293
    }
294
295
    /**
296
     * Check key.
297
     *
298
     * @param  string  $name
299
     * @param  string  $value
300
     */
301 220
    private static function checkKey($name, &$value): void
302
    {
303 220
        self::checkIsString($name, $value);
304
305 212
        $value = trim($value);
306
307 212
        self::checkIsNotEmpty($name, $value);
308 204
    }
309
310
    /**
311
     * Check if the value is a string value.
312
     *
313
     * @param  string  $name
314
     * @param  string  $value
315
     *
316
     * @throws \Arcanedev\NoCaptcha\Exceptions\ApiException
317
     */
318 220
    private static function checkIsString($name, $value): void
319
    {
320 220
        if ( ! is_string($value)) {
321 16
            throw new Exceptions\ApiException(
322 16
                "The {$name} must be a string value, ".gettype($value).' given.'
323
            );
324
        }
325 212
    }
326
327
    /**
328
     * Check if the value is not empty.
329
     *
330
     * @param string  $name
331
     * @param string  $value
332
     *
333
     * @throws \Arcanedev\NoCaptcha\Exceptions\ApiException
334
     */
335 212
    private static function checkIsNotEmpty($name, $value): void
336
    {
337 212
        if (empty($value)) {
338 16
            throw new Exceptions\ApiException("The {$name} must not be empty");
339
        }
340 204
    }
341
342
    /* -----------------------------------------------------------------
343
     |  Other Methods
344
     | -----------------------------------------------------------------
345
     */
346
347
    /**
348
     * Transform the string to an Html serializable object
349
     *
350
     * @param  string  $html
351
     *
352
     * @return \Illuminate\Support\HtmlString
353
     */
354 44
    protected function toHtmlString($html)
355
    {
356 44
        return new HtmlString($html);
357
    }
358
}
359