Completed
Push — master ( d090d0...220180 )
by Michael
11:35
created

HCaptchaField::setTheme()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace X3dgoo\HCaptcha\Forms;
4
5
use Psr\Log\LoggerInterface;
6
use SilverStripe\Control\Controller;
7
use SilverStripe\Core\Injector\Injector;
8
use SilverStripe\Forms\FormField;
9
use SilverStripe\Forms\Validator;
10
use SilverStripe\ORM\FieldType\DBHTMLText;
11
use SilverStripe\View\Requirements;
12
13
class HCaptchaField extends FormField
14
{
15
    /**
16
     * HCaptcha Site Key
17
     * @config HCaptchaField.site_key
18
     */
19
    private static $site_key;
20
21
    /**
22
     * HCaptcha Secret Key
23
     * @config HCaptchaField.secret_key
24
     */
25
    private static $secret_key;
26
27
    /**
28
     * HCaptcha Site Key
29
     * Configurable via Injector config
30
     */
31
    protected $_siteKey;
32
33
    /**
34
     * HCaptcha Site Key
35
     * Configurable via Injector config
36
     */
37
    protected $_secretKey;
38
39
    /**
40
     * Captcha theme, currently options are light and dark
41
     * @var string
42
     * @default light
43
     */
44
    private static $default_theme = 'light';
45
46
    /**
47
     * Captcha theme, currently options are light and dark
48
     * @var string
49
     */
50
    private $_captchaTheme;
51
52
    /**
53
     * Creates a new HCaptcha field.
54
     * @param string $name The internal field name, passed to forms.
55
     * @param string $title The human-readable field label.
56
     * @param mixed $value The value of the field (unused)
57
     */
58
    public function __construct($name, $title = null, $value = null)
59
    {
60
        parent::__construct($name, $title, $value);
61
62
        $this->title = $title;
63
        $this->_captchaTheme = self::config()->default_theme;
64
    }
65
66
    /**
67
     * Adds in the requirements for the field
68
     * @param array $properties Array of properties for the form element (not used)
69
     * @return DBHTMLText Rendered field template
70
     */
71
    public function Field($properties = [])
72
    {
73
        $siteKey = $this->getSiteKey();
74
        $secretKey = $this->getSecretKey();
75
76
        if (empty($siteKey) || empty($secretKey)) {
77
            user_error(
78
                'You must configure HCaptchaField.site_key and HCaptchaField.secret_key. ' .
79
                    'You can retrieve these at https://hcaptcha.com',
80
                E_USER_ERROR
81
            );
82
        }
83
84
        Requirements::javascript('https://hcaptcha.com/1/api.js');
85
86
        return parent::Field($properties);
87
    }
88
89
    /**
90
     * Validates the captcha against the hCaptcha API
91
     * @param Validator $validator Validator to send errors to
92
     * @return bool Returns boolean true if valid false if not
93
     */
94
    public function validate($validator)
95
    {
96
        $valid = $this->processCaptcha();
97
98
        if (!$valid) {
99
            $validator->validationError(
100
                $this->name,
101
                _t(
102
                    'X3dgoo\\HCaptcha\\Forms\\HCaptchaField.EMPTY',
103
                    'Please answer the captcha. If you do not see the captcha please enable Javascript'
104
                ),
105
                'validation'
106
            );
107
        }
108
109
        return $valid;
110
    }
111
112
    /**
113
     * Validates the captcha against the hCaptcha API
114
     * @return bool Returns boolean true if valid false if not
115
     */
116
    private function processCaptcha()
117
    {
118
        $hCaptchaResponse = Controller::curr()->getRequest()->requestVar('h-captcha-response');
119
120
        if (!isset($hCaptchaResponse) || !$hCaptchaResponse) {
121
            return false;
122
        }
123
124
        $secretKey = $this->getSecretKey();
125
126
        $client = new \GuzzleHttp\Client([
127
            'base_uri' => 'https://hcaptcha.com/',
128
        ]);
129
130
        $response = $client->request(
131
            'GET',
132
            'siteverify',
133
            [
134
                'query' => [
135
                    'secret' => $secretKey,
136
                    'response' => rawurlencode($hCaptchaResponse),
137
                    'remoteip' => rawurlencode($_SERVER['REMOTE_ADDR']),
138
                ],
139
            ]
140
        );
141
142
        $response = json_decode($response->getBody(), true);
143
144
        if (!is_array($response)) {
145
            $logger = Injector::inst()->get(LoggerInterface::class);
146
            $logger->error(
147
                'Captcha validation failed as request was not successful.'
148
            );
149
150
            return false;
151
        }
152
153
        if (array_key_exists('success', $response) && $response['success'] === false) {
154
            return false;
155
        }
156
157
        return true;
158
    }
159
160
    /**
161
     * Gets the site key configured via HCaptchaField.site_key this is used in the template
162
     * @return string
163
     */
164
    public function getSiteKey()
165
    {
166
        return $this->_siteKey ? $this->_siteKey : self::config()->site_key;
167
    }
168
169
    /**
170
     * Gets the secret key configured via HCaptchaField.secret_key
171
     * @return string
172
     */
173
    private function getSecretKey()
174
    {
175
        return $this->_secretKey ? $this->_secretKey : self::config()->secret_key;
176
    }
177
178
    /**
179
     * Setter for _siteKey to allow injector config to override the value
180
     * @param string $key
181
     */
182
    public function setSiteKey($key)
183
    {
184
        $this->_siteKey = $key;
185
    }
186
187
    /**
188
     * Setter for _secretKey to allow injector config to override the value
189
     * @param string $key
190
     */
191
    public function setSecretKey($key)
192
    {
193
        $this->_secretKey = $key;
194
    }
195
196
    /**
197
     * Gets the form's id
198
     * @return string
199
     */
200
    public function getFormID()
201
    {
202
        return ($this->form ? $this->getTemplateHelper()->generateFormID($this->form) : null);
203
    }
204
205
    /**
206
     * Sets the theme for this captcha
207
     * @param string $value Theme to set it to, currently the api supports light and dark
208
     * @return NocaptchaField
209
     */
210
    public function setTheme($value)
211
    {
212
        $this->_captchaTheme = $value;
213
214
        return $this;
215
    }
216
217
    /**
218
     * Gets the theme for this captcha
219
     * @return string
220
     */
221
    public function getCaptchaTheme()
222
    {
223
        return $this->_captchaTheme;
224
    }
225
}
226