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

DeCaptchaBase::recognize()   D

Complexity

Conditions 10
Paths 24

Size

Total Lines 42
Code Lines 31

Duplication

Lines 18
Ratio 42.86 %

Importance

Changes 0
Metric Value
dl 18
loc 42
rs 4.8196
c 0
b 0
f 0
cc 10
eloc 31
nc 24
nop 2

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
    public function recognize($filePath, $limit = 3)
156
    {
157
        try {
158
            $this->setParamSpec(static::PARAM_SPEC_FILE, $this->getFilePath($filePath));
159
            $response = $this->getCurlResponse($this->getInUrl(), $this->getParams(static::ACTION_RECOGNIZE));
160
            $data = $this->decodeResponse(static::DECODE_ACTION_RECOGNIZE, $response);
161
            if ($data[static::DECODE_PARAM_RESPONSE] === 'OK' && !empty($data[static::DECODE_PARAM_CODE])) {
162
                $this->setParamSpec(static::PARAM_SPEC_CAPTCHA, $data[static::DECODE_PARAM_CAPTCHA]);
163
            } else {
164
                if ($data[static::DECODE_PARAM_RESPONSE] === 'ERROR_NO_SLOT_AVAILABLE' && $limit > 0) {
165
                    return $this->recognize($filePath, $limit--);
166
                }
167
                throw new DeCaptchaErrors($data[static::DECODE_PARAM_RESPONSE]);
168
            }
169
            list(, $this->captchaId) = explode('|', $result);
0 ignored issues
show
Bug introduced by
The variable $result seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
170
            $waitTime = 0;
171
            sleep($this->requestTimeout);
0 ignored issues
show
Bug introduced by
The property requestTimeout 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...
172 View Code Duplication
            while (true) {
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...
173
                $result = $this->getResponse('get');
174
                $this->setError($result);
0 ignored issues
show
Bug introduced by
The method setError() does not exist on jumper423\decaptcha\core\DeCaptchaBase. Did you maybe mean setErrorLang()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
175
                if ($result == 'CAPCHA_NOT_READY') {
176
                    $waitTime += $this->requestTimeout;
177
                    if ($waitTime > $this->maxTimeout) {
0 ignored issues
show
Bug introduced by
The property maxTimeout 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...
178
                        break;
179
                    }
180
                    sleep($this->requestTimeout);
181
                } else {
182
                    $ex = explode('|', $result);
183
                    if (trim($ex[0]) == 'OK') {
184
                        $this->result = trim($ex[1]);
0 ignored issues
show
Bug introduced by
The property result 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...
185
186
                        return true;
187
                    }
188
                }
189
            }
190
            throw new Exception('Лимит времени превышен');
191
        } catch (Exception $e) {
192
            $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...
193
194
            return false;
195
        }
196
    }
197
198
    public function getCode()
199
    {
200
    }
201
202
    public function getError()
203
    {
204
    }
205
206
    /**
207
     * Запуск распознавания капчи.
208
     *
209
     * @deprecated
210
     *
211
     * @param string $filePath Путь до файла или ссылка на него
212
     *
213
     * @return bool
214
     */
215
    public function run($filePath)
216
    {
217
        return $this->recognize($filePath);
218
    }
219
220
    /**
221
     * Не верно распознана.
222
     */
223
    public function notTrue()
224
    {
225
        $this->getResponse('reportbad');
226
    }
227
228
    const DECODE_FORMAT = 0;
229
    const DECODE_ACTION = 1;
230
    const DECODE_SEPARATOR = 2;
231
    const DECODE_PARAMS = 3;
232
    const DECODE_PARAM_SETTING_MARKER = 4;
233
234
    const DECODE_ACTION_RECOGNIZE = 0;
235
    const DECODE_ACTION_GET = 1;
236
237
    const DECODE_PARAM_RESPONSE = 0;
238
    const DECODE_PARAM_CAPTCHA = 1;
239
    const DECODE_PARAM_CODE = 2;
240
241
    protected $decodeSettings = [
242
        self::DECODE_FORMAT => self::RESPONSE_TYPE_STRING,
243
        self::DECODE_ACTION => [
244
            self::DECODE_ACTION_RECOGNIZE => [
245
                self::DECODE_SEPARATOR => '|',
246
                self::DECODE_PARAMS    => [
247
                    self::DECODE_PARAM_RESPONSE => [
248
                        self::DECODE_PARAM_SETTING_MARKER => 0,
249
                    ],
250
                    self::DECODE_PARAM_CAPTCHA => [
251
                        self::DECODE_PARAM_SETTING_MARKER => 1,
252
                    ],
253
                ],
254
            ],
255
            self::DECODE_ACTION_GET => [
256
                self::DECODE_SEPARATOR => '|',
257
                self::DECODE_PARAMS    => [
258
                    self::DECODE_PARAM_RESPONSE => [
259
                        self::DECODE_PARAM_SETTING_MARKER => 0,
260
                    ],
261
                    self::DECODE_PARAM_CODE => [
262
                        self::DECODE_PARAM_SETTING_MARKER => 1,
263
                    ],
264
                ],
265
            ],
266
        ],
267
    ];
268
269
    protected function decodeResponse($action, $data)
270
    {
271
        if (!array_key_exists($action, $this->decodeSettings[static::DECODE_ACTION])) {
272
            throw new DeCaptchaErrors('нет action');
273
        }
274
        $decodeSetting = $this->decodeSettings[static::DECODE_ACTION][$action];
275
        $decodeFormat = array_key_exists(static::DECODE_FORMAT, $decodeSetting) ?
276
            $decodeSetting[static::DECODE_FORMAT] :
277
            $this->decodeSettings[static::DECODE_FORMAT];
278
        $values = [];
279
        switch ($decodeFormat) {
280
            case static::RESPONSE_TYPE_STRING:
281
                foreach (explode($decodeFormat[static::DECODE_SEPARATOR], $data) as $key => $value) {
282
                    foreach ($decodeFormat[static::DECODE_PARAMS] as $param => $paramKey) {
283
                        if ($key === $paramKey) {
284
                            $values[$param] = $value;
285
                        }
286
                    }
287
                }
288
                break;
289
        }
290
291
        return $values;
292
    }
293
}
294