Completed
Push — master ( ca2209...0f254b )
by Michael
01:02
created

HCaptchaField::getSecretKey()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 0
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
     * Creates a new HCaptcha field.
41
     * @param string $name The internal field name, passed to forms.
42
     * @param string $title The human-readable field label.
43
     * @param mixed $value The value of the field (unused)
44
     */
45
    public function __construct($name, $title = null, $value = null)
46
    {
47
        parent::__construct($name, $title, $value);
48
49
        $this->title = $title;
50
    }
51
52
    /**
53
     * Adds in the requirements for the field
54
     * @param array $properties Array of properties for the form element (not used)
55
     * @return DBHTMLText Rendered field template
56
     */
57
    public function Field($properties = [])
58
    {
59
        $siteKey = $this->getSiteKey();
60
        $secretKey = $this->getSecretKey();
61
62
        if (empty($siteKey) || empty($secretKey)) {
63
            user_error(
64
                'You must configure HCaptchaField.site_key and HCaptchaField.secret_key. ' .
65
                    'You can retrieve these at https://hcaptcha.com',
66
                E_USER_ERROR
67
            );
68
        }
69
70
        Requirements::javascript('https://hcaptcha.com/1/api.js');
71
72
        return parent::Field($properties);
73
    }
74
75
    /**
76
     * Validates the captcha against the hCaptcha API
77
     * @param Validator $validator Validator to send errors to
78
     * @return bool Returns boolean true if valid false if not
79
     */
80
    public function validate($validator)
81
    {
82
        $hCaptchaResponse = Controller::curr()->getRequest()->requestVar('h-captcha-response');
83
84
        if (!isset($hCaptchaResponse)) {
85
            $validator->validationError(
86
                $this->name,
87
                _t(
88
                    'X3dgoo\\HCaptcha\\Forms\\HCaptchaField.EMPTY',
89
                    'Please answer the captcha. If you do not see the captcha please enable Javascript'
90
                ),
91
                'validation'
92
            );
93
94
            return false;
95
        }
96
97
        if (!function_exists('curl_init')) {
98
            user_error('You must enable php-curl to use this field', E_USER_ERROR);
99
100
            return false;
101
        }
102
103
        $secretKey = $this->getSecretKey();
104
        $url = 'https://hcaptcha.com/siteverify' .
105
            '?secret=' . $secretKey .
106
            '&response=' . rawurlencode($hCaptchaResponse) .
107
            '&remoteip=' . rawurlencode($_SERVER['REMOTE_ADDR']);
108
        $ch = curl_init($url);
109
110
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
111
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
112
        curl_setopt($ch, CURLOPT_USERAGENT, str_replace(',', '/', 'SilverStripe'));
113
        $response = json_decode(curl_exec($ch), true);
114
115
        if (is_array($response)) {
116
            if (array_key_exists('success', $response) && $response['success'] == false) {
117
                $validator->validationError(
118
                    $this->name,
119
                    _t(
120
                        'X3dgoo\\HCaptcha\\Forms\\HCaptchaField.EMPTY',
121
                        'Please answer the captcha. If you do not see the captcha please enable Javascript'
122
                    ),
123
                    'validation'
124
                );
125
126
                return false;
127
            }
128
        } else {
129
            $validator->validationError(
130
                $this->name,
131
                _t(
132
                    'X3dgoo\\HCaptcha\\Forms\\HCaptchaField.VALIDATE_ERROR',
133
                    'Captcha could not be validated'
134
                ),
135
                'validation'
136
            );
137
            $logger = Injector::inst()->get(LoggerInterface::class);
138
            $logger->error(
139
                'Captcha validation failed as request was not successful.'
140
            );
141
142
            return false;
143
        }
144
145
        return true;
146
    }
147
148
    /**
149
     * Gets the site key configured via HCaptchaField.site_key this is used in the template
150
     * @return string
151
     */
152
    public function getSiteKey()
153
    {
154
        return $this->_siteKey ? $this->_siteKey : self::config()->site_key;
155
    }
156
157
    /**
158
     * Gets the secret key configured via HCaptchaField.secret_key
159
     * @return string
160
     */
161
    private function getSecretKey()
162
    {
163
        return $this->_secretKey ? $this->_secretKey : self::config()->secret_key;
164
    }
165
166
    /**
167
     * Setter for _siteKey to allow injector config to override the value
168
     * @param string $key
169
     */
170
    public function setSiteKey($key)
171
    {
172
        $this->_siteKey = $key;
173
    }
174
175
    /**
176
     * Setter for _secretKey to allow injector config to override the value
177
     * @param string $key
178
     */
179
    public function setSecretKey($key)
180
    {
181
        $this->_secretKey = $key;
182
    }
183
184
    /**
185
     * Gets the form's id
186
     * @return string
187
     */
188
    public function getFormID()
189
    {
190
        return ($this->form ? $this->getTemplateHelper()->generateFormID($this->form) : null);
191
    }
192
}
193