Completed
Push — master ( 1eaac3...200d07 )
by Владислав
02:18
created

DeCaptchaBase::recognize()   C

Complexity

Conditions 11
Paths 22

Size

Total Lines 37
Code Lines 28

Duplication

Lines 14
Ratio 37.84 %

Importance

Changes 0
Metric Value
dl 14
loc 37
rs 5.2653
c 0
b 0
f 0
cc 11
eloc 28
nc 22
nop 1

How to fix   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
namespace jumper423\decaptcha\core;
4
5
use Exception;
6
7
/**
8
 * Распознавание капчи.
9
 *
10
 * Class DeCaptchaBase
11
 */
12
class DeCaptchaBase extends DeCaptchaAbstract implements DeCaptchaInterface
13
{
14
    const PARAM_FIELD_METHOD = 0;
15
    const PARAM_FIELD_KEY = 1;
16
    const PARAM_FIELD_FILE = 2;
17
    const PARAM_FIELD_PHRASE = 3;
18
    const PARAM_FIELD_REGSENSE = 4;
19
    const PARAM_FIELD_NUMERIC = 5;
20
    const PARAM_FIELD_MIN_LEN = 6;
21
    const PARAM_FIELD_MAX_LEN = 7;
22
    const PARAM_FIELD_LANGUAGE = 8;
23
    const PARAM_FIELD_SOFT_ID = 9;
24
    const PARAM_FIELD_CAPTCHA_ID = 10;
25
    const PARAM_FIELD_ACTION = 11;
26
    const PARAM_FIELD_QUESTION = 12;
27
    const PARAM_FIELD_CALC = 13;
28
    const PARAM_FIELD_HEADER_ACAO = 14;
29
    const PARAM_FIELD_TEXTINSTRUCTIONS = 15;
30
    const PARAM_FIELD_PINGBACK = 16;
31
32
    const ACTION_RECOGNIZE = 0;
33
    const ACTION_UNIVERSAL = 1;
34
    const ACTION_UNIVERSAL_WITH_CAPTCHA = 2;
35
36
    protected $paramsNames = [
37
        self::PARAM_FIELD_METHOD               => 'method',
38
        self::PARAM_FIELD_KEY                  => 'key',
39
        self::PARAM_FIELD_FILE                 => 'file',
40
        self::PARAM_FIELD_PHRASE               => 'phrase',
41
        self::PARAM_FIELD_REGSENSE             => 'regsense',
42
        self::PARAM_FIELD_NUMERIC              => 'numeric',
43
        self::PARAM_FIELD_MIN_LEN              => 'min_len',
44
        self::PARAM_FIELD_MAX_LEN              => 'max_len',
45
        self::PARAM_FIELD_LANGUAGE             => 'language',
46
        self::PARAM_FIELD_SOFT_ID              => 'soft_id',
47
        self::PARAM_FIELD_CAPTCHA_ID           => 'id',
48
        self::PARAM_FIELD_ACTION               => 'action',
49
        self::PARAM_FIELD_QUESTION             => 'question',
50
        self::PARAM_FIELD_HEADER_ACAO          => 'header_acao',
51
        self::PARAM_FIELD_TEXTINSTRUCTIONS     => 'textinstructions',
52
        self::PARAM_FIELD_PINGBACK             => 'pingback',
53
    ];
54
55
    protected $paramsSettings = [
56
        self::ACTION_RECOGNIZE => [
57
            self::PARAM_FIELD_METHOD => [
58
                self::PARAM_SLUG_DEFAULT => 'post',
59
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_STRING,
60
            ],
61
            self::PARAM_FIELD_KEY => [
62
                self::PARAM_SLUG_REQUIRE => true,
63
                self::PARAM_SLUG_SPEC    => self::PARAM_SPEC_KEY,
64
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_STRING,
65
            ],
66
            self::PARAM_FIELD_FILE => [
67
                self::PARAM_SLUG_REQUIRE => true,
68
                self::PARAM_SLUG_SPEC    => self::PARAM_SPEC_FILE,
69
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_STRING,
70
            ],
71
            self::PARAM_FIELD_PHRASE => [
72
                self::PARAM_SLUG_DEFAULT => 0,
73
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
74
            ],
75
            self::PARAM_FIELD_REGSENSE => [
76
                self::PARAM_SLUG_DEFAULT => 0,
77
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
78
            ],
79
            self::PARAM_FIELD_NUMERIC => [
80
                self::PARAM_SLUG_DEFAULT => 0,
81
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
82
            ],
83
            self::PARAM_FIELD_MIN_LEN => [
84
                self::PARAM_SLUG_DEFAULT => 0,
85
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
86
            ],
87
            self::PARAM_FIELD_MAX_LEN => [
88
                self::PARAM_SLUG_DEFAULT => 0,
89
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
90
            ],
91
            self::PARAM_FIELD_LANGUAGE => [
92
                self::PARAM_SLUG_DEFAULT => 0,
93
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
94
            ],
95
            self::PARAM_FIELD_QUESTION => [
96
                self::PARAM_SLUG_DEFAULT => 0,
97
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
98
            ],
99
            self::PARAM_FIELD_CALC => [
100
                self::PARAM_SLUG_DEFAULT => 0,
101
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
102
            ],
103
            self::PARAM_FIELD_HEADER_ACAO => [
104
                self::PARAM_SLUG_DEFAULT => 0,
105
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
106
            ],
107
            self::PARAM_FIELD_TEXTINSTRUCTIONS => [
108
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_STRING,
109
            ],
110
            self::PARAM_FIELD_PINGBACK => [
111
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_STRING,
112
            ],
113
            self::PARAM_FIELD_SOFT_ID => [
114
                self::PARAM_SLUG_VARIABLE => false,
115
                self::PARAM_SLUG_TYPE     => self::PARAM_FIELD_TYPE_INTEGER,
116
            ],
117
        ],
118
        self::ACTION_UNIVERSAL => [
119
            self::PARAM_FIELD_KEY => [
120
                self::PARAM_SLUG_REQUIRE => true,
121
                self::PARAM_SLUG_SPEC    => self::PARAM_SPEC_KEY,
122
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_STRING,
123
            ],
124
            self::PARAM_FIELD_ACTION => [
125
                self::PARAM_SLUG_REQUIRE => true,
126
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_STRING,
127
            ],
128
            self::PARAM_FIELD_HEADER_ACAO => [
129
                self::PARAM_SLUG_DEFAULT => 0,
130
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
131
            ],
132
        ],
133
        self::ACTION_UNIVERSAL_WITH_CAPTCHA => [
134
            self::PARAM_FIELD_KEY => [
135
                self::PARAM_SLUG_REQUIRE => true,
136
                self::PARAM_SLUG_SPEC    => self::PARAM_SPEC_KEY,
137
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_STRING,
138
            ],
139
            self::PARAM_FIELD_CAPTCHA_ID => [
140
                self::PARAM_SLUG_REQUIRE => true,
141
                self::PARAM_SLUG_SPEC    => self::PARAM_SPEC_CAPTCHA,
142
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
143
            ],
144
            self::PARAM_FIELD_ACTION => [
145
                self::PARAM_SLUG_REQUIRE => true,
146
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_STRING,
147
            ],
148
            self::PARAM_FIELD_HEADER_ACAO => [
149
                self::PARAM_SLUG_DEFAULT => 0,
150
                self::PARAM_SLUG_TYPE    => self::PARAM_FIELD_TYPE_INTEGER,
151
            ],
152
        ],
153
    ];
154
155
    protected $code;
156
157
    protected $limitSettings = [
158
        self::ACTION_RECOGNIZE => 3,
159
        self::ACTION_UNIVERSAL_WITH_CAPTCHA => 20,
160
    ];
161
162
    protected $limit = [];
163
164
    protected function clearLimit(){
165
        foreach ($this->limitSettings as $action => $value) {
166
            $this->limit[$action] = $value;
167
        }
168
    }
169
170
    public function recognize($filePath)
171
    {
172
        try {
173
            $this->clearLimit();
174
            $this->setParamSpec(static::PARAM_SPEC_FILE, $this->getFilePath($filePath));
175
            $response = $this->getCurlResponse($this->getInUrl(), $this->getParams(static::ACTION_RECOGNIZE));
176
            $data = $this->decodeResponse(static::DECODE_ACTION_RECOGNIZE, $response);
177
            if ($data[static::DECODE_PARAM_RESPONSE] === 'OK' && !empty($data[static::DECODE_PARAM_CAPTCHA])) {
178
                $this->setParamSpec(static::PARAM_SPEC_CAPTCHA, $data[static::DECODE_PARAM_CAPTCHA]);
179 View Code Duplication
            } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
180
                if ($data[static::DECODE_PARAM_RESPONSE] === 'ERROR_NO_SLOT_AVAILABLE' && $this->limit[static::ACTION_RECOGNIZE] > 0) {
181
                    $this->limit[static::ACTION_RECOGNIZE]--;
182
                    return $this->recognize($filePath);
183
                }
184
                throw new DeCaptchaErrors($data[static::DECODE_PARAM_RESPONSE]);
185
            }
186
            while ($this->limit[static::ACTION_UNIVERSAL_WITH_CAPTCHA] > 0) {
187
                $response = $this->getResponse(static::ACTION_UNIVERSAL_WITH_CAPTCHA);
188
                $data = $this->decodeResponse(static::DECODE_ACTION_GET, $response);
189
                if ($data[static::DECODE_PARAM_RESPONSE] === 'OK' && !empty($data[static::DECODE_PARAM_CODE])) {
190
                    $this->code = $data[static::DECODE_PARAM_CODE];
191
                    return true;
192 View Code Duplication
                } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
193
                    $this->limit[static::ACTION_UNIVERSAL_WITH_CAPTCHA]--;
194
                    if ($data[static::DECODE_PARAM_RESPONSE] === 'CAPCHA_NOT_READY' && $this->limit[static::ACTION_UNIVERSAL_WITH_CAPTCHA] > 0) {
195
                        continue;
196
                    }
197
                    throw new DeCaptchaErrors($data[static::DECODE_PARAM_RESPONSE]);
198
                }
199
            }
200
        } catch (Exception $e) {
201
            $this->error = $e->getMessage();
0 ignored issues
show
Bug introduced by
The property error does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
202
203
            return false;
204
        }
