Test Failed
Push — main ( 6435b1...db043e )
by Paul
16:23 queued 07:02
created

CaptchaValidatorAbstract::siteVerifyUrl()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace GeminiLabs\SiteReviews\Modules\Validator;
4
5
use GeminiLabs\SiteReviews\Helper;
6
use GeminiLabs\SiteReviews\Helpers\Arr;
7
use GeminiLabs\SiteReviews\Helpers\Str;
8
use GeminiLabs\SiteReviews\Modules\Captcha;
9
10
abstract class CaptchaValidatorAbstract extends ValidatorAbstract
11
{
12
    public const CAPTCHA_DISABLED = 0;
13
    public const CAPTCHA_EMPTY = 1;
14
    public const CAPTCHA_FAILED = 2;
15
    public const CAPTCHA_INVALID = 3;
16
    public const CAPTCHA_VALID = 4;
17
18
    protected $status;
19
20
    abstract public function config(): array;
21
22
    public function isEnabled(): bool
23
    {
24
        return false;
25
    }
26
27
    public function isTokenValid(array $response): bool
28
    {
29
        return $response['success'];
30
    }
31
32
    public function isValid(): bool
33
    {
34
        if (in_array($this->status, [static::CAPTCHA_DISABLED, static::CAPTCHA_VALID])) {
35
            return true;
36
        }
37
        return false;
38
    }
39
40
    public function performValidation(): void
41
    {
42
        $this->status = $this->verifyStatus();
43
        if ($this->isValid()) {
44
            return;
45
        }
46
        $error = Helper::ifTrue($this->status === static::CAPTCHA_FAILED,
47
            __('The CAPTCHA failed to load, please refresh the page and try again.', 'site-reviews'),
48
            __('The CAPTCHA verification failed, please try again.', 'site-reviews')
49
        );
50
        $this->fail($error);
51
    }
52
53
    protected function data(): array
54
    {
55
        return [];
56
    }
57
58
    protected function errors(array $errors): array
59
    {
60
        $codes = $this->errorCodes();
61
        $errors = array_fill_keys($errors, '');
62
        return array_merge(
63
            array_intersect_key($codes, $errors), // known errors
64
            array_diff_key($errors, $codes) // unknown errors
65
        );
66
    }
67
68
    protected function errorCodes(): array
69
    {
70
        return [];
71
    }
72
73
    protected function getLocale(): string
74
    {
75
        $locale = '';
76
        if (function_exists('locale_parse')) {
77
            $values = locale_parse(get_locale());
78
            if (!empty($values['language'])) {
79
                $locale = $values['language'];
80
            }
81
        }
82
        return glsr()->filterString('captcha/language', $locale);
83
    }
84
85
    protected function makeRequest(array $data): array
86
    {
87
        $response = wp_remote_post($this->siteVerifyUrl(), [
88
            'body' => $data,
89
        ]);
90
        if (is_wp_error($response)) {
91
            glsr_log()->error($response->get_error_message());
92
            return [];
93
        }
94
        $body = json_decode(wp_remote_retrieve_body($response), true);
95
        return $this->response($body);
96
    }
97
98
    protected function response(array $body): array
99
    {
100
        $errors = Arr::consolidate(Arr::get($body, 'error-codes', Arr::get($body, 'errors')));
101
        return [
102
            'action' => Arr::get($body, 'action'),
103
            'errors' => $this->errors($errors),
104
            'score' => Arr::get($body, 'score', 0),
105
            'success' => wp_validate_boolean(Arr::get($body, 'success')),
106
        ];
107
    }
108
109
    protected function siteKey(): string
110
    {
111
        return '';
112
    }
113
114
    protected function siteSecret(): string
115
    {
116
        return '';
117
    }
118
119
    protected function siteVerifyUrl(): string
120
    {
121
        return '';
122
    }
123
124
    protected function token(): string
125
    {
126
        return '';
127
    }
128
129
    protected function verifyStatus(): int
130
    {
131
        if (!$this->isEnabled()) {
132
            return static::CAPTCHA_DISABLED;
133
        }
134
        return $this->verifyToken();
135
    }
136
137
    protected function verifyToken(): int
138
    {
139
        if (empty($this->token())) {
140
            return static::CAPTCHA_EMPTY; // fail early
141
        }
142
        $data = $this->data();
143
        $response = $this->makeRequest($data);
144
        if (empty($response)) {
145
            return static::CAPTCHA_FAILED;
146
        }
147
        if ($this->isTokenValid($response)) {
148
            return static::CAPTCHA_VALID;
149
        }
150
        if (!empty($response['errors'])) {
151
            $data['secret'] = Str::mask($this->siteSecret(), 4, 4, 20);
152
            $data['sitekey'] = Str::mask($this->siteKey(), 4, 4, 20);
153
            glsr_log()->error($response)->debug($data);
154
        }
155
        if (empty($data['secret']) || empty($data['sitekey'])) {
156
            return static::CAPTCHA_FAILED;
157
        }
158
        return static::CAPTCHA_INVALID;
159
    }
160
}
161