ReCaptcha2   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 188
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 29
lcom 1
cbo 6
dl 0
loc 188
rs 10
c 1
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A setOptions() 0 11 2
A getService() 0 7 2
D setService() 0 29 9
A getSiteKey() 0 4 1
A setSiteKey() 0 5 1
A getSecretKey() 0 4 1
A setSecretKey() 0 5 1
A generate() 0 4 1
D isValid() 0 39 10
A getHelperName() 0 4 1
1
<?php
2
namespace ReCaptcha2\Captcha;
3
4
use Zend\Captcha\AbstractAdapter;
5
use Zend\Captcha\Exception;
6
7
class ReCaptcha2 extends AbstractAdapter
8
{
9
    /**
10
     * @var ServiceInterface
11
     */
12
    protected $service;
13
14
    /**#@+
15
     * Error codes
16
     */
17
    const ERROR_CAPTCHA_GENERAL     = 'error-captcha-general';
18
    const MISSING_INPUT_RESPONSE    = 'missing-input-response';
19
    const INVALID_INPUT_RESPONSE    = 'invalid-input-response';
20
    const MISSING_INPUT_SECRET      = 'missing-input-secret';
21
    const INVALID_INPUT_SECRET      = 'invalid-input-secret';
22
    /**#@-*/
23
24
    /**
25
     * Error messages
26
     * @var array
27
     */
28
    protected $messageTemplates = [
29
        self::ERROR_CAPTCHA_GENERAL     => 'Failed to validate captcha',
30
        self::MISSING_INPUT_RESPONSE    => 'Missing captcha fields',
31
        self::INVALID_INPUT_RESPONSE    => 'Captcha value is wrong: %value%',
32
        self::MISSING_INPUT_SECRET      => 'Missing captcha secret',
33
        self::INVALID_INPUT_SECRET      => 'Invalid captcha secret',
34
    ];
35
36
    /**
37
     * @param array|\Traversable $options
38
     * @throws Exception\DomainException
39
     * @return ReCaptcha2
40
     */
41
    public function setOptions($options = [])
42
    {
43
        if (array_key_exists('service', $options)) {
44
            $this->setService($options['service']);
45
            unset($options['service']);
46
        }
47
48
        parent::setOptions($options);
49
50
        return $this;
51
    }
52
53
    /**
54
     * @return ServiceInterface
55
     */
56
    public function getService()
57
    {
58
        if (null === $this->service) {
59
            $this->service = new NoCaptchaService;
60
        }
61
        return $this->service;
62
    }
63
64
    /**
65
     * @param array|\Traversable|ServiceInterface $service
66
     * @return ReCaptcha2
67
     */
68
    public function setService($service)
69
    {
70
        $serviceOptions = [];
71
        if (is_array($service)) {
72
            $serviceOptions = isset($service['options']) ? $service['options'] : [];
73
            $service        = isset($service['class']) ? $service['class'] : NoCaptchaService::class;
74
        }
75
76
        if (is_string($service)) {
77
            if (!class_exists($service)) {
78
                throw new Exception\InvalidArgumentException(sprintf(
79
                    'Unable to locate service class "%s"',
80
                    $service
81
                ));
82
            }
83
            $service = new $service($serviceOptions);
84
        }
85
86
        if (!isset($service) || !$service instanceof ServiceInterface) {
87
            throw new Exception\DomainException(sprintf(
88
                '%s expects a valid implementation of %s; received "%s"',
89
                __METHOD__,
90
                ServiceInterface::class,
91
                (is_object($service) ? get_class($service) : gettype($service))
92
            ));
93
        }
94
        $this->service = $service;
95
        return $this;
96
    }
97
98
    /**
99
     * @see ServiceInterface::getSiteKey()
100
     */
101
    public function getSiteKey()
102
    {
103
        return $this->getService()->getSiteKey();
104
    }
105
106
    /**
107
     * @see ServiceInterface::setSiteKey()
108
     */
109
    public function setSiteKey($siteKey)
110
    {
111
        $this->getService()->setSiteKey($siteKey);
112
        return $this;
113
    }
114
115
    /**
116
     * @see ServiceInterface::getSecretKey()
117
     */
118
    public function getSecretKey()
119
    {
120
        return $this->getService()->getSecretKey();
121
    }
122
123
    /**
124
     * @see ServiceInterface::setSecretKey()
125
     */
126
    public function setSecretKey($secretKey)
127
    {
128
        $this->getService()->setSecretKey($secretKey);
129
        return $this;
130
    }
131
132
    /**
133
     * @see AbstractAdapter::generate()
134
     * @return string
135
     */
136
    public function generate()
137
    {
138
        return '';
139
    }
140
141
    /**
142
     * @see \Zend\Validator\ValidatorInterface::isValid()
143
     * @param mixed $value
144
     * @param mixed $context
145
     * @return boolean
146
     */
147
    public function isValid($value, $context = null)
148
    {
149
        if (!is_array($value) && !is_array($context)) {
150
            $this->error(self::MISSING_INPUT_RESPONSE);
151
            return false;
152
        }
153
154
        if (!is_array($value) && is_array($context)) {
155
            $value = $context;
156
        }
157
158
        if (empty($value['g-recaptcha-response'])) {
159
            $this->error(self::MISSING_INPUT_RESPONSE);
160
            return false;
161
        }
162
163
        $service = $this->getService();
164
        $res = $service->verify($value['g-recaptcha-response']);
165
166
        if (!$res) {
167
            $this->error(self::ERROR_CAPTCHA_GENERAL);
168
            return false;
169
        }
170
171
        if (!$res->isValid()) {
172
            $errorCodes = $res->getErrorCodes();
173
            if (!empty($errorCodes)) {
174
                foreach ($errorCodes as $errorCode) {
175
                    $this->error(self::INVALID_INPUT_RESPONSE, $errorCode);
176
                }
177
                return false;
178
            }
179
180
            $this->error(self::ERROR_CAPTCHA_GENERAL);
181
            return false;
182
        }
183
184
        return true;
185
    }
186
187
    /**
188
     * @return string
189
     */
190
    public function getHelperName()
191
    {
192
        return 'captcha/recaptcha2';
193
    }
194
}
195