205
        return false;
206
    }
207
208
    public function getCode()
209
    {
210
    }
211
212
    public function getError()
213
    {
214
    }
215
216
    /**
217
     * Запуск распознавания капчи.
218
     *
219
     * @deprecated
220
     *
221
     * @param string $filePath Путь до файла или ссылка на него
222
     *
223
     * @return bool
224
     */
225
    public function run($filePath)
226
    {
227
        return $this->recognize($filePath);
228
    }
229
230
    /**
231
     * Не верно распознана.
232
     */
233
    public function notTrue()
234
    {
235
        $this->getResponse('reportbad');
236
    }
237
238
    const DECODE_FORMAT = 0;
239
    const DECODE_ACTION = 1;
240
    const DECODE_SEPARATOR = 2;
241
    const DECODE_PARAMS = 3;
242
    const DECODE_PARAM_SETTING_MARKER = 4;
243
244
    const DECODE_ACTION_RECOGNIZE = 0;
245
    const DECODE_ACTION_GET = 1;
246
247
    const DECODE_PARAM_RESPONSE = 0;
248
    const DECODE_PARAM_CAPTCHA = 1;
249
    const DECODE_PARAM_CODE = 2;
250
251
    protected $decodeSettings = [
252
        self::DECODE_FORMAT => self::RESPONSE_TYPE_STRING,
253
        self::DECODE_ACTION => [
254
            self::DECODE_ACTION_RECOGNIZE => [
255
                self::DECODE_SEPARATOR => '|',
256
                self::DECODE_PARAMS    => [
257
                    self::DECODE_PARAM_RESPONSE => [
258
                        self::DECODE_PARAM_SETTING_MARKER => 0,
259
                    ],
260
                    self::DECODE_PARAM_CAPTCHA => [
261
                        self::DECODE_PARAM_SETTING_MARKER => 1,
262
                    ],
263
                ],
264
            ],
265
            self::DECODE_ACTION_GET => [
266
                self::DECODE_SEPARATOR => '|',
267
                self::DECODE_PARAMS    => [
268
                    self::DECODE_PARAM_RESPONSE => [
269
                        self::DECODE_PARAM_SETTING_MARKER => 0,
270
                    ],
271
                    self::DECODE_PARAM_CODE => [
272
                        self::DECODE_PARAM_SETTING_MARKER => 1,
273
                    ],
274
                ],
275
            ],
276
        ],
277
    ];
278
279
    protected function decodeResponse($action, $data)
280
    {
281
        if (!array_key_exists($action, $this->decodeSettings[static::DECODE_ACTION])) {
282
            throw new DeCaptchaErrors('нет action');
283
        }
284
        $decodeSetting = $this->decodeSettings[static::DECODE_ACTION][$action];
285
        $decodeFormat = array_key_exists(static::DECODE_FORMAT, $decodeSetting) ?
286
            $decodeSetting[static::DECODE_FORMAT] :
287
            $this->decodeSettings[static::DECODE_FORMAT];
288
        $values = [];
289
        switch ($decodeFormat) {
290
            case static::RESPONSE_TYPE_STRING:
291
                foreach (explode($decodeFormat[static::DECODE_SEPARATOR], $data) as $key => $value) {
292
                    foreach ($decodeFormat[static::DECODE_PARAMS] as $param => $paramKey) {
293
                        if ($key === $paramKey) {
294
                            $values[$param] = $value;
295
                        }
296
                    }
297
                }
298
                break;
299
        }
300
301
        return $values;
302
    }
303
}
304