DeCaptchaWiki   B
last analyzed

Complexity

Total Complexity 51

Size/Duplication

Total Lines 769
Duplicated Lines 1.3 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 51
lcom 1
cbo 1
dl 10
loc 769
rs 7.751
c 0
b 0
f 0

15 Methods

Rating   Name   Duplication   Size   Complexity  
A setLang() 0 4 1
B __construct() 0 460 1
A setText() 0 7 2
B getText() 0 28 7
A viewInstall() 0 16 1
B viewExamples() 5 73 6
A getRecognizeData() 5 20 5
A getRecognizeFile() 0 8 2
B viewFields() 0 22 9
A viewFieldLine() 0 14 3
B viewMenu() 0 27 6
A getNameConst() 0 12 4
A view() 0 31 1
A getFileName() 0 9 2
A save() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like DeCaptchaWiki often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DeCaptchaWiki, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace jumper423\decaptcha\core;
4
5
/**
6
 * Class DeCaptchaAbstract.
7
 */
8
class DeCaptchaWiki
9
{
10
    protected $texts = [];
11
    /**
12
     * @var DeCaptchaBase
13
     */
14
    protected $class;
15
    protected $lang = 'en';
16
17
    public function setLang($lang)
18
    {
19
        $this->lang = $lang;
20
    }
21
22
    public function __construct($class)
23
    {
24
        $this->class = $class;
25
        $this->texts = [
26
            'constructor_data' => [
27
                $class::ACTION_FIELD_KEY => '94f39af4bb295c40546fba5c932e0d32',
28
            ],
29
            'recognize_file'                            => true,
30
            'recognize_data_file'                       => 'http://site.com/captcha.jpg',
31
            'recognize_data'                            => [],
32
            'field_main_name_'.$class::ACTION_FIELD_KEY => [
33
                'ru' => 'Ключ',
34
                'en' => 'Key',
35
            ],
36
            'field_main_desc_'.$class::ACTION_FIELD_KEY => [
37
                'ru' => 'Ключ от учетной записи',
38
                'en' => 'Key account',
39
            ],
40
            'field_main_name_'.$class::ACTION_FIELD_LANGUAGE => [
41
                'ru' => 'Язык',
42
                'en' => 'Language',
43
            ],
44
            'field_main_desc_'.$class::ACTION_FIELD_LANGUAGE => [
45
                'ru' => 'На каком языке текст на капче',
46
                'en' => 'What language the text on the captcha',
47
            ],
48
            'field_main_name_'.$class::ACTION_FIELD_LANG => [
49
                'ru' => 'Код языка',
50
                'en' => 'Language code',
51
            ],
52
            'field_main_desc_'.$class::ACTION_FIELD_LANG => [
53
                'ru' => 'См. список поддерживаемых языков. https://rucaptcha.com/api-rucaptcha#language',
54
                'en' => 'See the list of supported languages. https://2captcha.com/api-rucaptcha#language',
55
            ],
56
            'field_main_name_'.$class::ACTION_FIELD_FILE => [
57
                'ru' => 'Картинка',
58
                'en' => 'Picture',
59
            ],
60
            'field_main_desc_'.$class::ACTION_FIELD_FILE => [
61
                'ru' => 'Путь на файл с картинкой или ссылка на него',
62
                'en' => 'The path to the picture file or link to it',
63
            ],
64
            'field_main_name_'.$class::ACTION_FIELD_PHRASE => [
65
                'ru' => 'Несколько слов',
66
                'en' => 'A few words',
67
            ],
68
            'field_main_desc_'.$class::ACTION_FIELD_PHRASE => [
69
                'ru' => 'Работник должен ввести текст с одним или несколькими пробелами',
70
                'en' => 'The worker must enter text with one or more spaces',
71
            ],
72
            'field_main_name_'.$class::ACTION_FIELD_REGSENSE => [
73
                'ru' => 'Регистр',
74
                'en' => 'Register',
75
            ],
76
            'field_main_desc_'.$class::ACTION_FIELD_REGSENSE => [
77
                'ru' => 'Работник должен ввести ответ с учетом регистра',
78
                'en' => 'The worker must enter the answer case sensitive',
79
            ],
80
            'field_main_name_'.$class::ACTION_FIELD_NUMERIC => [
81
                'ru' => 'Символы',
82
                'en' => 'Characters',
83
            ],
84
            'field_main_desc_'.$class::ACTION_FIELD_NUMERIC => [
85
                'ru' => 'Какие символы используется в капче',
86
                'en' => 'What are the symbols used in captcha',
87
            ],
88
            'field_main_name_'.$class::ACTION_FIELD_CALC => [
89
                'ru' => 'Вычисление',
90
                'en' => 'Calculation',
91
            ],
92
            'field_main_desc_'.$class::ACTION_FIELD_CALC => [
93
                'ru' => 'На капче изображенно математичекая выражение и её необходимо решить',
94
                'en' => 'The captcha shows matematicheskaya expression and must be addressed',
95
            ],
96
            'field_main_name_'.$class::ACTION_FIELD_MIN_LEN => [
97
                'ru' => 'Длина min',
98
                'en' => 'Length min',
99
            ],
100
            'field_main_desc_'.$class::ACTION_FIELD_MIN_LEN => [
101
                'ru' => 'Минимальная длина капчи',
102
                'en' => 'The minimum length of captcha',
103
            ],
104
            'field_main_name_'.$class::ACTION_FIELD_MAX_LEN => [
105
                'ru' => 'Длина max',
106
                'en' => 'Length max',
107
            ],
108
            'field_main_desc_'.$class::ACTION_FIELD_MAX_LEN => [
109
                'ru' => 'Максимальная длина капчи',
110
                'en' => 'The maximum length of the captcha',
111
            ],
112
            'field_main_name_'.$class::ACTION_FIELD_QUESTION => [
113
                'ru' => 'Вопрос',
114
                'en' => 'Question',
115
            ],
116
            'field_main_desc_'.$class::ACTION_FIELD_QUESTION => [
117
                'ru' => 'На изображении задан вопрос, работник должен написать ответ',
118
                'en' => 'The image asked, the employee must write the answer',
119
            ],
120
            'field_main_name_'.$class::ACTION_FIELD_IS_RUSSIAN => [
121
                'ru' => 'Кириллица',
122
                'en' => 'Cyrillic',
123
            ],
124
            'field_main_desc_'.$class::ACTION_FIELD_IS_RUSSIAN => [
125
                'ru' => 'На изображении присутствуют русские символы',
126
                'en' => 'In the image there are Russian characters',
127
            ],
128
            'field_main_name_'.$class::ACTION_FIELD_LANGUAGE => [
129
                'ru' => 'Язык',
130
                'en' => 'Language',
131
            ],
132
            'field_main_desc_'.$class::ACTION_FIELD_LANGUAGE => [
133
                'ru' => 'Символы какого языка размещенны на капче',
134
                'en' => 'The symbols of the language posted on the captcha',
135
            ],
136
            'field_main_name_'.$class::ACTION_FIELD_HEADER_ACAO => [
137
                'ru' => 'Кросс-доменный',
138
                'en' => 'Cross-domain',
139
            ],
140
            'field_main_desc_'.$class::ACTION_FIELD_HEADER_ACAO => [
141
                'ru' => 'Необходимо для кросс-доменных AJAX запросов в браузерных приложениях.',
142
                'en' => 'Need for cross-domain AJAX requests in browser-based applications.',
143
            ],
144
            'field_main_name_'.$class::ACTION_FIELD_INSTRUCTIONS => [
145
                'ru' => 'Инструкция',
146
                'en' => 'Manual',
147
            ],
148
            'field_main_desc_'.$class::ACTION_FIELD_INSTRUCTIONS => [
149
                'ru' => 'Текстовая капча или инструкция для прохождения капчи.',
150
                'en' => 'Text captcha or manual to pass the captcha.',
151
            ],
152
            'field_main_name_'.$class::ACTION_FIELD_PINGBACK => [
153
                'ru' => 'Ответ на',
154
                'en' => 'Response to',
155
            ],
156
            'field_main_desc_'.$class::ACTION_FIELD_PINGBACK => [
157
                'ru' => 'Указание для сервера, что после распознания изображения, нужно отправить ответ на указанный адрес.',
158
                'en' => 'Note to server, after recognizing the image, you need to send a reply to the specified address.',
159
            ],
160
            'field_main_name_'.$class::ACTION_FIELD_LABEL => [
161
                'ru' => 'От куда',
162
                'en' => 'From where',
163
            ],
164
            'field_main_desc_'.$class::ACTION_FIELD_LABEL => [
165
                'ru' => 'Пояснение от куда пришла капча ("vk", "google", "recaptcha", "yandex", "mailru", "yahoo" и т.д.).',
166
                'en' => 'Clarification from where came the captcha ("vk", "google", "recaptcha", "yandex", "Google", "yahoo", etc.).',
167
            ],
168
            'field_main_name_'.$class::ACTION_FIELD_PAGEURL => [
169
                'ru' => 'Адрес',
170
                'en' => 'Link',
171
            ],
172
            'field_main_desc_'.$class::ACTION_FIELD_PAGEURL => [
173
                'ru' => 'Адрес страницы на которой решается капча.',
174
                'en' => 'The address of the page where the captcha is solved.',
175
            ],
176
            'field_main_name_'.$class::ACTION_FIELD_GOOGLEKEY => [
177
                'ru' => 'Google key',
178
                'en' => 'Google key',
179
            ],
180
            'field_main_desc_'.$class::ACTION_FIELD_GOOGLEKEY => [
181
                'ru' => 'Ключ-индентификатор рекапчи на целевой странице. <div class="g-recaptcha" data-sitekey="ВОТ_ЭТОТ"></div>',
182
                'en' => 'Key-the identifier of the recaptcha on the landing page. <div class="g-recaptcha" data-sitekey="THIS"></div>',
183
            ],
184
            'field_main_name_'.$class::ACTION_FIELD_GOOGLETOKEN => [
185
                'ru' => 'Google token',
186
                'en' => 'Google token',
187
            ],
188
            'field_main_desc_'.$class::ACTION_FIELD_GOOGLETOKEN => [
189
                'ru' => 'Секретный токен для предыдущей версии рекапчи. В большинстве случаев сайты используют новую версию и этот токен не требуется. Секретный токен генерируется на сервере Google и вставляется на страницу в атрибуте data-stoken. Выглядит это примерно так: <script type="text/javascript" src="...." data-type="normal"  data-ray="..." async data-sitekey="..." data-stoken="ВОТ_ЭТОТ"></script> Токен действует пару минут после генерации, затем нужно снова зайти на страницу и получить его.',
190
                'en' => 'The secret token for the previous version of recaptcha. In most cases, sites use the new version and this token is not required. The secret token is generated on a Google server and inserted into the page in the attribute data-stoken. It looks like this: <script type="text/javascript" src="...." data-type="normal" data-ray="..." async data-sitekey="..." data-stoken="THIS"></script> the Token is valid a few minutes after generation, then you need to go back to the page and get it.',
191
            ],
192
            'field_main_name_'.$class::ACTION_FIELD_INVISIBLE => [
193
                'ru' => 'Невидимая ReCaptcha',
194
                'en' => 'Invisible ReCaptcha',
195
            ],
196
            'field_main_desc_'.$class::ACTION_FIELD_INVISIBLE => [
197
                'ru' => '1 — говорит нам, что на сайте невидимая ReCaptcha. 0 — обычная ReCaptcha.',
198
                'en' => '1 - tells us that the site is invisible ReCaptcha. 0 - regular ReCaptcha.',
199
            ],
200
            'field_main_name_'.$class::ACTION_FIELD_SSC_USER_ID => [
201
                'ru' => 'Параметра s_s_c_user_id',
202
                'en' => 'Parameter s_s_c_user_id',
203
            ],
204
            'field_main_desc_'.$class::ACTION_FIELD_SSC_USER_ID => [
205
                'ru' => 'Значение параметра s_s_c_user_id, найденное на странице',
206
                'en' => 'The value of the s_s_c_user_id parameter found on the page',
207
            ],
208
            'field_main_name_'.$class::ACTION_FIELD_SSC_SESSION_ID => [
209
                'ru' => 'Параметра s_s_c_session_id',
210
                'en' => 'Parameter s_s_c_session_id',
211
            ],
212
            'field_main_desc_'.$class::ACTION_FIELD_SSC_SESSION_ID => [
213
                'ru' => 'Значение параметра s_s_c_session_id, найденное на странице',
214
                'en' => 'The value of the s_s_c_session_id parameter found on the page',
215
            ],
216
            'field_main_name_'.$class::ACTION_FIELD_SSC_WEB_SERVER_SIGN => [
217
                'ru' => 'Параметра s_s_c_web_server_sign',
218
                'en' => 'Parameter s_s_c_web_server_sign',
219
            ],
220
            'field_main_desc_'.$class::ACTION_FIELD_SSC_WEB_SERVER_SIGN => [
221
                'ru' => 'Значение параметра s_s_c_web_server_sign, найденное на странице',
222
                'en' => 'The value of the s_s_c_web_server_sign parameter found on the page',
223
            ],
224
            'field_main_name_'.$class::ACTION_FIELD_SSC_WEB_SERVER_SIGN2 => [
225
                'ru' => 'Параметра s_s_c_web_server_sign2',
226
                'en' => 'Parameter s_s_c_web_server_sign2',
227
            ],
228
            'field_main_desc_'.$class::ACTION_FIELD_SSC_WEB_SERVER_SIGN2 => [
229
                'ru' => 'Значение параметра s_s_c_web_server_sign2, найденное на странице',
230
                'en' => 'The value of the s_s_c_web_server_sign2 parameter found on the page',
231
            ],
232
            'field_main_name_'.$class::ACTION_FIELD_PUBLICKEY => [
233
                'ru' => 'Параметра data-pkey',
234
                'en' => 'Parameter data-pkey',
235
            ],
236
            'field_main_desc_'.$class::ACTION_FIELD_PUBLICKEY => [
237
                'ru' => 'Найти div с FunCaptcha и посмотреть на значение параметра data-pkey или же найти элемент с именем (name) fc-token, а из его значения вырезать ключ, который указан после pk',
238
                'en' => 'Find a div with FunCaptcha and look at the value of the data-pkey parameter, or find an element with the name (name) fc-token, and cut the key from its value after the pk',
239
            ],
240
            'field_main_name_'.$class::ACTION_FIELD_NOJS => [
241
                'ru' => 'Истользовать JS',
242
                'en' => 'Истользовать JS',
243
            ],
244
            'field_main_desc_'.$class::ACTION_FIELD_NOJS => [
245
                'ru' => 'Говорит нам решать FunCaptcha с выключенным javascript. Может быть использован в случае, если нормальный метод по какой-то причине не срабатывает. Важно: имейте в виду, что в этом случае мы вернём только часть токена. Выше описано, что делать в этом случае.',
246
                'en' => 'Tells us to solve FunCaptcha with javascript turned off. It can be used in case the normal method for some reason does not work. Important: keep in mind that in this case we will return only part of the token. The above is what to do in this case.',
247
            ],
248
            'field_main_name_'.$class::ACTION_FIELD_MIN_SCORE => [
249
                'ru' => 'Минимальный рейтинг',
250
                'en' => 'Min rating',
251
            ],
252
            'field_main_desc_'.$class::ACTION_FIELD_MIN_SCORE => [
253
                'ru' => 'Требуемое значение рейтинга (score). На текущий момент сложно получить токен со score выше 0.3',
254
                'en' => 'Required rating value (score). Currently it is difficult to get a token with a score above 0.3',
255
            ],
256
            'field_main_name_'.$class::ACTION_FIELD_GT => [
257
                'ru' => 'Параметр gt',
258
                'en' => 'gt parameter',
259
            ],
260
            'field_main_desc_'.$class::ACTION_FIELD_GT => [
261
                'ru' => 'Значение параметра gt найденное на сайте',
262
                'en' => 'The value of the api_server parameter found on the site',
263
            ],
264
            'field_main_name_'.$class::ACTION_FIELD_CHALLENGE => [
265
                'ru' => 'Параметр challenge',
266
                'en' => 'challenge parameter',
267
            ],
268
            'field_main_desc_'.$class::ACTION_FIELD_CHALLENGE => [
269
                'ru' => 'Значение параметра challenge найденное на сайте',
270
                'en' => 'The value of the api_server parameter found on the site',
271
            ],
272
            'field_main_name_'.$class::ACTION_FIELD_API_SERVER => [
273
                'ru' => 'Параметр api_server',
274
                'en' => 'api_server parameter',
275
            ],
276
            'field_main_desc_'.$class::ACTION_FIELD_API_SERVER => [
277
                'ru' => 'Значение параметра api_server найденное на сайте',
278
                'en' => 'The value of the api_server parameter found on the site',
279
            ],
280
            'field_main_name_'.$class::ACTION_FIELD_PROXYTYPE => [
281
                'ru' => 'Тип прокси',
282
                'en' => 'The proxy type',
283
            ],
284
            'field_main_desc_'.$class::ACTION_FIELD_PROXYTYPE => [
285
                'ru' => 'Тип прокси (http, socks4, ...)',
286
                'en' => 'The proxy type (http, socks4, ...)',
287
            ],
288
            'field_main_name_'.$class::ACTION_FIELD_PROXY => [
289
                'ru' => 'Адрес прокси',
290
                'en' => 'The proxy address',
291
            ],
292
            'field_main_desc_'.$class::ACTION_FIELD_PROXY => [
293
                'ru' => 'IP адрес прокси ipv4/ipv6.',
294
                'en' => 'IP address of the proxy ipv4/ipv6.',
295
            ],
296
            'field_main_name_'.$class::ACTION_FIELD_PROXYPORT => [
297
                'ru' => 'Порт прокси',
298
                'en' => 'Proxy port',
299
            ],
300
            'field_main_desc_'.$class::ACTION_FIELD_PROXYPORT => [
301
                'ru' => 'Порт прокси.',
302
                'en' => 'Proxy port.',
303
            ],
304
            'field_main_name_'.$class::ACTION_FIELD_PROXYLOGIN => [
305
                'ru' => 'Логин прокси',
306
                'en' => 'Login proxy',
307
            ],
308
            'field_main_desc_'.$class::ACTION_FIELD_PROXYLOGIN => [
309
                'ru' => 'Логин от прокси-сервера.',
310
                'en' => 'Login from proxy server.',
311
            ],
312
            'field_main_name_'.$class::ACTION_FIELD_PROXYPASS => [
313
                'ru' => 'Пароль прокси',
314
                'en' => 'Password proxy',
315
            ],
316
            'field_main_desc_'.$class::ACTION_FIELD_PROXYPASS => [
317
                'ru' => 'Пароль от прокси-сервера.',
318
                'en' => 'The password for the proxy server.',
319
            ],
320
            'field_main_name_'.$class::ACTION_FIELD_USERAGENT => [
321
                'ru' => 'User-Agent браузера',
322
                'en' => 'User-Agent browser',
323
            ],
324
            'field_main_desc_'.$class::ACTION_FIELD_USERAGENT => [
325
                'ru' => 'User-Agent браузера, используемый в эмуляции. Необходимо использовать подпись современного браузера, иначе Google будет возвращать ошибку, требуя обновить браузер.',
326
                'en' => 'User-Agent browser used in emulation. You must use the signature modern browser, otherwise Google will return an error requiring you to upgrade your browser.',
327
            ],
328
            'field_main_name_'.$class::ACTION_FIELD_COOKIES => [
329
                'ru' => 'Куки',
330
                'en' => 'Cookies',
331
            ],
332
            'field_main_desc_'.$class::ACTION_FIELD_COOKIES => [
333
                'ru' => 'Дополнительные cookies которые мы должны использовать во время взаимодействия с целевой страницей.',
334
                'en' => 'Additional cookies which we should use during the interaction with the target page.',
335
            ],
336
            'table_th_name' => [
337
                'ru' => 'Название',
338
                'en' => 'Name',
339
            ],
340
            'table_th_code' => [
341
                'ru' => 'Код',
342
                'en' => 'Code',
343
            ],
344
            'table_th_type' => [
345
                'ru' => 'Тип',
346
                'en' => 'Type',
347
            ],
348
            'table_th_req' => [
349
                'ru' => 'Обяз.', //Обязательное
350
                'en' => 'Req.', //Required
351
            ],
352
            'table_th_def' => [
353
                'ru' => 'По ум.', //По умолчания
354
                'en' => 'By def.', //By default
355
            ],
356
            'table_th_enum' => [
357
                'ru' => 'Возможные значения',
358
                'en' => 'Possible values',
359
            ],
360
            'table_th_desc' => [
361
                'ru' => 'Описание',
362
                'en' => 'Description',
363
            ],
364
            'slug_link' => [
365
                'ru' => 'Ссылка',
366
                'en' => 'Link',
367
            ],
368
            'slug_link_to_service' => [
369
                'ru' => 'Ссылка на сервис',
370
                'en' => 'The link to the service',
371
            ],
372
            'slug_price' => [
373
                'ru' => 'Цены',
374
                'en' => 'Prices',
375
            ],
376
            'slug_service_desc' => [
377
                'ru' => 'Описание сервиса',
378
                'en' => 'The description of the service',
379
            ],
380
            'slug_recognize_desc' => [
381
                'ru' => 'Описание распознания',
382
                'en' => 'Description recognition',
383
            ],
384
            'slug_fields_desc' => [
385
                'ru' => 'Описание полей',
386
                'en' => 'A description of the fields',
387
            ],
388
            'example' => [
389
                'ru' => 'Примеры',
390
                'en' => 'Examples',
391
            ],
392
            'example_initialization' => [
393
                'ru' => 'Инициализация',
394
                'en' => 'Initialization',
395
            ],
396
            'example_initialization_desc' => [
397
                'ru' => 'Указываем ключ, обязательные и дополнительные параметры. Старайтесь по максимуму их заполнить это способствует более быстрому распознанию капчи.',
398
                'en' => 'Specify the key mandatory and optional parameters. Try the best to fill this promotes more rapid recognition of captcha.',
399
            ],
400
            'example_recognize' => [
401
                'ru' => 'Распознавание',
402
                'en' => 'Recognition',
403
            ],
404
            'example_recognize_desc' => [
405
                'ru' => 'В первом параметре передаём ссылку или путь на файл с картинкой, во второй параметры распознания при необходимости переопределения тех которые были переданы при инициализации.',
406
                'en' => 'In the first parameter, pass the link or path to the picture file in the second parameters of the recognition if necessary, override those which were transferred during the initialization.',
407
            ],
408
            'example_nottrue' => [
409
                'ru' => 'Не верно распознано',
410
                'en' => 'Not correctly recognized',
411
            ],
412
            'example_nottrue_desc' => [
413
                'ru' => 'Если Вы сможете понять что ответ которые пришёл не верные. Обязательно добавьте ниже написанный код. Это Вам съекономит деньги.',
414
                'en' => 'If You can understand that the answer which did not come true. Be sure to add below written code. It will save You money.',
415
            ],
416
            'example_balance' => [
417
                'ru' => 'Баланс',
418
                'en' => 'Balance',
419
            ],
420
            'example_error_lang_if' => [
421
                'ru' => true,
422
                'en' => false,
423
            ],
424
            'example_error_lang' => [
425
                'ru' => 'Язык ошибки',
426
                'en' => 'Language errors',
427
            ],
428
            'example_error_lang_desc' => [
429
                'ru' => 'По умолчанию ошибки на англиском языке, если необходимо переоперелить, сделайте следующее',
430
                'en' => 'Default error in English, if you want to properlyt, do the following',
431
            ],
432
            'example_error_interception' => [
433
                'ru' => 'Перехват ошибки',
434
                'en' => 'Intercept errors',
435
            ],
436
            'example_error_interception_desc' => [
437
                'ru' => 'При желании Вы можете перехватывать ошибку, но для этого надо вызвать setCauseAnError',
438
                'en' => 'If you wish, You can catch the error, but you need to call setCauseAnError',
439
            ],
440
            'install' => [
441
                'ru' => 'Установка',
442
                'en' => 'Installation',
443
            ],
444
            'install_preferred' => [
445
                'ru' => 'Предпочтительный способ установить это расширение через',
446
                'en' => 'The preferred way to install this extension via',
447
            ],
448
            'install_start' => [
449
                'ru' => 'Либо запустить',
450
                'en' => 'Or you can run',
451
            ],
452
            'install_add' => [
453
                'ru' => 'или добавить',
454
                'en' => 'or add',
455
            ],
456
            'install_add_file' => [
457
                'ru' => 'в файл',
458
                'en' => 'in file',
459
            ],
460
            'slug_menu' => [
461
                'ru' => 'Меню',
462
                'en' => 'Menu',
463
            ],
464
            'slug_menu_main' => [
465
                'ru' => 'Главная',
466
                'en' => 'Main',
467
            ],
468
            'slug_menu_another' => [
469
                'ru' => 'Documentation in English language',
470
                'en' => 'Документация на русском языке',
471
            ],
472
            'slug_menu_anchor' => [
473
                'ru' => 'Якоря',
474
                'en' => 'Anchor',
475
            ],
476
            'slug_menu_from_service' => [
477
                'ru' => 'Другой функционал от сервиса',
478
                'en' => 'Other functionality from the service',
479
            ],
480
        ];
481
    }
482
483
    /**
484
     * @param string|array      $name
485
     * @param string|array|bool $value
486
     */
487
    public function setText($name, $value)
488
    {
489
        if (is_array($name)) {
490
            $name = implode('_', $name);
491
        }
492
        $this->texts[$name] = $value;
493
    }
494
495
    /**
496
     * @param string|array $name
497
     * @param string       $separator
498
     *
499
     * @return string|array
500
     */
501
    public function getText($name, $separator = '; ')
502
    {
503
        $getResult = function ($name, $texts) {
504
            if (is_array($name)) {
505
                $name = implode('_', $name);
506
            }
507
            if (!isset($texts[$name])) {
508
                return null;
509
            }
510
            if (is_array($texts[$name])) {
511
                if (isset($texts[$name][$this->lang])) {
512
                    return $texts[$name][$this->lang];
513
                }
514
515
                return array_values($texts[$name])[0];
516
            }
517
518
            return $texts[$name];
519
        };
520
        $result = $getResult($name, $this->texts);
521
        if (is_array($result)) {
522
            if ($separator) {
523
                $result = implode($separator, $result);
524
            }
525
        }
526
527
        return $result;
528
    }
529
530
    protected function viewInstall()
531
    {
532
        $str = "{$this->getText(['install', 'preferred'])} [composer](http://getcomposer.org/download/).".PHP_EOL;
533
        $str .= PHP_EOL;
534
        $str .= "{$this->getText(['install', 'start'])}".PHP_EOL;
535
        $str .= '```'.PHP_EOL;
536
        $str .= 'composer require --prefer-dist jumper423/decaptcha "*"'.PHP_EOL;
537
        $str .= '```'.PHP_EOL;
538
        $str .= "{$this->getText(['install', 'add'])}".PHP_EOL;
539
        $str .= '```'.PHP_EOL;
540
        $str .= '"jumper423/decaptcha": "*"'.PHP_EOL;
541
        $str .= '```'.PHP_EOL;
542
        $str .= "{$this->getText(['install', 'add', 'file'])} `composer.json`.".PHP_EOL;
543
544
        return $str;
545
    }
546
547
    protected function viewExamples()
548
    {
549
        $class = $this->class;
550
        $reflection = (new \ReflectionClass($class));
551
552
        $str = "__{$this->getText(['example', 'initialization'])}__".PHP_EOL;
553
        $str .= "{$this->getText(['example', 'initialization', 'desc'])}".PHP_EOL;
554
        $str .= '```'.PHP_EOL;
555
        $str .= "use {$reflection->getName()};".PHP_EOL;
0 ignored issues
show
Bug introduced by
Consider using $reflection->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
556
        $str .= ''.PHP_EOL;
557
        $str .= '$captcha = new '.$reflection->getShortName().'(['.PHP_EOL;
558 View Code Duplication
        foreach ($this->texts['constructor_data'] as $key => $val) {
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...
559
            $str .= "    {$reflection->getShortName()}::{$this->getNameConst('ACTION_FIELD_', $key)} => ";
560
            $str .= is_string($val) ? "'{$val}'" : $val;
561
            $str .= ','.PHP_EOL;
562
        }
563
        $str .= ']);'.PHP_EOL;
564
        $str .= '```'.PHP_EOL;
565
566
        $str .= "__{$this->getText(['example', 'recognize'])}__".PHP_EOL;
567
        $str .= "{$this->getText(['example', 'recognize', 'desc'])}".PHP_EOL;
568
        $str .= '```'.PHP_EOL;
569
        $str .= 'if ($captcha->recognize(';
570
        $str .= $this->getRecognizeFile();
571
        $str .= $this->getRecognizeData();
572
        $str .= ')) {'.PHP_EOL;
573
        $str .= '    $code = $captcha->getCode();'.PHP_EOL;
574
        $str .= '} else {'.PHP_EOL;
575
        $str .= '    $error = $captcha->getError();'.PHP_EOL;
576
        $str .= '}'.PHP_EOL;
577
        $str .= '```'.PHP_EOL;
578
579
        if (in_array('notTrue', get_class_methods($class))) {
580
            $str .= "__{$this->getText(['example', 'nottrue'])}__".PHP_EOL;
581
            $str .= "{$this->getText(['example', 'nottrue', 'desc'])}".PHP_EOL;
582
            $str .= '```'.PHP_EOL;
583
            $str .= '$captcha->notTrue();'.PHP_EOL;
584
            $str .= '```'.PHP_EOL;
585
        }
586
587
        if (in_array('getBalance', get_class_methods($class))) {
588
            $str .= "__{$this->getText(['example', 'balance'])}__".PHP_EOL;
589
            $str .= '```'.PHP_EOL;
590
            $str .= '$balance = $captcha->getBalance();'.PHP_EOL;
591
            $str .= '```'.PHP_EOL;
592
        }
593
594
        if ($this->getText(['example', 'error', 'lang', 'if'])) {
595
            $str .= "__{$this->getText(['example', 'error', 'lang'])}__".PHP_EOL;
596
            $str .= "{$this->getText(['example', 'error', 'lang', 'desc'])}".PHP_EOL;
597
            $str .= '```'.PHP_EOL;
598
            $str .= '$captcha->setErrorLang(\jumper423\decaptcha\core\DeCaptchaErrors::LANG_RU);'.PHP_EOL;
599
            $str .= '```'.PHP_EOL;
600
        }
601
602
        $str .= "__{$this->getText(['example', 'error', 'interception'])}__".PHP_EOL;
603
        $str .= "{$this->getText(['example', 'error', 'interception', 'desc'])}".PHP_EOL;
604
        $str .= '```'.PHP_EOL;
605
        $str .= '$captcha->setCauseAnError(true);'.PHP_EOL;
606
        $str .= PHP_EOL;
607
        $str .= 'try {'.PHP_EOL;
608
        $str .= '    $captcha->recognize(';
609
        $str .= $this->getRecognizeFile();
610
        $str .= $this->getRecognizeData();
611
        $str .= ');'.PHP_EOL;
612
        $str .= '    $code = $captcha->getCode();'.PHP_EOL;
613
        $str .= '} catch (\jumper423\decaptcha\core\DeCaptchaErrors $e) {'.PHP_EOL;
614
        $str .= '    ...'.PHP_EOL;
615
        $str .= '}'.PHP_EOL;
616
        $str .= '```'.PHP_EOL;
617
618
        return $str;
619
    }
620
621
    protected function getRecognizeData()
622
    {
623
        $class = $this->class;
624
        $reflection = (new \ReflectionClass($class));
625
        $str = '';
626
        if ($this->texts['recognize_data']) {
627
            if ($this->texts['recognize_file']) {
628
                $str .= ', ';
629
            }
630
            $str .= '['.PHP_EOL;
631 View Code Duplication
            foreach ($this->texts['recognize_data'] as $key => $val) {
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...
632
                $str .= "       {$reflection->getShortName()}::{$this->getNameConst('ACTION_FIELD_', $key)} => ";
633
                $str .= is_string($val) ? "'{$val}'" : $val;
634
                $str .= ','.PHP_EOL;
635
            }
636
            $str .= '    ]';
637
        }
638
639
        return $str;
640
    }
641
642
    protected function getRecognizeFile()
643
    {
644
        if (!$this->texts['recognize_file']) {
645
            return '';
646
        }
647
648
        return "'{$this->getText(['recognize', 'data', 'file'])}'";
649
    }
650
651
    protected function viewFields()
652
    {
653
        $class = $this->class;
654
        $str = " {$this->getText(['table', 'th', 'name'])} | {$this->getText(['table', 'th', 'code'])} | {$this->getText(['table', 'th', 'type'])} | {$this->getText(['table', 'th', 'req'])} | {$this->getText(['table', 'th', 'def'])} | {$this->getText(['table', 'th', 'enum'])} | {$this->getText(['table', 'th', 'desc'])} ".PHP_EOL;
655
        $str .= ' --- | --- | --- | --- | --- | --- | --- '.PHP_EOL;
656
        foreach ($this->class->actions[$class::ACTION_RECOGNIZE][$class::ACTION_FIELDS] as $param => $setting) {
657
            if (array_key_exists($class::ACTION_FIELDS, $setting) && is_array($setting[$class::ACTION_FIELDS])) {
658
                foreach ($setting[$class::ACTION_FIELDS] as $param1 => $setting1) {
659
                    if (array_key_exists($class::PARAM_SLUG_NOTWIKI, $setting1) && $setting1[$class::PARAM_SLUG_NOTWIKI] === true) {
660
                        continue;
661
                    }
662
                    $str .= $this->viewFieldLine($param1, $setting1);
663
                }
664
            }
665
            if (array_key_exists($class::PARAM_SLUG_NOTWIKI, $setting) && $setting[$class::PARAM_SLUG_NOTWIKI] === true) {
666
                continue;
667
            }
668
            $str .= $this->viewFieldLine($param, $setting);
669
        }
670
671
        return $str;
672
    }
673
674
    protected function viewFieldLine($param, $setting)
675
    {
676
        $class = $this->class;
677
        $str = " {$this->getText(['field', 'main', 'name', $param])} |";
678
        $str .= " {$this->getNameConst('ACTION_FIELD_', $param)} |";
679
        $str .= ' '.substr($this->getNameConst('PARAM_FIELD_TYPE_', $setting[$class::PARAM_SLUG_TYPE]), 17).' |';
680
        $str .= ' '.(array_key_exists($class::PARAM_SLUG_REQUIRE, $setting) ? '+' : '-').' |';
681
        $str .= ' '.(array_key_exists($class::PARAM_SLUG_DEFAULT, $setting) ? $setting[$class::PARAM_SLUG_DEFAULT] : '').' |';
682
        $str .= " {$this->getText(['field', 'slug', $class::PARAM_SLUG_ENUM, $param])} |";
683
        $str .= " {$this->getText(['field', 'main', 'desc', $param])} |";
684
        $str .= PHP_EOL;
685
686
        return $str;
687
    }
688
689
    protected function viewMenu()
690
    {
691
        $str = "+ [{$this->getText(['slug', 'menu', 'main'])}](../docs/README-{$this->lang}.md)".PHP_EOL;
692
        $str .= "+ [{$this->getText(['slug', 'menu', 'another'])}](../docs/".$this->getFileName($this->lang == 'ru' ? 'en' : 'ru').')'.PHP_EOL;
693
        $str .= "+ {$this->getText(['slug', 'menu', 'anchor'])}".PHP_EOL;
694
        foreach ([
695
                     ['slug', 'link'],
696
                     ['slug', 'service', 'desc'],
697
                     ['slug', 'price'],
698
                     ['slug', 'recognize', 'desc'],
699
                     ['install'],
700
                     ['example'],
701
                     ['slug', 'fields', 'desc'],
702
                 ] as $anchor) {
703
            $str .= "  + [{$this->getText($anchor)}](#".implode('-', explode(' ', ($this->lang === 'en' ? mb_strtolower($this->getText($anchor)) : $this->getText($anchor)))).')'.PHP_EOL;
704
        }
705
        if ($this->getText(['menu', 'from_service'])) {
706
            $str .= "+ {$this->getText(['slug', 'menu', 'from_service'])}".PHP_EOL;
707
            foreach ($this->texts['menu_from_service'] as $fromServiceClass) {
708
                $fromServiceObject = new $fromServiceClass([]);
709
                $fromServiceObjectWiki = $fromServiceObject->getWiki($this->lang);
710
                $str .= "  + [{$fromServiceObjectWiki->getText(['service', 'name'])}](../docs/{$fromServiceObjectWiki->getFileName()})".PHP_EOL;
711
            }
712
        }
713
714
        return $str;
715
    }
716
717
    protected function getNameConst($keyMask, $value)
718
    {
719
        $class = $this->class;
720
        $constants = (new \ReflectionClass($class))->getConstants();
721
        foreach ($constants as $key => $val) {
722
            if (stripos($key, $keyMask) !== false && $val === $value) {
723
                return $key;
724
            }
725
        }
726
727
        return null;
728
    }
729
730
    public function view()
731
    {
732
        $str = $this->getText(['service', 'name']).PHP_EOL;
733
        $str .= '=============='.PHP_EOL;
734
        $str .= "{$this->getText(['slug', 'menu'])}".PHP_EOL;
735
        $str .= '--------------'.PHP_EOL;
736
        $str .= $this->viewMenu().PHP_EOL.PHP_EOL;
737
        $str .= "{$this->getText(['slug', 'link'])}".PHP_EOL;
738
        $str .= '--------------'.PHP_EOL;
739
        $str .= "[{$this->getText(['slug', 'link', 'to_service'])} {$this->getText(['service', 'name'])}]({$this->getText(['service', 'href'])})".PHP_EOL.PHP_EOL;
740
        $str .= "{$this->getText(['slug', 'service', 'desc'])}".PHP_EOL;
741
        $str .= '--------------'.PHP_EOL;
742
        $str .= "{$this->getText(['service', 'desc'])}".PHP_EOL.PHP_EOL;
743
        $str .= "{$this->getText(['slug', 'price'])}".PHP_EOL;
744
        $str .= '--------------'.PHP_EOL;
745
        $str .= "{$this->getText(['recognize', 'price'])}".PHP_EOL.PHP_EOL;
746
        $str .= "{$this->getText(['slug', 'recognize', 'desc'])}".PHP_EOL;
747
        $str .= '--------------'.PHP_EOL;
748
        $str .= "{$this->getText(['recognize', 'desc'])}".PHP_EOL.PHP_EOL;
749
        $str .= "{$this->getText(['install'])}".PHP_EOL;
750
        $str .= '--------------'.PHP_EOL;
751
        $str .= "{$this->viewInstall()}".PHP_EOL.PHP_EOL;
752
        $str .= "{$this->getText(['example'])}".PHP_EOL;
753
        $str .= '--------------'.PHP_EOL;
754
        $str .= "{$this->viewExamples()}".PHP_EOL.PHP_EOL;
755
        $str .= "{$this->getText(['slug', 'fields', 'desc'])}".PHP_EOL;
756
        $str .= '--------------'.PHP_EOL;
757
        $str .= $this->viewFields().PHP_EOL;
758
759
        return $str;
760
    }
761
762
    public function getFileName($lang = null)
763
    {
764
        if (is_null($lang)) {
765
            $lang = $this->lang;
766
        }
767
        $class = $this->class;
768
769
        return (new \ReflectionClass($class))->getShortName().'-'.$lang.'.md';
770
    }
771
772
    public function save()
773
    {
774
        file_put_contents(__DIR__.'/../../docs/'.$this->getFileName(), $this->view());
775
    }
776
}
777