Passed
Push — master ( 26f295...e4804f )
by Roberto
02:49
created

ReCaptchaBuilder::htmlScriptTagJsApi()   B

Complexity

Conditions 10
Paths 19

Size

Total Lines 69
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 31
nc 19
nop 2
dl 0
loc 69
rs 7.6666
c 0
b 0
f 0

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
 * Copyright (c) 2017 - present
4
 * LaravelGoogleRecaptcha - ReCaptchaBuilder.php
5
 * author: Roberto Belotti - [email protected]
6
 * web : robertobelotti.com, github.com/biscolab
7
 * Initial version created on: 12/9/2018
8
 * MIT license: https://github.com/biscolab/laravel-recaptcha/blob/master/LICENSE
9
 */
10
11
namespace Biscolab\ReCaptcha;
12
13
use Exception;
14
15
class ReCaptchaBuilder {
16
17
    /**
18
     * The Site key
19
     * please visit https://developers.google.com/recaptcha/docs/start
20
     * @var string
21
     */
22
    protected $api_site_key;
23
24
    /**
25
     * The Secret key
26
     * please visit https://developers.google.com/recaptcha/docs/start
27
     * @var string
28
     */
29
    protected $api_secret_key;
30
31
    /**
32
     * The chosen ReCAPTCHA version
33
     * please visit https://developers.google.com/recaptcha/docs/start
34
     * @var string
35
     */
36
    protected $version;
37
38
    /**
39
     * Whether is true the ReCAPTCHA is inactive
40
     * @var boolean
41
     */
42
    protected $skip_by_ip = false;
43
44
    /**
45
     * The API request URI
46
     */
47
    protected $api_url = 'https://www.google.com/recaptcha/api/siteverify';
48
49
    public function __construct($api_site_key, $api_secret_key, $version = 'v2') {
50
51
        $this->setApiSiteKey($api_site_key);
52
        $this->setApiSecretKey($api_secret_key);
53
        $this->setVersion($version);
54
        $this->setSkipByIp($this->skipByIp());
55
    }
56
57
    /**
58
     * @param string $api_site_key
59
     *
60
     * @return ReCaptchaBuilder
61
     */
62
    public function setApiSiteKey(string $api_site_key): ReCaptchaBuilder{
63
        $this->api_site_key = $api_site_key;
64
65
        return $this;
66
    }
67
68
    /**
69
     * @param string $api_secret_key
70
     *
71
     * @return ReCaptchaBuilder
72
     */
73
    public function setApiSecretKey(string $api_secret_key): ReCaptchaBuilder{
74
        $this->api_secret_key = $api_secret_key;
75
76
        return $this;
77
    }
78
79
    /**
80
     * @param string $version
81
     *
82
     * @return ReCaptchaBuilder
83
     */
84
    public function setVersion(string $version): ReCaptchaBuilder{
85
        $this->version = $version;
86
87
        return $this;
88
    }
89
90
    /**
91
     * @return string
92
     */
93
    public function getVersion(): string {
94
        return $this->version;
95
    }
96
97
    /**
98
     * @param bool $skip_by_ip
99
     *
100
     * @return ReCaptchaBuilder
101
     */
102
    public function setSkipByIp(bool $skip_by_ip): ReCaptchaBuilder {
103
        $this->skip_by_ip = $skip_by_ip;
104
105
        return $this;
106
    }
107
108
    /**
109
     * Checks whether the user IP address is among IPs "to be skipped"
110
     *
111
     * @return boolean
112
     */
113
    public function skipByIp(): bool {
114
115
        return (in_array(request()->ip(), config('recaptcha.skip_ip', [])));
116
    }
117
118
    /**
119
     * Write script HTML tag in you HTML code
120
     * Insert before </head> tag
121
     *
122
     * @param string|null    $formId
123
     * @param array|null $configuration
124
     *
125
     * @return string
126
     * @throws Exception
127
     */
128
    public function htmlScriptTagJsApi(?string $formId = '', ?array $configuration = []): string {
129
130
        if ($this->skip_by_ip) {
131
            return '';
132
        }
133
134
        switch ($this->version) {
135
            case 'v3':
136
                $html = "<script src=\"https://www.google.com/recaptcha/api.js?render={$this->api_site_key}\"></script>";
137
                break;
138
            default:
139
                $html = "<script src=\"https://www.google.com/recaptcha/api.js\" async defer></script>";
140
        }
141
142
        if ($this->version == 'invisible') {
143
            if (!$formId) {
144
                throw new Exception("formId required", 1);
145
            }
146
            $html .= '<script>
147
		       function biscolabLaravelReCaptcha(token) {
148
		         document.getElementById("' . $formId . '").submit();
149
		       }
150
		     </script>';
151
        }
152
        elseif ($this->version == 'v3') {
153
154
            $action = array_get($configuration, 'action', 'homepage');
155
156
            $js_custom_validation = array_get($configuration, 'custom_validation', '');
157
158
            // Check if set custom_validation. That function will override default fetch validation function
159
            if($js_custom_validation) {
160
161
                $validate_function = ($js_custom_validation) ? "{$js_custom_validation}(token);" : '';
162
            }
163
            else {
164
165
                $js_then_callback = array_get($configuration, 'callback_then', '');
166
                $js_callback_catch = array_get($configuration, 'callback_catch', '');
167
168
                $js_then_callback = ($js_then_callback) ? "{$js_then_callback}(response)" : '';
169
                $js_callback_catch = ($js_callback_catch) ? "{$js_callback_catch}(err)" : '';
170
171
                $validate_function = "
172
                fetch('/" . config('recaptcha.default_validation_route', 'biscolab-recaptcha/validate') . "?" . config('recaptcha.default_token_parameter_name', 'token') . "=' + token, {
173
                    headers: {
174
                        \"X-Requested-With\": \"XMLHttpRequest\",
175
                        \"X-CSRF-TOKEN\": csrfToken.content
176
                    }
177
                })
178
                .then(function(response) {
179
                   	{$js_then_callback}
180
                })
181
                .catch(function(err) {
182
                    {$js_callback_catch}
183
                });";
184
            }
185
186
            $html .= "<script>
187
                    var csrfToken = document.head.querySelector('meta[name=\"csrf-token\"]');
188
                  grecaptcha.ready(function() {
189
                      grecaptcha.execute('{$this->api_site_key}', {action: '{$action}'}).then(function(token) {
190
                        {$validate_function}
191
                      });
192
                  });
193
		     </script>";
194
        }
195
196
        return $html;
197
    }
198
199
    /**
200
     * @param array|null $configuration
201
     *
202
     * @return string
203
     */
204
    public function htmlScriptTagJsApiV3(?array $configuration = []): string {
205
        return $this->htmlScriptTagJsApi('', $configuration);
206
    }
207
208
    /**
209
     * Call out to reCAPTCHA and process the response
210
     *
211
     * @param string $response
212
     *
213
     * @return boolean
214
     */
215
    public function validate($response) {
216
217
        if ($this->skip_by_ip) {
218
            return true;
219
        }
220
221
        $params = http_build_query([
222
            'secret'   => $this->api_secret_key,
223
            'remoteip' => request()->getClientIp(),
224
            'response' => $response,
225
        ]);
226
227
        $url = $this->api_url . '?' . $params;
228
229
        if (function_exists('curl_version')) {
230
            $curl = curl_init($url);
231
            curl_setopt($curl, CURLOPT_HEADER, false);
232
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
233
            curl_setopt($curl, CURLOPT_TIMEOUT, 1);
234
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
235
            $curl_response = curl_exec($curl);
236
        } else {
237
            $curl_response = file_get_contents($url);
238
        }
239
        if (is_null($curl_response) || empty($curl_response)) {
240
            return false;
241
        }
242
        $response = json_decode(trim($curl_response), true);
243
244
        if($this->version == 'v3') {
245
            return $response;
246
        }
247
248
        return $response['success'];
249
250
    }
251
}