Completed
Pull Request — master (#104)
by ARCANEDEV
15:35
created

AbstractNoCaptcha::getLang()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
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 216
    public function __construct($secret, $siteKey, $lang = null)
86
    {
87 216
        $this->setSecret($secret);
88 200
        $this->setSiteKey($siteKey);
89 184
        $this->setLang($lang);
90
91 184
        $this->setRequestClient(new Request);
92 184
    }
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 216
    protected function setSecret($secret)
107
    {
108 216
        self::checkKey('secret key', $secret);
109
110 200
        $this->secret = $secret;
111
112 200
        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 200
    protected function setSiteKey($siteKey)
133
    {
134 200
        self::checkKey('site key', $siteKey);
135
136 184
        $this->siteKey = $siteKey;
137
138 184
        return $this;
139
    }
140
141
    /**
142
     * Set language code.
143
     *
144
     * @param  string  $lang
145
     *
146
     * @return $this
147
     */
148 184
    public function setLang($lang)
149
    {
150 184
        $this->lang = $lang;
151
152 184
        return $this;
153
    }
154
155
    /**
156
     * Get language code.
157
     *
158
     * @return string|null
159
     */
160
    public function getLang()
161
    {
162 184
        return $this->lang;
163
    }
164 184
165
    /**
166 184
     * Set HTTP Request Client.
167
     *
168
     * @param  \Arcanedev\NoCaptcha\Contracts\Utilities\Request  $request
169
     *
170
     * @return $this
171
     */
172
    public function setRequestClient(Contracts\Utilities\Request $request)
173
    {
174 4
        $this->request = $request;
175
176 4
        return $this;
177
    }
178
179
    /**
180
     * Get the last response.
181
     *
182
     * @return \Arcanedev\NoCaptcha\Utilities\AbstractResponse|null
183
     */
184 48
    public function getLastResponse()
185
    {
186 48
        return $this->response;
187 8
    }
188 48
189
    /**
190
     * Get the client url.
191
     *
192
     * @return string
193
     */
194
    public static function getClientUrl()
195
    {
196 40
        return static::$useGlobalDomain
197
            ? 'https://www.recaptcha.net/recaptcha/api.js'
198 40
            : 'https://www.google.com/recaptcha/api.js';
199 8
    }
200 40
201
    /**
202
     * Get the verification url.
203
     *
204
     * @return string
205
     */
206
    public static function getVerificationUrl()
207
    {
208
        return static::$useGlobalDomain
209
            ? 'https://www.recaptcha.net/recaptcha/api/siteverify'
210
            : 'https://www.google.com/recaptcha/api/siteverify';
211
    }
212
213
    /* -----------------------------------------------------------------
214
     |  Main Methods
215
     | -----------------------------------------------------------------
216 32
     */
217
218 32
    /**
219 32
     * Verify Response.
220 32
     *
221 32
     * @param  string  $response
222
     * @param  string  $clientIp
223
     *
224
     * @return \Arcanedev\NoCaptcha\Utilities\AbstractResponse|mixed
225
     */
226
    public function verify($response, $clientIp = null)
227
    {
228
        return $this->response = $this->sendVerifyRequest([
229
            'secret'   => $this->secret,
230
            'response' => $response,
231
            'remoteip' => $clientIp
232
        ]);
233 8
    }
234
235 8
    /**
236 8
     * Calls the reCAPTCHA siteverify API to verify whether the user passes CAPTCHA
237
     * test using a PSR-7 ServerRequest object.
238 8
     *
239 8
     * @param  \Psr\Http\Message\ServerRequestInterface  $request
240 8
     *
241
     * @return \Arcanedev\NoCaptcha\Utilities\AbstractResponse
242
     */
243
    public function verifyRequest(ServerRequestInterface $request)
244
    {
245
        $body   = $request->getParsedBody();
246
        $server = $request->getServerParams();
247
248
        return $this->verify(
249
            $body[self::CAPTCHA_NAME] ?? '',
250
            $server['REMOTE_ADDR'] ?? null
251 32
        );
252
    }
253 32
254 32
    /**
255 32
     * Send verify request to API and get response.
256
     *
257
     * @param  array  $query
258 32
     *
259
     * @return \Arcanedev\NoCaptcha\Contracts\Utilities\Response
260
     */
261
    protected function sendVerifyRequest(array $query = [])
262
    {
263
        $query = array_filter($query);
264
        $json  = $this->request->send(
265
            $this->getVerificationUrl().'?'.http_build_query($query)
266
        );
267
268
        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 40
    /* -----------------------------------------------------------------
281
     |  Check Methods
282 40
     | -----------------------------------------------------------------
283
     */
284
285
    /**
286
     * Check if has lang.
287
     *
288
     * @return bool
289
     */
290
    protected function hasLang()
291 216
    {
292
        return ! empty($this->getLang());
293 216
    }
294
295 208
    /**
296
     * Check key.
297 208
     *
298 200
     * @param  string  $name
299
     * @param  string  $value
300
     */
301
    private static function checkKey($name, &$value): void
302
    {
303
        self::checkIsString($name, $value);
304
305
        $value = trim($value);
306
307
        self::checkIsNotEmpty($name, $value);
308 216
    }
309
310 216
    /**
311 16
     * Check if the value is a string value.
312 16
     *
313
     * @param  string  $name
314
     * @param  string  $value
315 208
     *
316
     * @throws \Arcanedev\NoCaptcha\Exceptions\ApiException
317
     */
318
    private static function checkIsString($name, $value): void
319
    {
320
        if ( ! is_string($value)) {
321
            throw new Exceptions\ApiException(
322
                "The {$name} must be a string value, ".gettype($value).' given.'
323
            );
324
        }
325 208
    }
326
327 208
    /**
328 16
     * Check if the value is not empty.
329
     *
330 200
     * @param string  $name
331
     * @param string  $value
332
     *
333
     * @throws \Arcanedev\NoCaptcha\Exceptions\ApiException
334
     */
335
    private static function checkIsNotEmpty($name, $value): void
336
    {
337
        if (empty($value)) {
338
            throw new Exceptions\ApiException("The {$name} must not be empty");
339
        }
340
    }
341
342
    /* -----------------------------------------------------------------
343
     |  Other Methods
344 44
     | -----------------------------------------------------------------
345
     */
346 44
347
    /**
348
     * Transform the string to an Html serializable object
349
     *
350
     * @param  string  $html
351
     *
352
     * @return \Illuminate\Support\HtmlString
353
     */
354
    protected function toHtmlString($html)
355
    {
356
        return new HtmlString($html);
357
    }
358
}
359