Weglot Translate – Translate your WP website - Version 1.11

Version Description

(05/04/2018)

Download this release

Release Info

Developer remyb92
Plugin Icon 128x128 Weglot Translate – Translate your WP website
Version 1.11
Comparing to
See all releases

Code changes from version 1.10 to 1.11

WeglotPHPClient/src/Client.php DELETED
@@ -1,695 +0,0 @@
1
- <?php
2
- namespace Weglot;
3
- use WeglotSDP;
4
- class Client {
5
-
6
- protected $api_key;
7
-
8
- const API_BASE = 'https://api.weglot.com';
9
- const API_BASE_OLD = 'https://weglot.com/api/';
10
-
11
- function __construct( $key ) {
12
- $this->api_key = $key;
13
-
14
- if ( $this->api_key == null || mb_strlen( $this->api_key ) == 0 ) {
15
- return null;
16
- }
17
- }
18
-
19
- public function hasAncestorAttribute( $node, $attribute ) {
20
-
21
- $currentNode = $node;
22
-
23
- if ( isset( $currentNode->$attribute ) ) {
24
- return true;
25
- }
26
-
27
- while ( $currentNode->parent() && $currentNode->parent()->tag != 'html' ) {
28
-
29
- if ( isset( $currentNode->parent()->$attribute ) ) {
30
- return true;
31
- } else {
32
- $currentNode = $currentNode->parent();
33
- }
34
- }
35
- return false;
36
- }
37
-
38
- public function checkTitle( $row ) {
39
- return true;
40
- }
41
-
42
- public function checkText( $row ) {
43
- return ($row->parent()->tag != 'script'
44
- && $row->parent()->tag != 'style'
45
- && $row->parent()->tag != 'noscript'
46
- && $row->parent()->tag != 'title'
47
- && $row->parent()->tag != 'code'
48
- && ! is_numeric( $this->full_trim( $row->outertext ) )
49
- && ! preg_match( '/^\d+%$/',$this->full_trim( $row->outertext ) )
50
- && strpos( $row->outertext,'[vc_' ) === false);
51
- }
52
-
53
- public function checkButton( $row ) {
54
- return ( ! is_numeric( $this->full_trim( $row->value ) )
55
- && ! preg_match( '/^\d+%$/',$this->full_trim( $row->value ) ));
56
- }
57
-
58
- public function checkTd_dt( $row ) {
59
- return true;
60
- }
61
-
62
- public function checkInput_dv( $row ) {
63
- return true;
64
- }
65
-
66
- public function checkInput_dobt( $row ) {
67
- return true;
68
- }
69
-
70
- public function checkRad_obt ($row ) {
71
- return true;
72
- }
73
-
74
-
75
- public function checkPlaceholder( $row ) {
76
- return ( ! is_numeric( $this->full_trim( $row->placeholder ) )
77
- && ! preg_match( '/^\d+%$/',$this->full_trim( $row->placeholder ) ) );
78
- }
79
-
80
- public function checkMeta_desc( $row ) {
81
- return ( ! is_numeric( $this->full_trim( $row->placeholder ) )
82
- && ! preg_match( '/^\d+%$/',$this->full_trim( $row->placeholder ) ) );
83
- }
84
-
85
- public function checkIframe_src( $row ) {
86
- return (strpos( $this->full_trim( $row->src ),'youtube.' ) !== false);
87
- }
88
-
89
- public function checkSource_src( $row ) {
90
- return true;
91
- }
92
-
93
- public function checkImg_src( $row ) {
94
- return true;
95
- }
96
-
97
- public function checkImg_alt( $row ) {
98
- return true;
99
- }
100
-
101
- public function checkA_pdf( $row ) {
102
- return (
103
- strtolower( substr( $this->full_trim( $row->href ),-4 ) ) == '.pdf'
104
- || strtolower( substr( $this->full_trim( $row->href ),-4 ) ) == '.rar'
105
- || strtolower( substr( $this->full_trim( $row->href ),-4 ) ) == 'docx'
106
- );
107
- }
108
-
109
- public function checkA_title( $row ) {
110
- return true;
111
- }
112
-
113
- public function checkA_dv( $row ) {
114
- return true;
115
- }
116
-
117
- public function checkA_dt( $row ) {
118
- return true;
119
- }
120
-
121
- public function checkA_dto( $row ) {
122
- return true;
123
- }
124
-
125
- public function checkA_dho( $row ) {
126
- return true;
127
- }
128
-
129
- public function checkA_dco( $row ) {
130
- return true;
131
- }
132
-
133
- public function checkA_dte( $row ) {
134
- return true;
135
- }
136
-
137
- function searchForId( $id, $array ) {
138
- foreach ( $array as $key => $val ) {
139
- if ( $val['uid'] === $id ) {
140
- return $key;
141
- }
142
- }
143
- return null;
144
- }
145
-
146
- public function ignoreNodes($dom) {
147
- $nodes_to_ignore = array(
148
- array('<strong>','</strong>'),
149
- array('<em>','</em>'),
150
- array('<abbr>','</abbr>'),
151
- array('<acronym>','</acronym>'),
152
- array('<b>','</b>'),
153
- array('<bdo>','</bdo>'),
154
- array('<big>','</big>'),
155
- array('<cite>','</cite>'),
156
- array('<kbd>','</kbd>'),
157
- array('<q>','</q>'),
158
- array('<small>','</small>'),
159
- array('<sub>','</sub>'),
160
- array('<sup>','</sup>'),
161
- );
162
-
163
- foreach ($nodes_to_ignore as $ignore) {
164
- $pattern = '#'.$ignore[0].'([^>]*)?'.$ignore[1].'#';
165
- $replace = htmlentities($ignore[0]).'$1'.htmlentities($ignore[1]);
166
- $dom = preg_replace($pattern,$replace,$dom);
167
- }
168
-
169
- return $dom;
170
- }
171
-
172
- public function translateDomFromTo( $dom, $l_from, $l_to ) {
173
- if(strlen($this->api_key)==36)
174
- $dom = $this->ignoreNodes($dom);
175
-
176
- $html = WeglotSDP\str_get_html( $dom, true, true, WG_DEFAULT_TARGET_CHARSET, false, WG_DEFAULT_BR_TEXT, WG_DEFAULT_SPAN_TEXT );
177
-
178
- $exceptions = explode( ',',get_option( 'exclude_blocks' ) );
179
- array_push( $exceptions,'#wpadminbar' );
180
- foreach ( $exceptions as $exception ) {
181
- foreach ( $html->find( $exception ) as $k => $row ) {
182
- $attribute = 'data-wg-notranslate';
183
- $row->$attribute = '';
184
- }
185
- }
186
-
187
- $words = array();
188
- $nodes = array();
189
-
190
- $elements_to_check = array(
191
-
192
- 'title'
193
- => array(
194
- array(
195
- 'property' => 'innertext',
196
- 't' => 4,
197
- 'type' => 'text',
198
- ),
199
- ),
200
-
201
-
202
- 'meta[name="description"],meta[property="og:title"],meta[property="og:description"],meta[property="og:site_name"],meta[name="twitter:title"],meta[name="twitter:description"]'
203
- => array(
204
- array(
205
- 'property' => 'content',
206
- 't' => 4,
207
- 'type' => 'meta_desc',
208
- ),
209
- ),
210
-
211
- 'text'
212
- => array(
213
- array(
214
- 'property' => 'outertext',
215
- 't' => 1,
216
- 'type' => 'text',
217
- ),
218
- ),
219
-
220
-
221
- "input[type='submit'],input[type='button'],button"
222
- => array(
223
- array(
224
- 'property' => 'value',
225
- 't' => 2,
226
- 'type' => 'button',
227
- ),
228
- array(
229
- 'property' => 'data-value',
230
- 't' => 1,
231
- 'type' => 'input_dv',
232
- ),
233
- array(
234
- 'property' => 'data-order_button_text',
235
- 't' => 1,
236
- 'type' => 'input_dobt',
237
- ),
238
- ),
239
-
240
- "input[type='radio']"
241
- => array(
242
- array(
243
- 'property' => 'data-order_button_text',
244
- 't' => 2,
245
- 'type' => 'rad_obt',
246
- ),
247
- ),
248
-
249
-
250
- "td"
251
- => array(
252
- array(
253
- 'property' => 'data-title',
254
- 't' => 2,
255
- 'type' => 'td_dt',
256
- ),
257
- ),
258
-
259
- "input[type=\'text\'],input[type=\'password\'],input[type=\'search\'],input[type=\'email\'],input:not([type]),textarea"
260
- => array(
261
- array(
262
- 'property' => 'placeholder',
263
- 't' => 3,
264
- 'type' => 'placeholder',
265
- ),
266
- ),
267
-
268
- 'iframe'
269
- => array(
270
- array(
271
- 'property' => 'src',
272
- 't' => 5,
273
- 'type' => 'iframe_src',
274
- ),
275
- ),
276
-
277
- 'img'
278
- => array(
279
- array(
280
- 'property' => 'src',
281
- 't' => 6,
282
- 'type' => 'img_src',
283
- ),
284
- array(
285
- 'property' => 'alt',
286
- 't' => 7,
287
- 'type' => 'img_alt',
288
- ),
289
- ),
290
-
291
- 'source'
292
- => array(
293
- array(
294
- 'property' => 'src',
295
- 't' => 5,
296
- 'type' => 'source_src',
297
- ),
298
- ),
299
-
300
- 'a'
301
- => array(
302
- array(
303
- 'property' => 'href',
304
- 't' => 8,
305
- 'type' => 'a_pdf',
306
- ),
307
- array(
308
- 'property' => 'title',
309
- 't' => 1,
310
- 'type' => 'a_title',
311
- ),
312
- array(
313
- 'property' => 'data-value',
314
- 't' => 1,
315
- 'type' => 'a_dv',
316
- ),
317
- array(
318
- 'property' => 'data-title',
319
- 't' => 1,
320
- 'type' => 'a_dt',
321
- ),
322
- array(
323
- 'property' => 'data-tooltip',
324
- 't' => 1,
325
- 'type' => 'a_dto',
326
- ),
327
- array(
328
- 'property' => 'data-hover',
329
- 't' => 1,
330
- 'type' => 'a_dho',
331
- ),
332
- array(
333
- 'property' => 'data-content',
334
- 't' => 1,
335
- 'type' => 'a_dco',
336
- ),
337
- array(
338
- 'property' => 'data-text',
339
- 't' => 1,
340
- 'type' => 'a_dte',
341
- ),
342
- ),
343
-
344
- );
345
-
346
- foreach ( $elements_to_check as $key => $elem ) {
347
- foreach ( $html->find( $key ) as $k => $row ) {
348
-
349
- foreach ( $elem as $element ) {
350
-
351
- $property = $element['property'];
352
- $t = $element['t'];
353
- $type = $element['type'];
354
- $functionName = 'check' . ucfirst( $type );
355
-
356
- if ( $this->full_trim( $row->$property ) != '' && ! $this->hasAncestorAttribute( $row, 'data-wg-notranslate' )
357
- && $this->$functionName($row)
358
- ) {
359
- array_push(
360
- $words, array(
361
- 't' => $t,
362
- 'w' => $row->$property,
363
- )
364
- );
365
- array_push(
366
- $nodes, array(
367
- 'node' => $row,
368
- 'type' => $type,
369
- 'property' => $property,
370
- )
371
- );
372
- }
373
- }
374
- }
375
- }
376
-
377
-
378
-
379
- $microData = array("description");
380
- $jsons = array();
381
- $nbJsonStrings = 0;
382
- foreach ( $html->find( 'script[type="application/ld+json"]' ) as $k => $row ) {
383
- $mustAddjson = false;
384
- $json = json_decode($row->innertext,true);
385
- if (json_last_error() === JSON_ERROR_NONE) {
386
- foreach($microData as $key) {
387
-
388
- $path = explode(">", $key);
389
- $value = $this->getValue($json,$path);
390
-
391
- if(isset($value)) {
392
- $mustAddjson = true;
393
- $this->addValues($value, $words, $nbJsonStrings);
394
- }
395
-
396
- }
397
-
398
- if($mustAddjson) {
399
- array_push($jsons, array('node' => $row, 'json' => $json));
400
- }
401
- }
402
- }
403
-
404
- $countWC18n = $this->addWCLabels($dom,$words);
405
-
406
- $title = 'Empty title';
407
- foreach ( $html->find( 'title' ) as $k => $row ) {
408
- if($row->innertext != '')
409
- $title = $row->innertext;
410
- }
411
-
412
-
413
- $absolute_url = $this->full_url( $_SERVER );
414
- if ( strpos( $absolute_url,'admin-ajax.php' ) !== false ) {
415
- if ( isset( $_SERVER['HTTP_REFERER'] ) ) {
416
- $absolute_url = sanitize_text_field( wp_unslash( $_SERVER['HTTP_REFERER'] ) );
417
- }
418
- $title = 'Ajax data';
419
- }
420
-
421
- $bot = $this->bot_detected();
422
- $parameters = array(
423
- 'l_from' => $l_from,
424
- 'l_to' => $l_to,
425
- 'title' => $title,
426
- 'request_url' => $absolute_url,
427
- 'bot' => $bot,
428
- 'words' => $words,
429
- );
430
- $results = $this->doRequest( self::API_BASE . '/translate?api_key=' . $this->api_key,$parameters );
431
-
432
- $json = json_decode( $results,true );
433
- if ( json_last_error() == JSON_ERROR_NONE ) {
434
- $answer = $json;
435
- if ( isset( $answer['to_words'] ) ) {
436
- $translated_words = $answer['to_words'];
437
- $from_words = $answer['from_words'];
438
-
439
- if ( (count( $nodes ) + $nbJsonStrings + $countWC18n ) == count( $translated_words ) ) {
440
- for ( $i = 0;$i < count( $nodes );$i++ ) {
441
-
442
- $property = $nodes[$i]['property'];
443
- $type = $nodes[$i]['type'];
444
-
445
- if ($type == "meta_desc") {
446
- $nodes[$i]['node']->$property = htmlspecialchars($translated_words[$i]);
447
- } else {
448
- $nodes[$i]['node']->$property = $translated_words[$i];
449
- }
450
-
451
-
452
- if ($nodes[$i]['type'] == 'img_src') {
453
- $nodes[$i]['node']->src = $translated_words[$i];
454
- if ($nodes[$i]['node']->hasAttribute('srcset') && $nodes[$i]['node']->srcset != '' && htmlspecialchars_decode($translated_words[$i]) != htmlspecialchars_decode($words[$i]['w'])) {
455
- $nodes[$i]['node']->srcset = '';
456
- }
457
- }
458
- }
459
- $index = count( $nodes );
460
- for ( $j = 0;$j < count( $jsons );$j++ ) {
461
- $jsonArray = $jsons[$j]['json'];
462
- $node = $jsons[$j]['node'];
463
- foreach($microData as $key) {
464
-
465
- $path = explode(">", $key);
466
- $hasV = $this->getValue($jsonArray,$path);
467
-
468
- if(isset($hasV)) {
469
- $this->setValues($jsonArray,$path,$translated_words, $index);
470
- }
471
- }
472
- $node->innertext = json_encode($jsonArray,JSON_PRETTY_PRINT);
473
-
474
- }
475
-
476
- $dom = $html->save();
477
-
478
- for( $k = 0; $k<$countWC18n; $k++) {
479
- $dom = str_replace('\"'.$this->unformatFromApi($from_words[$k+$index+$nbJsonStrings]).'\"','\"'.$this->unformatFromApi($translated_words[$k+$index+$nbJsonStrings]).'\"',$dom);
480
- }
481
-
482
- return $dom;
483
-
484
- } else {
485
- throw new WeglotException( 'Unknown error with Weglot Api (0006)' );
486
- }
487
- } else {
488
- throw new WeglotException( 'Unknown error with Weglot Api (0005) Error is: ' . serialize( $results ) );
489
- }
490
- } else {
491
- throw new WeglotException( 'Error with Weglot Api (0001) : ' . json_last_error() . ' Error is: ' . serialize( $results ) );
492
- }
493
- }
494
-
495
- public function getUserInfo() {
496
- $results = $this->doRequest( self::API_BASE_OLD . 'user-info?api_key=' . $this->api_key,null );
497
- $json = json_decode( $results,true );
498
- if ( json_last_error() == JSON_ERROR_NONE ) {
499
- if ( isset( $json['succeeded'] ) && ($json['succeeded'] == 0 || $json['succeeded'] == 1) ) {
500
- if ( $json['succeeded'] == 1 ) {
501
- if ( isset( $json['answer'] ) ) {
502
- $answer = $json['answer'];
503
- return $answer;
504
- } else {
505
- throw new WeglotException( 'Unknown error with Weglot Api (0004)' );
506
- }
507
- } else {
508
- $error = isset( $json['error'] ) ? $json['error'] : 'Unknown error with Weglot Api (0003)';
509
- throw new WeglotException( $error );
510
- }
511
- } else {
512
- throw new WeglotException( 'Unknown error with Weglot Api (0002) : ' . $json );
513
- }
514
- } else {
515
- throw new WeglotException( 'Unknown error with Weglot Api (0001) : ' . json_last_error() );
516
- }
517
- }
518
-
519
- public function doRequest( $url, $parameters ) {
520
-
521
- if ( $parameters ) {
522
- $payload = json_encode( $parameters );
523
- if ( json_last_error() == JSON_ERROR_NONE ) {
524
- $response = wp_remote_post(
525
- $url, array(
526
- 'method' => 'POST',
527
- 'timeout' => 45,
528
- 'redirection' => 5,
529
- 'blocking' => true,
530
- 'headers' => array(
531
- 'Content-type' => 'application/json',
532
- ),
533
- 'body' => $payload,
534
- 'cookies' => array(),
535
- 'sslverify' => false,
536
- )
537
- );
538
- } else {
539
- throw new WeglotException( 'Cannot json encode parameters: ' . json_last_error() );
540
- }
541
- } else {
542
- $response = wp_remote_get(
543
- $url, array(
544
- 'method' => 'GET',
545
- 'timeout' => 45,
546
- 'redirection' => 5,
547
- 'blocking' => true,
548
- 'headers' => array(
549
- 'Content-type' => 'application/json',
550
- ),
551
- 'body' => null,
552
- 'cookies' => array(),
553
- 'sslverify' => false,
554
- )
555
- );
556
- }
557
-
558
- if ( is_wp_error( $response ) ) {
559
- $error_message = $response->get_error_message();
560
- throw new WeglotException( 'Error doing the external request to ' . $url . ': ' . $error_message );
561
- } else {
562
- return $response['body'];
563
- }
564
- }
565
-
566
-
567
-
568
- function bot_detected() {
569
- if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
570
- $ua = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) );
571
- }
572
- if ( isset( $ua ) ) {
573
- if ( preg_match( '/bot|favicon|crawl|facebook|slurp|spider/i', $ua ) ) {
574
- if ( strpos( $ua, 'Google' ) !== false || strpos( $ua, 'facebook' ) !== false || strpos( $ua, 'wprocketbot' ) !== false || strpos( $ua, 'SemrushBot' ) !== false ) {
575
- return 2;
576
- } elseif ( strpos( $ua, 'bing' ) !== false ) {
577
- return 3;
578
- } elseif ( strpos( $ua, 'yahoo' ) !== false ) {
579
- return 4;
580
- } elseif ( strpos( $ua, 'Baidu' ) !== false ) {
581
- return 5;
582
- } elseif ( strpos( $ua, 'Yandex' ) !== false ) {
583
- return 6;
584
- } else {
585
- return 1;
586
- }
587
- } else {
588
- return 0;
589
- }
590
- } else {
591
- return 1;
592
- }
593
- }
594
-
595
-
596
- function addValues( $value, &$words, &$nbJsonStrings )
597
- {
598
- if (is_array($value)) {
599
- foreach ($value as $key => $val) {
600
- $this->addValues($val, $words, $nbJsonStrings);
601
- }
602
-
603
- }
604
- else {
605
- array_push(
606
- $words, array(
607
- 't' => 1,
608
- 'w' => $value,
609
- )
610
- );
611
- $nbJsonStrings++;
612
- }
613
- }
614
-
615
- function setValues(&$data, $path, $translatedwords,&$index) {
616
-
617
- $temp = &$data;
618
- foreach ($path as $key) {
619
- if (array_key_exists($key, $temp))
620
- $temp = &$temp[$key];
621
- else
622
- return null;
623
- }
624
-
625
- if (is_array($temp)) {
626
- foreach ($temp as $key => &$val) {
627
- $this->setValues($val, null, $translatedwords, $index) ;
628
- }
629
- } else {
630
- $temp = $translatedwords[$index];
631
- $index++;
632
- }
633
-
634
- return;
635
- }
636
-
637
- function getValue($data, $path) {
638
- $temp = $data;
639
- foreach ( $path as $key ) {
640
- if(array_key_exists($key,$temp))
641
- $temp = $temp[$key];
642
- else
643
- return null;
644
- }
645
- return $temp ;
646
- }
647
-
648
- function addWCLabels($html,&$words) {
649
-
650
- preg_match('#wc_address_i18n_params(.*?);#', $html, $match);
651
- preg_match_all('#(label|placeholder)\\\":\\\"(.*?)\\\"#', $match[1],$all);
652
- $all_words = $all[2];
653
- $c = 0;
654
- foreach($all_words as $value) {
655
- $value = $this->formatForApi($value);
656
- array_push(
657
- $words, array(
658
- 't' => 1,
659
- 'w' => $value,
660
- )
661
- );
662
- $c++;
663
- }
664
- return $c;
665
- }
666
-
667
- function formatForApi($string) {
668
- $string = '"'.$string.'"';
669
- return json_decode(str_replace('\\/','/',str_replace('\\\\', '\\', $string)));
670
- }
671
-
672
- function unformatFromApi($string) {
673
- $string = str_replace('"','',str_replace('/','\\\\/',str_replace('\\u', '\\\\u',json_encode($string))));
674
- return $string;
675
- }
676
-
677
- function url_origin( $s, $use_forwarded_host = false ) {
678
- $ssl = ( ! empty( $s['HTTPS'] ) && $s['HTTPS'] == 'on') ? true : false;
679
- $sp = strtolower( $s['SERVER_PROTOCOL'] );
680
- $protocol = substr( $sp, 0, strpos( $sp, '/' ) ) . (($ssl) ? 's' : '');
681
- $port = $s['SERVER_PORT'];
682
- $port = (( ! $ssl && $port == '80') || ($ssl && $port == '443')) ? '' : ':' . $port;
683
- $host = ($use_forwarded_host && isset( $s['HTTP_X_FORWARDED_HOST'] )) ? $s['HTTP_X_FORWARDED_HOST'] : (isset( $s['HTTP_HOST'] ) ? $s['HTTP_HOST'] : null);
684
- $host = isset( $host ) ? $host : $s['SERVER_NAME'] . $port;
685
- return $protocol . '://' . $host;
686
- }
687
- function full_url( $s, $use_forwarded_host = false ) {
688
- return $this->url_origin( $s, $use_forwarded_host ) . $s['REQUEST_URI'];
689
- }
690
- function full_trim( $word ) {
691
- return trim( $word," \t\n\r\0\x0B\xA0�" );
692
- }
693
- }
694
-
695
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
WeglotPHPClient/src/WeglotException.php DELETED
@@ -1,6 +0,0 @@
1
- <?php
2
- namespace Weglot;
3
-
4
- class WeglotException extends \Exception {
5
-
6
- }
 
 
 
 
 
 
WeglotPHPClient/weglot.php DELETED
@@ -1,4 +0,0 @@
1
- <?php
2
-
3
- require_once 'src/Client.php';
4
- require_once 'src/WeglotException.php';
 
 
 
 
includes/wg-settings-page.php CHANGED
@@ -1,24 +1,32 @@
1
  <?php
 
 
 
 
2
  $showRTL = false;
3
  $showLTR = false;
4
- if (WGUtils::isLanguageRTL($this->original_l)) { // Right lo left language
5
- if (WGUtils::hasLanguageLTR(explode(',', $this->destination_l))) {
 
6
  $showLTR = true;
7
  }
8
  } else { // Left to right language
9
- if (WGUtils::hasLanguageRTL(explode(',', $this->destination_l))) {
10
  $showRTL = true;
11
  }
12
  } ?>
13
  <div class="wrap">
14
- <?php if ($this->allowed == 0) { ?>
 
15
  <div class="wg-status-box">
16
  <h3><?php echo sprintf(esc_html__('Weglot Translate service is not active because you have reached the end of the trial period.', 'weglot'), esc_html__($this->userInfo['limit'])); ?></h3>
17
  <p><?php echo sprintf(esc_html__('To reactivate the service, please %1$supgrade your plan%2$s.', 'weglot'), '<a target="_blank" href="https://weglot.com/change-plan">', '</a>'); ?></p>
18
  </div>
19
- <?php } ?>
 
20
 
21
- <?php if (esc_attr(get_option('show_box')) == 'on') { ?>
 
22
  <div class="wgbox-blur">
23
  <div class="wgbox">
24
  <div class="wgclose-btn"><?php esc_html_e('Close', 'weglot'); ?></div>
@@ -26,12 +34,10 @@ if (WGUtils::isLanguageRTL($this->original_l)) { // Right lo left language
26
  <p class="wgbox-text"><?php esc_html_e('Go on your website, there is a language switcher. Try it :)', 'weglot'); ?></p>
27
  <a class="wgbox-button button button-primary" href="
28
  <?php
29
- echo esc_html__($this->home_dir);
30
- ?>
31
  /" target="_blank">
32
  <?php
33
- esc_html_e('Go on my front page.', 'weglot');
34
- ?>
35
  </a>
36
  <p class="wgbox-subtext"><?php esc_html_e('Next step, edit your translations directly in your Weglot account.', 'weglot'); ?></p>
37
  </div>
@@ -40,14 +46,12 @@ if (WGUtils::isLanguageRTL($this->original_l)) { // Right lo left language
40
  list($wgfirstlang) = explode(',', get_option('destination_l'));
41
  if (strlen($wgfirstlang) == 2) {
42
  ?>
43
- <iframe style="visibility:hidden;" src="
44
- <?php
45
- echo esc_html__($this->home_dir);
46
- ?>
47
- /<?php echo esc_html__($wgfirstlang); ?>/" width=1
48
  height=1
49
  ></iframe>
50
- <?php } ?>
 
51
  <?php update_option('show_box', 'off');
52
  } ?>
53
  <form class="wg-widget-option-form" method="post" action="options.php">
@@ -68,326 +72,12 @@ if (WGUtils::isLanguageRTL($this->original_l)) { // Right lo left language
68
  style="font-weight:normal;margin-top:2px;"><?php esc_html_e('What is the original (current) language of your website?', 'weglot'); ?></p>
69
  </th>
70
  <td>
71
- <select class="wg-input-select" name="original_l"
72
- style="width :200px;">
73
- <option <?php if (esc_attr(get_option('original_l')) == 'af') {
74
- echo 'selected';
75
- } ?> value="af"><?php esc_html_e('Afrikaans', 'weglot'); ?></option>
76
- <option <?php if (esc_attr(get_option('original_l')) == 'sq') {
77
- echo 'selected';
78
- } ?> value="sq"><?php esc_html_e('Albanian', 'weglot'); ?></option>
79
- <option <?php if (esc_attr(get_option('original_l')) == 'am') {
80
- echo 'selected';
81
- } ?> value="am"><?php esc_html_e('Amharic', 'weglot'); ?></option>
82
- <option <?php if (esc_attr(get_option('original_l')) == 'ar') {
83
- echo 'selected';
84
- } ?> value="ar"><?php esc_html_e('Arabic', 'weglot'); ?></option>
85
- <option <?php if (esc_attr(get_option('original_l')) == 'hy') {
86
- echo 'selected';
87
- } ?> value="hy"><?php esc_html_e('Armenian', 'weglot'); ?></option>
88
- <option <?php if (esc_attr(get_option('original_l')) == 'az') {
89
- echo 'selected';
90
- } ?> value="az"><?php esc_html_e('Azerbaijani', 'weglot'); ?></option>
91
- <option <?php if (esc_attr(get_option('original_l')) == 'ba') {
92
- echo 'selected';
93
- } ?> value="ba"><?php esc_html_e('Bashkir', 'weglot'); ?></option>
94
- <option <?php if (esc_attr(get_option('original_l')) == 'eu') {
95
- echo 'selected';
96
- } ?> value="eu"><?php esc_html_e('Basque', 'weglot'); ?></option>
97
- <option <?php if (esc_attr(get_option('original_l')) == 'be') {
98
- echo 'selected';
99
- } ?> value="be"><?php esc_html_e('Belarusian', 'weglot'); ?></option>
100
- <option <?php if (esc_attr(get_option('original_l')) == 'bn') {
101
- echo 'selected';
102
- } ?> value="bn"><?php esc_html_e('Bengali', 'weglot'); ?></option>
103
- <option <?php if (esc_attr(get_option('original_l')) == 'bs') {
104
- echo 'selected';
105
- } ?> value="bs"><?php esc_html_e('Bosnian', 'weglot'); ?></option>
106
- <option <?php if (esc_attr(get_option('original_l')) == 'bg') {
107
- echo 'selected';
108
- } ?> value="bg"><?php esc_html_e('Bulgarian', 'weglot'); ?></option>
109
- <option <?php if (esc_attr(get_option('original_l')) == 'my') {
110
- echo 'selected';
111
- } ?> value="my"><?php esc_html_e('Burmese', 'weglot'); ?></option>
112
- <option <?php if (esc_attr(get_option('original_l')) == 'ca') {
113
- echo 'selected';
114
- } ?> value="ca"><?php esc_html_e('Catalan', 'weglot'); ?></option>
115
- <option <?php if (esc_attr(get_option('original_l')) == 'ny') {
116
- echo 'selected';
117
- } ?> value="ny"><?php esc_html_e('Chichewa', 'weglot'); ?></option>
118
- <option <?php if (esc_attr(get_option('original_l')) == 'zh') {
119
- echo 'selected';
120
- } ?> value="zh"><?php esc_html_e('Simplified Chinese', 'weglot'); ?></option>
121
- <option <?php if (esc_attr(get_option('original_l')) == 'tw') {
122
- echo 'selected';
123
- } ?> value="tw"><?php esc_html_e('Traditional Chinese', 'weglot'); ?></option>
124
- <option <?php if (esc_attr(get_option('original_l')) == 'co') {
125
- echo 'selected';
126
- } ?> value="co"><?php esc_html_e('Corsican', 'weglot'); ?></option>
127
- <option <?php if (esc_attr(get_option('original_l')) == 'hr') {
128
- echo 'selected';
129
- } ?> value="hr"><?php esc_html_e('Croatian', 'weglot'); ?></option>
130
- <option <?php if (esc_attr(get_option('original_l')) == 'cs') {
131
- echo 'selected';
132
- } ?> value="cs"><?php esc_html_e('Czech', 'weglot'); ?></option>
133
- <option <?php if (esc_attr(get_option('original_l')) == 'da') {
134
- echo 'selected';
135
- } ?> value="da"><?php esc_html_e('Danish', 'weglot'); ?></option>
136
- <option <?php if (esc_attr(get_option('original_l')) == 'nl') {
137
- echo 'selected';
138
- } ?> value="nl"><?php esc_html_e('Dutch', 'weglot'); ?></option>
139
- <option <?php if (esc_attr(get_option('original_l')) == 'en' || !get_option('original_l')) {
140
- echo 'selected';
141
- } ?> value="en"><?php esc_html_e('English', 'weglot'); ?></option>
142
- <option <?php if (esc_attr(get_option('original_l')) == 'eo') {
143
- echo 'selected';
144
- } ?> value="eo"><?php esc_html_e('Esperanto', 'weglot'); ?></option>
145
- <option <?php if (esc_attr(get_option('original_l')) == 'et') {
146
- echo 'selected';
147
- } ?> value="et"><?php esc_html_e('Estonian', 'weglot'); ?></option>
148
- <option <?php if (esc_attr(get_option('original_l')) == 'fj') {
149
- echo 'selected';
150
- } ?> value="fj"><?php esc_html_e('Fijian', 'weglot'); ?></option>
151
- <option <?php if (esc_attr(get_option('original_l')) == 'fi') {
152
- echo 'selected';
153
- } ?> value="fi"><?php esc_html_e('Finnish', 'weglot'); ?></option>
154
- <option <?php if (esc_attr(get_option('original_l')) == 'fr') {
155
- echo 'selected';
156
- } ?> value="fr"><?php esc_html_e('French', 'weglot'); ?></option>
157
- <option <?php if (esc_attr(get_option('original_l')) == 'gl') {
158
- echo 'selected';
159
- } ?> value="gl"><?php esc_html_e('Galician', 'weglot'); ?></option>
160
- <option <?php if (esc_attr(get_option('original_l')) == 'ka') {
161
- echo 'selected';
162
- } ?> value="ka"><?php esc_html_e('Georgian', 'weglot'); ?></option>
163
- <option <?php if (esc_attr(get_option('original_l')) == 'de') {
164
- echo 'selected';
165
- } ?> value="de"><?php esc_html_e('German', 'weglot'); ?></option>
166
- <option <?php if (esc_attr(get_option('original_l')) == 'el') {
167
- echo 'selected';
168
- } ?> value="el"><?php esc_html_e('Greek', 'weglot'); ?></option>
169
- <option <?php if (esc_attr(get_option('original_l')) == 'gu') {
170
- echo 'selected';
171
- } ?> value="gu"><?php esc_html_e('Gujarati', 'weglot'); ?></option>
172
- <option <?php if (esc_attr(get_option('original_l')) == 'ht') {
173
- echo 'selected';
174
- } ?> value="ht"><?php esc_html_e('Haitian', 'weglot'); ?></option>
175
- <option <?php if (esc_attr(get_option('original_l')) == 'ha') {
176
- echo 'selected';
177
- } ?> value="ha"><?php esc_html_e('Hausa', 'weglot'); ?></option>
178
- <option <?php if (esc_attr(get_option('original_l')) == 'he') {
179
- echo 'selected';
180
- } ?> value="he"><?php esc_html_e('Hebrew', 'weglot'); ?></option>
181
- <option <?php if (esc_attr(get_option('original_l')) == 'hi') {
182
- echo 'selected';
183
- } ?> value="hi"><?php esc_html_e('Hindi', 'weglot'); ?></option>
184
- <option <?php if (esc_attr(get_option('original_l')) == 'hu') {
185
- echo 'selected';
186
- } ?> value="hu"><?php esc_html_e('Hungarian', 'weglot'); ?></option>
187
- <option <?php if (esc_attr(get_option('original_l')) == 'is') {
188
- echo 'selected';
189
- } ?> value="is"><?php esc_html_e('Icelandic', 'weglot'); ?></option>
190
- <option <?php if (esc_attr(get_option('original_l')) == 'ig') {
191
- echo 'selected';
192
- } ?> value="ig"><?php esc_html_e('Igbo', 'weglot'); ?></option>
193
- <option <?php if (esc_attr(get_option('original_l')) == 'id') {
194
- echo 'selected';
195
- } ?> value="id"><?php esc_html_e('Indonesian', 'weglot'); ?></option>
196
- <option <?php if (esc_attr(get_option('original_l')) == 'ga') {
197
- echo 'selected';
198
- } ?> value="ga"><?php esc_html_e('Irish', 'weglot'); ?></option>
199
- <option <?php if (esc_attr(get_option('original_l')) == 'it') {
200
- echo 'selected';
201
- } ?> value="it"><?php esc_html_e('Italian', 'weglot'); ?></option>
202
- <option <?php if (esc_attr(get_option('original_l')) == 'ja') {
203
- echo 'selected';
204
- } ?> value="ja"><?php esc_html_e('Japanese', 'weglot'); ?></option>
205
- <option <?php if (esc_attr(get_option('original_l')) == 'jv') {
206
- echo 'selected';
207
- } ?> value="jv"><?php esc_html_e('Javanese', 'weglot'); ?></option>
208
- <option <?php if (esc_attr(get_option('original_l')) == 'kn') {
209
- echo 'selected';
210
- } ?> value="kn"><?php esc_html_e('Kannada', 'weglot'); ?></option>
211
- <option <?php if (esc_attr(get_option('original_l')) == 'kk') {
212
- echo 'selected';
213
- } ?> value="kk"><?php esc_html_e('Kazakh', 'weglot'); ?></option>
214
- <option <?php if (esc_attr(get_option('original_l')) == 'km') {
215
- echo 'selected';
216
- } ?> value="km"><?php esc_html_e('Khmer', 'weglot'); ?></option>
217
- <option <?php if (esc_attr(get_option('original_l')) == 'ko') {
218
- echo 'selected';
219
- } ?> value="ko"><?php esc_html_e('Korean', 'weglot'); ?></option>
220
- <option <?php if (esc_attr(get_option('original_l')) == 'ku') {
221
- echo 'selected';
222
- } ?> value="ku"><?php esc_html_e('Kurdish', 'weglot'); ?></option>
223
- <option <?php if (esc_attr(get_option('original_l')) == 'ky') {
224
- echo 'selected';
225
- } ?> value="ky"><?php esc_html_e('Kyrgyz', 'weglot'); ?></option>
226
- <option <?php if (esc_attr(get_option('original_l')) == 'lo') {
227
- echo 'selected';
228
- } ?> value="lo"><?php esc_html_e('Lao', 'weglot'); ?></option>
229
- <option <?php if (esc_attr(get_option('original_l')) == 'la') {
230
- echo 'selected';
231
- } ?> value="la"><?php esc_html_e('Latin', 'weglot'); ?></option>
232
- <option <?php if (esc_attr(get_option('original_l')) == 'lv') {
233
- echo 'selected';
234
- } ?> value="lv"><?php esc_html_e('Latvian', 'weglot'); ?></option>
235
- <option <?php if (esc_attr(get_option('original_l')) == 'lt') {
236
- echo 'selected';
237
- } ?> value="lt"><?php esc_html_e('Lithuanian', 'weglot'); ?></option>
238
- <option <?php if (esc_attr(get_option('original_l')) == 'lb') {
239
- echo 'selected';
240
- } ?> value="lb"><?php esc_html_e('Luxembourgish', 'weglot'); ?></option>
241
- <option <?php if (esc_attr(get_option('original_l')) == 'mk') {
242
- echo 'selected';
243
- } ?> value="mk"><?php esc_html_e('Macedonian', 'weglot'); ?></option>
244
- <option <?php if (esc_attr(get_option('original_l')) == 'mg') {
245
- echo 'selected';
246
- } ?> value="mg"><?php esc_html_e('Malagasy', 'weglot'); ?></option>
247
- <option <?php if (esc_attr(get_option('original_l')) == 'ms') {
248
- echo 'selected';
249
- } ?> value="ms"><?php esc_html_e('Malay', 'weglot'); ?></option>
250
- <option <?php if (esc_attr(get_option('original_l')) == 'ml') {
251
- echo 'selected';
252
- } ?> value="ml"><?php esc_html_e('Malayalam', 'weglot'); ?></option>
253
- <option <?php if (esc_attr(get_option('original_l')) == 'mt') {
254
- echo 'selected';
255
- } ?> value="mt"><?php esc_html_e('Maltese', 'weglot'); ?></option>
256
- <option <?php if (esc_attr(get_option('original_l')) == 'mi') {
257
- echo 'selected';
258
- } ?> value="mi"><?php esc_html_e('Māori', 'weglot'); ?></option>
259
- <option <?php if (esc_attr(get_option('original_l')) == 'mr') {
260
- echo 'selected';
261
- } ?> value="mr"><?php esc_html_e('Marathi', 'weglot'); ?></option>
262
- <option <?php if (esc_attr(get_option('original_l')) == 'mn') {
263
- echo 'selected';
264
- } ?> value="mn"><?php esc_html_e('Mongolian', 'weglot'); ?></option>
265
- <option <?php if (esc_attr(get_option('original_l')) == 'ne') {
266
- echo 'selected';
267
- } ?> value="ne"><?php esc_html_e('Nepali', 'weglot'); ?></option>
268
- <option <?php if (esc_attr(get_option('original_l')) == 'no') {
269
- echo 'selected';
270
- } ?> value="no"><?php esc_html_e('Norwegian', 'weglot'); ?></option>
271
- <option <?php if (esc_attr(get_option('original_l')) == 'ps') {
272
- echo 'selected';
273
- } ?> value="ps"><?php esc_html_e('Pashto', 'weglot'); ?></option>
274
- <option <?php if (esc_attr(get_option('original_l')) == 'fa') {
275
- echo 'selected';
276
- } ?> value="fa"><?php esc_html_e('Persian', 'weglot'); ?></option>
277
- <option <?php if (esc_attr(get_option('original_l')) == 'pl') {
278
- echo 'selected';
279
- } ?> value="pl"><?php esc_html_e('Polish', 'weglot'); ?></option>
280
- <option <?php if (esc_attr(get_option('original_l')) == 'pt') {
281
- echo 'selected';
282
- } ?> value="pt"><?php esc_html_e('Portuguese', 'weglot'); ?></option>
283
- <option <?php if (esc_attr(get_option('original_l')) == 'pa') {
284
- echo 'selected';
285
- } ?> value="pa"><?php esc_html_e('Punjabi', 'weglot'); ?></option>
286
- <option <?php if (esc_attr(get_option('original_l')) == 'ro') {
287
- echo 'selected';
288
- } ?> value="ro"><?php esc_html_e('Romanian', 'weglot'); ?></option>
289
- <option <?php if (esc_attr(get_option('original_l')) == 'ru') {
290
- echo 'selected';
291
- } ?> value="ru"><?php esc_html_e('Russian', 'weglot'); ?></option>
292
- <option <?php if (esc_attr(get_option('original_l')) == 'sm') {
293
- echo 'selected';
294
- } ?> value="sm"><?php esc_html_e('Samoan', 'weglot'); ?></option>
295
- <option <?php if (esc_attr(get_option('original_l')) == 'gd') {
296
- echo 'selected';
297
- } ?> value="gd"><?php esc_html_e('Scottish Gaelic', 'weglot'); ?></option>
298
- <option <?php if (esc_attr(get_option('original_l')) == 'sr') {
299
- echo 'selected';
300
- } ?> value="sr"><?php esc_html_e('Serbian', 'weglot'); ?></option>
301
- <option <?php if (esc_attr(get_option('original_l')) == 'sn') {
302
- echo 'selected';
303
- } ?> value="sn"><?php esc_html_e('Shona', 'weglot'); ?></option>
304
- <option <?php if (esc_attr(get_option('original_l')) == 'sd') {
305
- echo 'selected';
306
- } ?> value="sd"><?php esc_html_e('Sindhi', 'weglot'); ?></option>
307
- <option <?php if (esc_attr(get_option('original_l')) == 'si') {
308
- echo 'selected';
309
- } ?> value="si"><?php esc_html_e('Sinhalese', 'weglot'); ?></option>
310
- <option <?php if (esc_attr(get_option('original_l')) == 'sk') {
311
- echo 'selected';
312
- } ?> value="sk"><?php esc_html_e('Slovak', 'weglot'); ?></option>
313
- <option <?php if (esc_attr(get_option('original_l')) == 'sl') {
314
- echo 'selected';
315
- } ?> value="sl"><?php esc_html_e('Slovenian', 'weglot'); ?></option>
316
- <option <?php if (esc_attr(get_option('original_l')) == 'so') {
317
- echo 'selected';
318
- } ?> value="so"><?php esc_html_e('Somali', 'weglot'); ?></option>
319
- <option <?php if (esc_attr(get_option('original_l')) == 'st') {
320
- echo 'selected';
321
- } ?> value="st"><?php esc_html_e('Southern Sotho', 'weglot'); ?></option>
322
- <option <?php if (esc_attr(get_option('original_l')) == 'es') {
323
- echo 'selected';
324
- } ?> value="es"><?php esc_html_e('Spanish', 'weglot'); ?></option>
325
- <option <?php if (esc_attr(get_option('original_l')) == 'su') {
326
- echo 'selected';
327
- } ?> value="su"><?php esc_html_e('Sundanese', 'weglot'); ?></option>
328
- <option <?php if (esc_attr(get_option('original_l')) == 'sw') {
329
- echo 'selected';
330
- } ?> value="sw"><?php esc_html_e('Swahili', 'weglot'); ?></option>
331
- <option <?php if (esc_attr(get_option('original_l')) == 'sv') {
332
- echo 'selected';
333
- } ?> value="sv"><?php esc_html_e('Swedish', 'weglot'); ?></option>
334
- <option <?php if (esc_attr(get_option('original_l')) == 'tl') {
335
- echo 'selected';
336
- } ?> value="tl"><?php esc_html_e('Tagalog', 'weglot'); ?></option>
337
- <option <?php if (esc_attr(get_option('original_l')) == 'ty') {
338
- echo 'selected';
339
- } ?> value="ty"><?php esc_html_e('Tahitian', 'weglot'); ?></option>
340
- <option <?php if (esc_attr(get_option('original_l')) == 'tg') {
341
- echo 'selected';
342
- } ?> value="tg"><?php esc_html_e('Tajik', 'weglot'); ?></option>
343
- <option <?php if (esc_attr(get_option('original_l')) == 'ta') {
344
- echo 'selected';
345
- } ?> value="ta"><?php esc_html_e('Tamil', 'weglot'); ?></option>
346
- <option <?php if (esc_attr(get_option('original_l')) == 'tt') {
347
- echo 'selected';
348
- } ?> value="tt"><?php esc_html_e('Tatar', 'weglot'); ?></option>
349
- <option <?php if (esc_attr(get_option('original_l')) == 'te') {
350
- echo 'selected';
351
- } ?> value="te"><?php esc_html_e('Telugu', 'weglot'); ?></option>
352
- <option <?php if (esc_attr(get_option('original_l')) == 'th') {
353
- echo 'selected';
354
- } ?> value="th"><?php esc_html_e('Thai', 'weglot'); ?></option>
355
- <option <?php if (esc_attr(get_option('original_l')) == 'to') {
356
- echo 'selected';
357
- } ?> value="to"><?php esc_html_e('Tongan', 'weglot'); ?></option>
358
- <option <?php if (esc_attr(get_option('original_l')) == 'tr') {
359
- echo 'selected';
360
- } ?> value="tr"><?php esc_html_e('Turkish', 'weglot'); ?></option>
361
- <option <?php if (esc_attr(get_option('original_l')) == 'uk') {
362
- echo 'selected';
363
- } ?> value="uk"><?php esc_html_e('Ukrainian', 'weglot'); ?></option>
364
- <option <?php if (esc_attr(get_option('original_l')) == 'ur') {
365
- echo 'selected';
366
- } ?> value="ur"><?php esc_html_e('Urdu', 'weglot'); ?></option>
367
- <option <?php if (esc_attr(get_option('original_l')) == 'uz') {
368
- echo 'selected';
369
- } ?> value="uz"><?php esc_html_e('Uzbek', 'weglot'); ?></option>
370
- <option <?php if (esc_attr(get_option('original_l')) == 'vi') {
371
- echo 'selected';
372
- } ?> value="vi"><?php esc_html_e('Vietnamese', 'weglot'); ?></option>
373
- <option <?php if (esc_attr(get_option('original_l')) == 'cy') {
374
- echo 'selected';
375
- } ?> value="cy"><?php esc_html_e('Welsh', 'weglot'); ?></option>
376
- <option <?php if (esc_attr(get_option('original_l')) == 'fy') {
377
- echo 'selected';
378
- } ?> value="fy"><?php esc_html_e('Western Frisian', 'weglot'); ?></option>
379
- <option <?php if (esc_attr(get_option('original_l')) == 'xh') {
380
- echo 'selected';
381
- } ?> value="xh"><?php esc_html_e('Xhosa', 'weglot'); ?></option>
382
- <option <?php if (esc_attr(get_option('original_l')) == 'yi') {
383
- echo 'selected';
384
- } ?> value="yi"><?php esc_html_e('Yiddish', 'weglot'); ?></option>
385
- <option <?php if (esc_attr(get_option('original_l')) == 'yo') {
386
- echo 'selected';
387
- } ?> value="yo"><?php esc_html_e('Yoruba', 'weglot'); ?></option>
388
- <option <?php if (esc_attr(get_option('original_l')) == 'zu') {
389
- echo 'selected';
390
- } ?> value="zu"><?php esc_html_e('Zulu', 'weglot'); ?></option>
391
  </select>
392
  </td>
393
  </tr>
@@ -401,324 +91,11 @@ if (WGUtils::isLanguageRTL($this->original_l)) { // Right lo left language
401
  style=""
402
  placeholder="French, German, Italian, Portuguese, …"
403
  name="destination_l">
404
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'af') !== false) {
405
- echo 'selected';
406
- } ?> value="af"><?php esc_html_e('Afrikaans', 'weglot'); ?></option>
407
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'sq') !== false) {
408
- echo 'selected';
409
- } ?> value="sq"><?php esc_html_e('Albanian', 'weglot'); ?></option>
410
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'am') !== false) {
411
- echo 'selected';
412
- } ?> value="am"><?php esc_html_e('Amharic', 'weglot'); ?></option>
413
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ar') !== false) {
414
- echo 'selected';
415
- } ?> value="ar"><?php esc_html_e('Arabic', 'weglot'); ?></option>
416
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'hy') !== false) {
417
- echo 'selected';
418
- } ?> value="hy"><?php esc_html_e('Armenian', 'weglot'); ?></option>
419
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'az') !== false) {
420
- echo 'selected';
421
- } ?> value="az"><?php esc_html_e('Azerbaijani', 'weglot'); ?></option>
422
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ba') !== false) {
423
- echo 'selected';
424
- } ?> value="ba"><?php esc_html_e('Bashkir', 'weglot'); ?></option>
425
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'eu') !== false) {
426
- echo 'selected';
427
- } ?> value="eu"><?php esc_html_e('Basque', 'weglot'); ?></option>
428
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'be') !== false) {
429
- echo 'selected';
430
- } ?> value="be"><?php esc_html_e('Belarusian', 'weglot'); ?></option>
431
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'bn') !== false) {
432
- echo 'selected';
433
- } ?> value="bn"><?php esc_html_e('Bengali', 'weglot'); ?></option>
434
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'bs') !== false) {
435
- echo 'selected';
436
- } ?> value="bs"><?php esc_html_e('Bosnian', 'weglot'); ?></option>
437
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'bg') !== false) {
438
- echo 'selected';
439
- } ?> value="bg"><?php esc_html_e('Bulgarian', 'weglot'); ?></option>
440
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'my') !== false) {
441
- echo 'selected';
442
- } ?> value="my"><?php esc_html_e('Burmese', 'weglot'); ?></option>
443
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ca') !== false) {
444
- echo 'selected';
445
- } ?> value="ca"><?php esc_html_e('Catalan', 'weglot'); ?></option>
446
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ny') !== false) {
447
- echo 'selected';
448
- } ?> value="ny"><?php esc_html_e('Chichewa', 'weglot'); ?></option>
449
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'zh') !== false) {
450
- echo 'selected';
451
- } ?> value="zh"><?php esc_html_e('Simplified Chinese', 'weglot'); ?></option>
452
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'tw') !== false) {
453
- echo 'selected';
454
- } ?> value="tw"><?php esc_html_e('Traditional Chinese', 'weglot'); ?></option>
455
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'co') !== false) {
456
- echo 'selected';
457
- } ?> value="co"><?php esc_html_e('Corsican', 'weglot'); ?></option>
458
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'hr') !== false) {
459
- echo 'selected';
460
- } ?> value="hr"><?php esc_html_e('Croatian', 'weglot'); ?></option>
461
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'cs') !== false) {
462
- echo 'selected';
463
- } ?> value="cs"><?php esc_html_e('Czech', 'weglot'); ?></option>
464
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'da') !== false) {
465
- echo 'selected';
466
- } ?> value="da"><?php esc_html_e('Danish', 'weglot'); ?></option>
467
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'nl') !== false) {
468
- echo 'selected';
469
- } ?> value="nl"><?php esc_html_e('Dutch', 'weglot'); ?></option>
470
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'en') !== false) {
471
- echo 'selected';
472
- } ?> value="en"><?php esc_html_e('English', 'weglot'); ?></option>
473
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'eo') !== false) {
474
- echo 'selected';
475
- } ?> value="eo"><?php esc_html_e('Esperanto', 'weglot'); ?></option>
476
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'et') !== false) {
477
- echo 'selected';
478
- } ?> value="et"><?php esc_html_e('Estonian', 'weglot'); ?></option>
479
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'fj') !== false) {
480
- echo 'selected';
481
- } ?> value="fj"><?php esc_html_e('Fijian', 'weglot'); ?></option>
482
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'fi') !== false) {
483
- echo 'selected';
484
- } ?> value="fi"><?php esc_html_e('Finnish', 'weglot'); ?></option>
485
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'fr') !== false) {
486
- echo 'selected';
487
- } ?> value="fr"><?php esc_html_e('French', 'weglot'); ?></option>
488
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'gl') !== false) {
489
- echo 'selected';
490
- } ?> value="gl"><?php esc_html_e('Galician', 'weglot'); ?></option>
491
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ka') !== false) {
492
- echo 'selected';
493
- } ?> value="ka"><?php esc_html_e('Georgian', 'weglot'); ?></option>
494
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'de') !== false) {
495
- echo 'selected';
496
- } ?> value="de"><?php esc_html_e('German', 'weglot'); ?></option>
497
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'el') !== false) {
498
- echo 'selected';
499
- } ?> value="el"><?php esc_html_e('Greek', 'weglot'); ?></option>
500
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'gu') !== false) {
501
- echo 'selected';
502
- } ?> value="gu"><?php esc_html_e('Gujarati', 'weglot'); ?></option>
503
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ht') !== false) {
504
- echo 'selected';
505
- } ?> value="ht"><?php esc_html_e('Haitian', 'weglot'); ?></option>
506
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ha') !== false) {
507
- echo 'selected';
508
- } ?> value="ha"><?php esc_html_e('Hausa', 'weglot'); ?></option>
509
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'he') !== false) {
510
- echo 'selected';
511
- } ?> value="he"><?php esc_html_e('Hebrew', 'weglot'); ?></option>
512
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'hi') !== false) {
513
- echo 'selected';
514
- } ?> value="hi"><?php esc_html_e('Hindi', 'weglot'); ?></option>
515
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'hu') !== false) {
516
- echo 'selected';
517
- } ?> value="hu"><?php esc_html_e('Hungarian', 'weglot'); ?></option>
518
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'is') !== false) {
519
- echo 'selected';
520
- } ?> value="is"><?php esc_html_e('Icelandic', 'weglot'); ?></option>
521
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ig') !== false) {
522
- echo 'selected';
523
- } ?> value="ig"><?php esc_html_e('Igbo', 'weglot'); ?></option>
524
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'id') !== false) {
525
- echo 'selected';
526
- } ?> value="id"><?php esc_html_e('Indonesian', 'weglot'); ?></option>
527
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ga') !== false) {
528
- echo 'selected';
529
- } ?> value="ga"><?php esc_html_e('Irish', 'weglot'); ?></option>
530
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'it') !== false) {
531
- echo 'selected';
532
- } ?> value="it"><?php esc_html_e('Italian', 'weglot'); ?></option>
533
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ja') !== false) {
534
- echo 'selected';
535
- } ?> value="ja"><?php esc_html_e('Japanese', 'weglot'); ?></option>
536
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'jv') !== false) {
537
- echo 'selected';
538
- } ?> value="jv"><?php esc_html_e('Javanese', 'weglot'); ?></option>
539
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'kn') !== false) {
540
- echo 'selected';
541
- } ?> value="kn"><?php esc_html_e('Kannada', 'weglot'); ?></option>
542
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'kk') !== false) {
543
- echo 'selected';
544
- } ?> value="kk"><?php esc_html_e('Kazakh', 'weglot'); ?></option>
545
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'km') !== false) {
546
- echo 'selected';
547
- } ?> value="km"><?php esc_html_e('Khmer', 'weglot'); ?></option>
548
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ko') !== false) {
549
- echo 'selected';
550
- } ?> value="ko"><?php esc_html_e('Korean', 'weglot'); ?></option>
551
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ku') !== false) {
552
- echo 'selected';
553
- } ?> value="ku"><?php esc_html_e('Kurdish', 'weglot'); ?></option>
554
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ky') !== false) {
555
- echo 'selected';
556
- } ?> value="ky"><?php esc_html_e('Kyrgyz', 'weglot'); ?></option>
557
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'lo') !== false) {
558
- echo 'selected';
559
- } ?> value="lo"><?php esc_html_e('Lao', 'weglot'); ?></option>
560
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'la') !== false) {
561
- echo 'selected';
562
- } ?> value="la"><?php esc_html_e('Latin', 'weglot'); ?></option>
563
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'lv') !== false) {
564
- echo 'selected';
565
- } ?> value="lv"><?php esc_html_e('Latvian', 'weglot'); ?></option>
566
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'lt') !== false) {
567
- echo 'selected';
568
- } ?> value="lt"><?php esc_html_e('Lithuanian', 'weglot'); ?></option>
569
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'lb') !== false) {
570
- echo 'selected';
571
- } ?> value="lb"><?php esc_html_e('Luxembourgish', 'weglot'); ?></option>
572
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'mk') !== false) {
573
- echo 'selected';
574
- } ?> value="mk"><?php esc_html_e('Macedonian', 'weglot'); ?></option>
575
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'mg') !== false) {
576
- echo 'selected';
577
- } ?> value="mg"><?php esc_html_e('Malagasy', 'weglot'); ?></option>
578
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ms') !== false) {
579
- echo 'selected';
580
- } ?> value="ms"><?php esc_html_e('Malay', 'weglot'); ?></option>
581
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ml') !== false) {
582
- echo 'selected';
583
- } ?> value="ml"><?php esc_html_e('Malayalam', 'weglot'); ?></option>
584
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'mt') !== false) {
585
- echo 'selected';
586
- } ?> value="mt"><?php esc_html_e('Maltese', 'weglot'); ?></option>
587
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'mi') !== false) {
588
- echo 'selected';
589
- } ?> value="mi"><?php esc_html_e('Māori', 'weglot'); ?></option>
590
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'mr') !== false) {
591
- echo 'selected';
592
- } ?> value="mr"><?php esc_html_e('Marathi', 'weglot'); ?></option>
593
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'mn') !== false) {
594
- echo 'selected';
595
- } ?> value="mn"><?php esc_html_e('Mongolian', 'weglot'); ?></option>
596
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ne') !== false) {
597
- echo 'selected';
598
- } ?> value="ne"><?php esc_html_e('Nepali', 'weglot'); ?></option>
599
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'no') !== false) {
600
- echo 'selected';
601
- } ?> value="no"><?php esc_html_e('Norwegian', 'weglot'); ?></option>
602
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ps') !== false) {
603
- echo 'selected';
604
- } ?> value="ps"><?php esc_html_e('Pashto', 'weglot'); ?></option>
605
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'fa') !== false) {
606
- echo 'selected';
607
- } ?> value="fa"><?php esc_html_e('Persian', 'weglot'); ?></option>
608
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'pl') !== false) {
609
- echo 'selected';
610
- } ?> value="pl"><?php esc_html_e('Polish', 'weglot'); ?></option>
611
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'pt') !== false) {
612
- echo 'selected';
613
- } ?> value="pt"><?php esc_html_e('Portuguese', 'weglot'); ?></option>
614
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'pa') !== false) {
615
- echo 'selected';
616
- } ?> value="pa"><?php esc_html_e('Punjabi', 'weglot'); ?></option>
617
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ro') !== false) {
618
- echo 'selected';
619
- } ?> value="ro"><?php esc_html_e('Romanian', 'weglot'); ?></option>
620
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ru') !== false) {
621
- echo 'selected';
622
- } ?> value="ru"><?php esc_html_e('Russian', 'weglot'); ?></option>
623
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'sm') !== false) {
624
- echo 'selected';
625
- } ?> value="sm"><?php esc_html_e('Samoan', 'weglot'); ?></option>
626
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'gd') !== false) {
627
- echo 'selected';
628
- } ?> value="gd"><?php esc_html_e('Scottish Gaelic', 'weglot'); ?></option>
629
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'sr') !== false) {
630
- echo 'selected';
631
- } ?> value="sr"><?php esc_html_e('Serbian', 'weglot'); ?></option>
632
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'sn') !== false) {
633
- echo 'selected';
634
- } ?> value="sn"><?php esc_html_e('Shona', 'weglot'); ?></option>
635
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'sd') !== false) {
636
- echo 'selected';
637
- } ?> value="sd"><?php esc_html_e('Sindhi', 'weglot'); ?></option>
638
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'si') !== false) {
639
- echo 'selected';
640
- } ?> value="si"><?php esc_html_e('Sinhalese', 'weglot'); ?></option>
641
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'sk') !== false) {
642
- echo 'selected';
643
- } ?> value="sk"><?php esc_html_e('Slovak', 'weglot'); ?></option>
644
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'sl') !== false) {
645
- echo 'selected';
646
- } ?> value="sl"><?php esc_html_e('Slovenian', 'weglot'); ?></option>
647
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'so') !== false) {
648
- echo 'selected';
649
- } ?> value="so"><?php esc_html_e('Somali', 'weglot'); ?></option>
650
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'st') !== false) {
651
- echo 'selected';
652
- } ?> value="st"><?php esc_html_e('Southern Sotho', 'weglot'); ?></option>
653
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'es') !== false) {
654
- echo 'selected';
655
- } ?> value="es"><?php esc_html_e('Spanish', 'weglot'); ?></option>
656
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'su') !== false) {
657
- echo 'selected';
658
- } ?> value="su"><?php esc_html_e('Sundanese', 'weglot'); ?></option>
659
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'sw') !== false) {
660
- echo 'selected';
661
- } ?> value="sw"><?php esc_html_e('Swahili', 'weglot'); ?></option>
662
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'sv') !== false) {
663
- echo 'selected';
664
- } ?> value="sv"><?php esc_html_e('Swedish', 'weglot'); ?></option>
665
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'tl') !== false) {
666
- echo 'selected';
667
- } ?> value="tl"><?php esc_html_e('Tagalog', 'weglot'); ?></option>
668
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ty') !== false) {
669
- echo 'selected';
670
- } ?> value="ty"><?php esc_html_e('Tahitian', 'weglot'); ?></option>
671
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'tg') !== false) {
672
- echo 'selected';
673
- } ?> value="tg"><?php esc_html_e('Tajik', 'weglot'); ?></option>
674
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ta') !== false) {
675
- echo 'selected';
676
- } ?> value="ta"><?php esc_html_e('Tamil', 'weglot'); ?></option>
677
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'tt') !== false) {
678
- echo 'selected';
679
- } ?> value="tt"><?php esc_html_e('Tatar', 'weglot'); ?></option>
680
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'te') !== false) {
681
- echo 'selected';
682
- } ?> value="te"><?php esc_html_e('Telugu', 'weglot'); ?></option>
683
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'th') !== false) {
684
- echo 'selected';
685
- } ?> value="th"><?php esc_html_e('Thai', 'weglot'); ?></option>
686
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'to') !== false) {
687
- echo 'selected';
688
- } ?> value="to"><?php esc_html_e('Tongan', 'weglot'); ?></option>
689
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'tr') !== false) {
690
- echo 'selected';
691
- } ?> value="tr"><?php esc_html_e('Turkish', 'weglot'); ?></option>
692
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'uk') !== false) {
693
- echo 'selected';
694
- } ?> value="uk"><?php esc_html_e('Ukrainian', 'weglot'); ?></option>
695
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'ur') !== false) {
696
- echo 'selected';
697
- } ?> value="ur"><?php esc_html_e('Urdu', 'weglot'); ?></option>
698
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'uz') !== false) {
699
- echo 'selected';
700
- } ?> value="uz"><?php esc_html_e('Uzbek', 'weglot'); ?></option>
701
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'vi') !== false) {
702
- echo 'selected';
703
- } ?> value="vi"><?php esc_html_e('Vietnamese', 'weglot'); ?></option>
704
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'cy') !== false) {
705
- echo 'selected';
706
- } ?> value="cy"><?php esc_html_e('Welsh', 'weglot'); ?></option>
707
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'fy') !== false) {
708
- echo 'selected';
709
- } ?> value="fy"><?php esc_html_e('Western Frisian', 'weglot'); ?></option>
710
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'xh') !== false) {
711
- echo 'selected';
712
- } ?> value="xh"><?php esc_html_e('Xhosa', 'weglot'); ?></option>
713
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'yi') !== false) {
714
- echo 'selected';
715
- } ?> value="yi"><?php esc_html_e('Yiddish', 'weglot'); ?></option>
716
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'yo') !== false) {
717
- echo 'selected';
718
- } ?> value="yo"><?php esc_html_e('Yoruba', 'weglot'); ?></option>
719
- <option <?php if (strpos(esc_attr(get_option('destination_l')), 'zu') !== false) {
720
- echo 'selected';
721
- } ?> value="zu"><?php esc_html_e('Zulu', 'weglot'); ?></option>
722
  </select>
723
  </div>
724
  <input id="destination_input_hidden" type="text"
@@ -726,9 +103,13 @@ if (WGUtils::isLanguageRTL($this->original_l)) { // Right lo left language
726
  value="<?php echo esc_attr(get_option('destination_l')); ?>"
727
  placeholder="en,es" required style="display:none;"/>
728
  <?php
729
- if ($this->userInfo['plan'] <= 0) { ?>
730
- <p class="wg-fsubtext"><?php echo sprintf(esc_html__('On the free plan, you can only choose one language and a maximum of 2000 words. If you want to use more than 1 language and 2000 words, please %1$supgrade your plan%2$s.', 'weglot'), '<a target="_blank" href="https://weglot.com/change-plan">', '</a>'); ?></p><?php } ?> <?php if ($this->userInfo['plan'] >= 18 && $this->userInfo['plan'] <= 19) { ?>
731
- <p class="wg-fsubtext"><?php echo sprintf(esc_html__('On the Starter plan, you can only choose one language. If you want to use more than 1 language, please %1$supgrade your plan%2$s.', 'weglot'), '<a target="_blank" href="https://weglot.com/change-plan">', '</a>'); ?></p><?php } ?>
 
 
 
 
732
  </td>
733
  </tr>
734
  </table>
@@ -944,11 +325,11 @@ color: blue!important;
944
  </td>
945
  </tr>
946
  </table>
947
- <?php if ($this->userInfo['plan'] > 0) { ?>
 
948
  <h3 style="border-bottom:1px solid #c0c0c0;padding-bottom:10px;max-width:800px;margin-top:40px;">
949
  <?php
950
- echo esc_html__('Other options', 'weglot') . ' ' . esc_html__('(Optional)', 'weglot');
951
- ?>
952
  </h3>
953
  <table class="form-table">
954
  <tr valign="top">
@@ -964,15 +345,14 @@ color: blue!important;
964
  </td>
965
  </tr>
966
  </table>
967
- <?php } ?>
 
968
  <?php
969
  if ($showLTR || $showRTL) {
970
- $ltrOrRtl = $showLTR ? esc_html__('Left to Right languages', 'weglot') : esc_html__('Right to Left languages', 'weglot');
971
- ?>
972
  <h3 style="border-bottom:1px solid #c0c0c0;padding-bottom:10px;max-width:800px;margin-top:40px;">
973
  <?php
974
- echo esc_html__('Customize style for ', 'weglot') . esc_html__($ltrOrRtl) . ' ' . esc_html__('(Optional)', 'weglot');
975
- ?>
976
  </h3>
977
  <table class="form-table">
978
  <tr valign="top">
@@ -985,11 +365,13 @@ text-align: right;
985
  }"><?php echo esc_attr(get_option('rtl_ltr_style')); ?></textarea></td>
986
  </tr>
987
  </table>
988
- <?php } ?>
 
989
  <?php submit_button(); ?>
990
  </form>
991
  <?php
992
- if (esc_attr(get_option('show_box')) == 'off') { ?>
 
993
  <div class="wginfobox">
994
  <h3><?php esc_html_e('Where are my translations?', 'weglot'); ?></h3>
995
  <div>
@@ -998,7 +380,8 @@ text-align: right;
998
  target="_blank"
999
  class="wg-editbtn"><?php esc_html_e('Edit my translations', 'weglot'); ?></a>
1000
  </div>
1001
- </div><?php } ?>
 
1002
  <br>
1003
  <a target="_blank"
1004
  href="http://wordpress.org/support/view/plugin-reviews/weglot?rate=5#postform">
1
  <?php
2
+
3
+ use Weglot\Helpers\WeglotUtils;
4
+ use Weglot\Helpers\WeglotLang;
5
+
6
  $showRTL = false;
7
  $showLTR = false;
8
+
9
+ if (WeglotUtils::isLanguageRTL($this->original_l)) { // Right lo left language
10
+ if (WeglotUtils::hasLanguageLTR(explode(',', $this->destination_l))) {
11
  $showLTR = true;
12
  }
13
  } else { // Left to right language
14
+ if (WeglotUtils::hasLanguageRTL(explode(',', $this->destination_l))) {
15
  $showRTL = true;
16
  }
17
  } ?>
18
  <div class="wrap">
19
+ <?php if ($this->allowed == 0) {
20
+ ?>
21
  <div class="wg-status-box">
22
  <h3><?php echo sprintf(esc_html__('Weglot Translate service is not active because you have reached the end of the trial period.', 'weglot'), esc_html__($this->userInfo['limit'])); ?></h3>
23
  <p><?php echo sprintf(esc_html__('To reactivate the service, please %1$supgrade your plan%2$s.', 'weglot'), '<a target="_blank" href="https://weglot.com/change-plan">', '</a>'); ?></p>
24
  </div>
25
+ <?php
26
+ } ?>
27
 
28
+ <?php if (esc_attr(get_option('show_box')) == 'on') {
29
+ ?>
30
  <div class="wgbox-blur">
31
  <div class="wgbox">
32
  <div class="wgclose-btn"><?php esc_html_e('Close', 'weglot'); ?></div>
34
  <p class="wgbox-text"><?php esc_html_e('Go on your website, there is a language switcher. Try it :)', 'weglot'); ?></p>
35
  <a class="wgbox-button button button-primary" href="
36
  <?php
37
+ echo esc_html__($this->home_dir); ?>
 
38
  /" target="_blank">
39
  <?php
40
+ esc_html_e('Go on my front page.', 'weglot'); ?>
 
41
  </a>
42
  <p class="wgbox-subtext"><?php esc_html_e('Next step, edit your translations directly in your Weglot account.', 'weglot'); ?></p>
43
  </div>
46
  list($wgfirstlang) = explode(',', get_option('destination_l'));
47
  if (strlen($wgfirstlang) == 2) {
48
  ?>
49
+ <iframe style="visibility:hidden;" src="<?php
50
+ echo esc_html__($this->home_dir).'/'.esc_html__($wgfirstlang); ?>/" width=1
 
 
 
51
  height=1
52
  ></iframe>
53
+ <?php
54
+ } ?>
55
  <?php update_option('show_box', 'off');
56
  } ?>
57
  <form class="wg-widget-option-form" method="post" action="options.php">
72
  style="font-weight:normal;margin-top:2px;"><?php esc_html_e('What is the original (current) language of your website?', 'weglot'); ?></p>
73
  </th>
74
  <td>
75
+ <select class="wg-input-select" name="original_l" style="width :200px;">
76
+ <?php
77
+ $optionL = get_option('original_l', 'en');
78
+ foreach (WeglotLang::getCodeLangs() as $code): ?>
79
+ <option <?php selected($optionL, $code); ?> value="<?php echo $code ?>"><?php echo esc_html(WeglotLang::getStrLangByCode($code)); ?></option>
80
+ <?php endforeach; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  </select>
82
  </td>
83
  </tr>
91
  style=""
92
  placeholder="French, German, Italian, Portuguese, …"
93
  name="destination_l">
94
+ <?php foreach (WeglotLang::getCodeLangs() as $code): ?>
95
+ <option <?php if (strpos(esc_attr(get_option('destination_l')), $code) !== false) {
96
+ echo 'selected';
97
+ } ?> value="<?php echo $code ?>"><?php echo esc_html(WeglotLang::getStrLangByCode($code)); ?></option>
98
+ <?php endforeach; ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  </select>
100
  </div>
101
  <input id="destination_input_hidden" type="text"
103
  value="<?php echo esc_attr(get_option('destination_l')); ?>"
104
  placeholder="en,es" required style="display:none;"/>
105
  <?php
106
+ if ($this->userInfo['plan'] <= 0) {
107
+ ?>
108
+ <p class="wg-fsubtext"><?php echo sprintf(esc_html__('On the free plan, you can only choose one language and a maximum of 2000 words. If you want to use more than 1 language and 2000 words, please %1$supgrade your plan%2$s.', 'weglot'), '<a target="_blank" href="https://weglot.com/change-plan">', '</a>'); ?></p><?php
109
+ } ?> <?php if ($this->userInfo['plan'] >= 18 && $this->userInfo['plan'] <= 19) {
110
+ ?>
111
+ <p class="wg-fsubtext"><?php echo sprintf(esc_html__('On the Starter plan, you can only choose one language. If you want to use more than 1 language, please %1$supgrade your plan%2$s.', 'weglot'), '<a target="_blank" href="https://weglot.com/change-plan">', '</a>'); ?></p><?php
112
+ } ?>
113
  </td>
114
  </tr>
115
  </table>
325
  </td>
326
  </tr>
327
  </table>
328
+ <?php if ($this->userInfo['plan'] > 0) {
329
+ ?>
330
  <h3 style="border-bottom:1px solid #c0c0c0;padding-bottom:10px;max-width:800px;margin-top:40px;">
331
  <?php
332
+ echo esc_html__('Other options', 'weglot') . ' ' . esc_html__('(Optional)', 'weglot'); ?>
 
333
  </h3>
334
  <table class="form-table">
335
  <tr valign="top">
345
  </td>
346
  </tr>
347
  </table>
348
+ <?php
349
+ } ?>
350
  <?php
351
  if ($showLTR || $showRTL) {
352
+ $ltrOrRtl = $showLTR ? esc_html__('Left to Right languages', 'weglot') : esc_html__('Right to Left languages', 'weglot'); ?>
 
353
  <h3 style="border-bottom:1px solid #c0c0c0;padding-bottom:10px;max-width:800px;margin-top:40px;">
354
  <?php
355
+ echo esc_html__('Customize style for ', 'weglot') . esc_html__($ltrOrRtl) . ' ' . esc_html__('(Optional)', 'weglot'); ?>
 
356
  </h3>
357
  <table class="form-table">
358
  <tr valign="top">
365
  }"><?php echo esc_attr(get_option('rtl_ltr_style')); ?></textarea></td>
366
  </tr>
367
  </table>
368
+ <?php
369
+ } ?>
370
  <?php submit_button(); ?>
371
  </form>
372
  <?php
373
+ if (esc_attr(get_option('show_box')) == 'off') {
374
+ ?>
375
  <div class="wginfobox">
376
  <h3><?php esc_html_e('Where are my translations?', 'weglot'); ?></h3>
377
  <div>
380
  target="_blank"
381
  class="wg-editbtn"><?php esc_html_e('Edit my translations', 'weglot'); ?></a>
382
  </div>
383
+ </div><?php
384
+ } ?>
385
  <br>
386
  <a target="_blank"
387
  href="http://wordpress.org/support/view/plugin-reviews/weglot?rate=5#postform">
readme.txt CHANGED
@@ -3,7 +3,8 @@ Contributors: remyb92
3
  Tags: translate,translation,language,multilingual,bilingual,international,localization,multilanguage,multi language,translations,translator,multilangues,traduction,traducteur,ubersetzung,mehrsprachig,traduccion,traduzione,vertaling,vertaler,meertalig
4
  Requires at least: 4.5
5
  Tested up to: 4.9
6
- Stable tag: 1.10
 
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -17,7 +18,7 @@ a unique dashboard to edit translations or purchase professional translations to
17
  With Weglot Translate, you can translate your site into a multilingual website with multiple languages in minutes without doing any code.
18
  Weglot Translate is totally SEO compatible. Weglot Translate follows Google's best practice in terms of multilingual websites to serve a translated webpage with clean source code. Every translated version of your website will be indexed by Google.
19
 
20
- Weglot Translate is trusted by companies in e-commerce, SaaS, marketplaces, corporate websites, mobile application landing pages, blogs, etc.
21
 
22
  Check Weglot Translate in video:
23
 
@@ -41,6 +42,10 @@ Weglot Translate is free for small websites (under 2000 words) with one translat
41
  Weglot Translate has Free and Premium plans available on the [pricing page](https://weglot.com/pricing), depending on your needs. You can always take the Weglot Translate free trial version to test it.
42
  Weglot Translate offers professional support to premium users to help them translate their websites.
43
 
 
 
 
 
44
  Does Weglot Translate provide support?
45
 
46
  Yes, the Weglot Translate team will support everyone. Post a topic on the [support forum](https://wordpress.org/support/plugin/weglot) or email us at support@weglot.com or speak with us on our live chat on the Weglot website.
@@ -147,6 +152,13 @@ See changelog for upgrade changes.
147
 
148
  == Changelog ==
149
 
 
 
 
 
 
 
 
150
  = 1.10 =
151
  * Add new languages + add Oman flag
152
  * Can potentially translate email sent from admin
3
  Tags: translate,translation,language,multilingual,bilingual,international,localization,multilanguage,multi language,translations,translator,multilangues,traduction,traducteur,ubersetzung,mehrsprachig,traduccion,traduzione,vertaling,vertaler,meertalig
4
  Requires at least: 4.5
5
  Tested up to: 4.9
6
+ Requires PHP: 5.3
7
+ Stable tag: 1.11
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
18
  With Weglot Translate, you can translate your site into a multilingual website with multiple languages in minutes without doing any code.
19
  Weglot Translate is totally SEO compatible. Weglot Translate follows Google's best practice in terms of multilingual websites to serve a translated webpage with clean source code. Every translated version of your website will be indexed by Google.
20
 
21
+ Weglot Translate, a WP multi language plugin, is trusted by companies in e-commerce, SaaS, marketplaces, corporate websites, mobile application landing pages, blogs, etc.
22
 
23
  Check Weglot Translate in video:
24
 
42
  Weglot Translate has Free and Premium plans available on the [pricing page](https://weglot.com/pricing), depending on your needs. You can always take the Weglot Translate free trial version to test it.
43
  Weglot Translate offers professional support to premium users to help them translate their websites.
44
 
45
+ Can I migrate from WPML or Polylang to Weglot Translate?
46
+
47
+ Yes, you can easily migrate to Weglot Translate. Simply deactivate WPML or Polylang to only have one multilingual plugin. Then start using Weglot normally. If you need to import some translations contact us directly at support@weglot.com
48
+
49
  Does Weglot Translate provide support?
50
 
51
  Yes, the Weglot Translate team will support everyone. Post a topic on the [support forum](https://wordpress.org/support/plugin/weglot) or email us at support@weglot.com or speak with us on our live chat on the Weglot website.
152
 
153
  == Changelog ==
154
 
155
+ = 1.11 (05/04/2018) =
156
+ * Add new languages
157
+ * Add new filters
158
+ * Add Yoast Premium compatibility on redirect
159
+ * Bugfix : Exclusion AMP
160
+ * Bugfix : Redirection checkout order on WooCommerce
161
+
162
  = 1.10 =
163
  * Add new languages + add Oman flag
164
  * Can potentially translate email sent from admin
resources/wp-weglot-admin-js.js CHANGED
@@ -216,28 +216,28 @@ jQuery(
216
  switch (original) {
217
  case "af":
218
  return english ? "Afrikaans" : "Afrikaans";
219
- case "sq":
220
- return english ? "Albanian" : "Shqip";
221
  case "am":
222
  return english ? "Amharic" : "አማርኛ";
223
- case "ar":
224
- return english ? "Arabic" : "‏العربية‏";
225
- case "hy":
226
- return english ? "Armenian" : "հայերեն";
227
- case "az":
228
- return english ? "Azerbaijani" : "Azərbaycan dili";
229
  case "ba":
230
  return english ? "Bashkir" : "башҡорт теле";
231
- case "eu":
232
- return english ? "Basque" : "Euskara";
233
- case "be":
234
- return english ? "Belarusian" : "Беларуская";
235
  case "bn":
236
  return english ? "Bengali" : "বাংলা";
237
  case "bs":
238
  return english ? "Bosnian" : "Bosanski";
239
- case "bg":
240
- return english ? "Bulgarian" : "български";
241
  case "my":
242
  return english ? "Burmese" : "မြန်မာ";
243
  case "ca":
@@ -268,6 +268,8 @@ jQuery(
268
  return english ? "Estonian" : "Eesti";
269
  case "fj":
270
  return english ? "Fijian" : "Fidžin";
 
 
271
  case "fi":
272
  return english ? "Finnish" : "Suomi";
273
  case "fr":
@@ -286,6 +288,8 @@ jQuery(
286
  return english ? "Haitian" : "Kreyòl ayisyen";
287
  case "ha":
288
  return english ? "Hausa" : "Hausa";
 
 
289
  case "he":
290
  return english ? "Hebrew" : "עברית";
291
  case "hi":
@@ -298,10 +302,10 @@ jQuery(
298
  return english ? "Igbo" : "Igbo";
299
  case "id":
300
  return english ? "Indonesian" : "Bahasa Indonesia";
301
- case "ga":
302
- return english ? "Irish" : "Gaeilge";
303
- case "it":
304
- return english ? "Italian" : "Italiano";
305
  case "ja":
306
  return english ? "Japanese" : "日本語";
307
  case "jv":
@@ -380,8 +384,8 @@ jQuery(
380
  return english ? "Somali" : "af Soomaali";
381
  case "st":
382
  return english ? "Southern Sotho" : "seSotho";
383
- case "es":
384
- return english ? "Spanish" : "Español";
385
  case "su":
386
  return english ? "Sundanese" : "Sunda";
387
  case "sw":
@@ -410,21 +414,21 @@ jQuery(
410
  return english ? "Ukrainian" : "Українська";
411
  case "ur":
412
  return english ? "Urdu" : "اردو";
413
- case "uz":
414
- return english ? "Uzbek" : "O'zbek";
415
  case "vi":
416
  return english ? "Vietnamese" : "Tiếng Việt";
417
  case "cy":
418
  return english ? "Welsh" : "Cymraeg";
419
  case "fy": //t
420
  return english ? "Western Frisian" : "Frysk";
421
- case "xh"://t
422
  return english ? "Xhosa" : "isiXhosa";
423
- case "yi"://t
424
  return english ? "Yiddish" : "ײִדיש";
425
- case "yo"://t
426
  return english ? "Yoruba" : "Yorùbá";
427
- case "zu"://t
428
  return english ? "Zulu" : "isiZulu";
429
  }
430
  }
216
  switch (original) {
217
  case "af":
218
  return english ? "Afrikaans" : "Afrikaans";
219
+ case "sq":
220
+ return english ? "Albanian" : "Shqip";
221
  case "am":
222
  return english ? "Amharic" : "አማርኛ";
223
+ case "ar":
224
+ return english ? "Arabic" : "‏العربية‏";
225
+ case "hy":
226
+ return english ? "Armenian" : "հայերեն";
227
+ case "az":
228
+ return english ? "Azerbaijani" : "Azərbaycan dili";
229
  case "ba":
230
  return english ? "Bashkir" : "башҡорт теле";
231
+ case "eu":
232
+ return english ? "Basque" : "Euskara";
233
+ case "be":
234
+ return english ? "Belarusian" : "Беларуская";
235
  case "bn":
236
  return english ? "Bengali" : "বাংলা";
237
  case "bs":
238
  return english ? "Bosnian" : "Bosanski";
239
+ case "bg":
240
+ return english ? "Bulgarian" : "български";
241
  case "my":
242
  return english ? "Burmese" : "မြန်မာ";
243
  case "ca":
268
  return english ? "Estonian" : "Eesti";
269
  case "fj":
270
  return english ? "Fijian" : "Fidžin";
271
+ case "fl":
272
+ return english ? "Filipino" : "Filipino";
273
  case "fi":
274
  return english ? "Finnish" : "Suomi";
275
  case "fr":
288
  return english ? "Haitian" : "Kreyòl ayisyen";
289
  case "ha":
290
  return english ? "Hausa" : "Hausa";
291
+ case "hw":
292
+ return english ? "Hawaiann" : "Hawaiann";
293
  case "he":
294
  return english ? "Hebrew" : "עברית";
295
  case "hi":
302
  return english ? "Igbo" : "Igbo";
303
  case "id":
304
  return english ? "Indonesian" : "Bahasa Indonesia";
305
+ case "ga":
306
+ return english ? "Irish" : "Gaeilge";
307
+ case "it":
308
+ return english ? "Italian" : "Italiano";
309
  case "ja":
310
  return english ? "Japanese" : "日本語";
311
  case "jv":
384
  return english ? "Somali" : "af Soomaali";
385
  case "st":
386
  return english ? "Southern Sotho" : "seSotho";
387
+ case "es":
388
+ return english ? "Spanish" : "Español";
389
  case "su":
390
  return english ? "Sundanese" : "Sunda";
391
  case "sw":
414
  return english ? "Ukrainian" : "Українська";
415
  case "ur":
416
  return english ? "Urdu" : "اردو";
417
+ case "uz":
418
+ return english ? "Uzbek" : "O'zbek";
419
  case "vi":
420
  return english ? "Vietnamese" : "Tiếng Việt";
421
  case "cy":
422
  return english ? "Welsh" : "Cymraeg";
423
  case "fy": //t
424
  return english ? "Western Frisian" : "Frysk";
425
+ case "xh": //t
426
  return english ? "Xhosa" : "isiXhosa";
427
+ case "yi": //t
428
  return english ? "Yiddish" : "ײִדיש";
429
+ case "yo": //t
430
  return english ? "Yoruba" : "Yorùbá";
431
+ case "zu": //t
432
  return english ? "Zulu" : "isiZulu";
433
  }
434
  }
resources/wp-weglot-css.css CHANGED
@@ -169,11 +169,13 @@
169
  height: 20px;
170
  }
171
 
 
172
  .wg-li.af a:before { background-position: -6570px 0; }
 
173
  .wg-li.sq a:before { background-position: -2580px 0; }
174
  .wg-li.am a:before { background-position: -5130px 0; }
175
  .wg-li.ar a:before { background-position: -510px 0; }
176
- .wg-li.hy a:before { background-position: -2880px 0; }
177
  .wg-li.az a:before { background-position: -6840px 0; }
178
  .wg-li.ba a:before { background-position: -2040px 0; }
179
  .wg-li.eu a:before { background-position: -7260px 0; }
@@ -290,6 +292,8 @@
290
  height: 20px;
291
  }
292
 
 
 
293
  .wg-li.flag-1.af a:before { background-position: -6848px 0; }
294
  .wg-li.flag-1.sq a:before { background-position: -97px 0; }
295
  .wg-li.flag-1.am a:before { background-position: -2369px 0; }
@@ -405,6 +409,8 @@
405
  height: 24px;
406
  }
407
 
 
 
408
  .wg-li.flag-2.af a:before { background-position: -4968px 0; }
409
  .wg-li.flag-2.sq a:before { background-position: -2976px 0; }
410
  .wg-li.flag-2.am a:before { background-position: -3816px 0; }
@@ -519,6 +525,8 @@
519
  height: 24px;
520
  }
521
 
 
 
522
  .wg-li.flag-3.af a:before { background-position: -5496px 0; }
523
  .wg-li.flag-3.sq a:before { background-position: -4776px 0; }
524
  .wg-li.flag-3.am a:before { background-position: -192px 0; }
169
  height: 20px;
170
  }
171
 
172
+ .wg-li.hw a:before { background-position: -3570px 0; }
173
  .wg-li.af a:before { background-position: -6570px 0; }
174
+ .wg-li.fl a:before { background-position: -3060px 0px; }
175
  .wg-li.sq a:before { background-position: -2580px 0; }
176
  .wg-li.am a:before { background-position: -5130px 0; }
177
  .wg-li.ar a:before { background-position: -510px 0; }
178
+ .wg-li.hy a:before { background-position: -1800px 0; }
179
  .wg-li.az a:before { background-position: -6840px 0; }
180
  .wg-li.ba a:before { background-position: -2040px 0; }
181
  .wg-li.eu a:before { background-position: -7260px 0; }
292
  height: 20px;
293
  }
294
 
295
+ .wg-li.flag-1.hw a:before { background-position: -7840px 0; }
296
+ .wg-li.flag-1.fl a:before { background-position: 2560px 0; }
297
  .wg-li.flag-1.af a:before { background-position: -6848px 0; }
298
  .wg-li.flag-1.sq a:before { background-position: -97px 0; }
299
  .wg-li.flag-1.am a:before { background-position: -2369px 0; }
409
  height: 24px;
410
  }
411
 
412
+ .wg-li.flag-2.hw a:before { background-position: -5448px 0; }
413
+ .wg-li.flag-2.fl a:before { background-position: -1008px 0; }
414
  .wg-li.flag-2.af a:before { background-position: -4968px 0; }
415
  .wg-li.flag-2.sq a:before { background-position: -2976px 0; }
416
  .wg-li.flag-2.am a:before { background-position: -3816px 0; }
525
  height: 24px;
526
  }
527
 
528
+ .wg-li.flag-3.hw a:before { background-position: -2711px 0; }
529
+ .wg-li.flag-3.fl a:before { background-position: -5232px 0; }
530
  .wg-li.flag-3.af a:before { background-position: -5496px 0; }
531
  .wg-li.flag-3.sq a:before { background-position: -4776px 0; }
532
  .wg-li.flag-3.am a:before { background-position: -192px 0; }
simple_html_dom.php CHANGED
@@ -44,21 +44,21 @@ namespace WeglotSDP {
44
  */
45
  define('WG_HDOM_TYPE_ELEMENT', 1);
46
  define('WG_HDOM_TYPE_COMMENT', 2);
47
- define('WG_HDOM_TYPE_TEXT', 3);
48
- define('WG_HDOM_TYPE_ENDTAG', 4);
49
- define('WG_HDOM_TYPE_ROOT', 5);
50
  define('WG_HDOM_TYPE_UNKNOWN', 6);
51
  define('WG_HDOM_QUOTE_DOUBLE', 0);
52
  define('WG_HDOM_QUOTE_SINGLE', 1);
53
- define('WG_HDOM_QUOTE_NO', 3);
54
- define('WG_HDOM_INFO_BEGIN', 0);
55
- define('WG_HDOM_INFO_END', 1);
56
- define('WG_HDOM_INFO_QUOTE', 2);
57
- define('WG_HDOM_INFO_SPACE', 3);
58
- define('WG_HDOM_INFO_TEXT', 4);
59
- define('WG_HDOM_INFO_INNER', 5);
60
- define('WG_HDOM_INFO_OUTER', 6);
61
- define('WG_HDOM_INFO_ENDSPACE',7);
62
  define('WG_DEFAULT_TARGET_CHARSET', 'UTF-8');
63
  define('WG_DEFAULT_BR_TEXT', "\r\n");
64
  define('WG_DEFAULT_SPAN_TEXT', " ");
@@ -75,8 +75,7 @@ function file_get_html($url, $use_include_path = false, $context=null, $offset =
75
  $contents = file_get_contents($url, $use_include_path, $context, $offset);
76
  // Paperg - use our own mechanism for getting the contents as we want to control the timeout.
77
  //$contents = retrieve_url_contents($url);
78
- if (empty($contents) || strlen($contents) > WG_MAX_FILE_SIZE)
79
- {
80
  return false;
81
  }
82
  // The second parameter can force the selectors to all be lowercase.
@@ -88,8 +87,7 @@ function file_get_html($url, $use_include_path = false, $context=null, $offset =
88
  function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = WG_DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=WG_DEFAULT_BR_TEXT, $defaultSpanText=WG_DEFAULT_SPAN_TEXT)
89
  {
90
  $dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText);
91
- if (empty($str) || strlen($str) > WG_MAX_FILE_SIZE)
92
- {
93
  $dom->clear();
94
  return false;
95
  }
@@ -124,24 +122,24 @@ class simple_html_dom_node
124
  public $tag_start = 0;
125
  private $dom = null;
126
 
127
- function __construct($dom)
128
  {
129
  $this->dom = $dom;
130
  $dom->nodes[] = $this;
131
  }
132
 
133
- function __destruct()
134
  {
135
  $this->clear();
136
  }
137
 
138
- function __toString()
139
  {
140
  return $this->outertext();
141
  }
142
 
143
  // clean up memory due to php5 circular references memory leak...
144
- function clear()
145
  {
146
  $this->dom = null;
147
  $this->nodes = null;
@@ -150,24 +148,22 @@ class simple_html_dom_node
150
  }
151
 
152
  // dump node's tree
153
- function dump($show_attr=true, $deep=0)
154
  {
155
  $lead = str_repeat(' ', $deep);
156
 
157
  echo $lead.$this->tag;
158
- if ($show_attr && count($this->attr)>0)
159
- {
160
  echo '(';
161
- foreach ($this->attr as $k=>$v)
162
  echo "[$k]=>\"".$this->$k.'", ';
 
163
  echo ')';
164
  }
165
  echo "\n";
166
 
167
- if ($this->nodes)
168
- {
169
- foreach ($this->nodes as $c)
170
- {
171
  $c->dump($show_attr, $deep+1);
172
  }
173
  }
@@ -175,29 +171,22 @@ class simple_html_dom_node
175
 
176
 
177
  // Debugging function to dump a single dom node with a bunch of information about it.
178
- function dump_node($echo=true)
179
  {
180
-
181
  $string = $this->tag;
182
- if (count($this->attr)>0)
183
- {
184
  $string .= '(';
185
- foreach ($this->attr as $k=>$v)
186
- {
187
  $string .= "[$k]=>\"".$this->$k.'", ';
188
  }
189
  $string .= ')';
190
  }
191
- if (count($this->_)>0)
192
- {
193
  $string .= ' $_ (';
194
- foreach ($this->_ as $k=>$v)
195
- {
196
- if (is_array($v))
197
- {
198
  $string .= "[$k]=>(";
199
- foreach ($v as $k2=>$v2)
200
- {
201
  $string .= "[$k2]=>\"".$v2.'", ';
202
  }
203
  $string .= ")";
@@ -208,18 +197,14 @@ class simple_html_dom_node
208
  $string .= ")";
209
  }
210
 
211
- if (isset($this->text))
212
- {
213
  $string .= " text: (" . $this->text . ")";
214
  }
215
 
216
  $string .= " WG_HDOM_INNER_INFO: '";
217
- if (isset($node->_[WG_HDOM_INFO_INNER]))
218
- {
219
  $string .= $node->_[WG_HDOM_INFO_INNER] . "'";
220
- }
221
- else
222
- {
223
  $string .= ' NULL ';
224
  }
225
 
@@ -228,25 +213,21 @@ class simple_html_dom_node
228
  $string .= " tag_start: " . $this->tag_start;
229
  $string .= "\n";
230
 
231
- if ($echo)
232
- {
233
  echo $string;
234
  return;
235
- }
236
- else
237
- {
238
  return $string;
239
  }
240
  }
241
 
242
  // returns the parent of node
243
  // If a node is passed in, it will reset the parent of the current node to that one.
244
- function parent($parent=null)
245
  {
246
  // I am SURE that this doesn't work properly.
247
  // It fails to unset the current node from it's current parents nodes or children list first.
248
- if ($parent !== null)
249
- {
250
  $this->parent = $parent;
251
  $this->parent->nodes[] = $this;
252
  $this->parent->children[] = $this;
@@ -256,90 +237,93 @@ class simple_html_dom_node
256
  }
257
 
258
  // verify that node has children
259
- function has_child()
260
  {
261
  return !empty($this->children);
262
  }
263
 
264
  // returns children of node
265
- function children($idx=-1)
266
  {
267
- if ($idx===-1)
268
- {
269
  return $this->children;
270
  }
271
- if (isset($this->children[$idx])) return $this->children[$idx];
 
 
272
  return null;
273
  }
274
 
275
  // returns the first child of node
276
- function first_child()
277
  {
278
- if (count($this->children)>0)
279
- {
280
  return $this->children[0];
281
  }
282
  return null;
283
  }
284
 
285
  // returns the last child of node
286
- function last_child()
287
  {
288
- if (($count=count($this->children))>0)
289
- {
290
  return $this->children[$count-1];
291
  }
292
  return null;
293
  }
294
 
295
  // returns the next sibling of node
296
- function next_sibling()
297
  {
298
- if ($this->parent===null)
299
- {
300
  return null;
301
  }
302
 
303
  $idx = 0;
304
  $count = count($this->parent->children);
305
- while ($idx<$count && $this!==$this->parent->children[$idx])
306
- {
307
  ++$idx;
308
  }
309
- if (++$idx>=$count)
310
- {
311
  return null;
312
  }
313
  return $this->parent->children[$idx];
314
  }
315
 
316
  // returns the previous sibling of node
317
- function prev_sibling()
318
  {
319
- if ($this->parent===null) return null;
 
 
320
  $idx = 0;
321
  $count = count($this->parent->children);
322
- while ($idx<$count && $this!==$this->parent->children[$idx])
323
  ++$idx;
324
- if (--$idx<0) return null;
 
 
 
325
  return $this->parent->children[$idx];
326
  }
327
 
328
  // function to locate a specific ancestor tag in the path to the root.
329
- function find_ancestor_tag($tag)
330
  {
331
  global $debugObject;
332
- if (is_object($debugObject)) { $debugObject->debugLogEntry(1); }
 
 
333
 
334
  // Start by including ourselves in the comparison.
335
  $returnDom = $this;
336
 
337
- while (!is_null($returnDom))
338
- {
339
- if (is_object($debugObject)) { $debugObject->debugLog(2, "Current tag is: " . $returnDom->tag); }
 
340
 
341
- if ($returnDom->tag == $tag)
342
- {
343
  break;
344
  }
345
  $returnDom = $returnDom->parent;
@@ -348,113 +332,116 @@ class simple_html_dom_node
348
  }
349
 
350
  // get dom node's inner html
351
- function innertext()
352
  {
353
- if (isset($this->_[WG_HDOM_INFO_INNER])) return $this->_[WG_HDOM_INFO_INNER];
354
- if (isset($this->_[WG_HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[WG_HDOM_INFO_TEXT]);
 
 
 
 
355
 
356
  $ret = '';
357
- foreach ($this->nodes as $n)
358
  $ret .= $n->outertext();
 
359
  return $ret;
360
  }
361
 
362
  // get dom node's outer text (with tag)
363
- function outertext()
364
  {
365
  global $debugObject;
366
- if (is_object($debugObject))
367
- {
368
  $text = '';
369
- if ($this->tag == 'text')
370
- {
371
- if (!empty($this->text))
372
- {
373
  $text = " with text: " . $this->text;
374
  }
375
  }
376
  $debugObject->debugLog(1, 'Innertext of tag: ' . $this->tag . $text);
377
  }
378
 
379
- if ($this->tag==='root') return $this->innertext();
 
 
380
 
381
  // trigger callback
382
- if ($this->dom && $this->dom->callback!==null)
383
- {
384
  call_user_func_array($this->dom->callback, array($this));
385
  }
386
 
387
- if (isset($this->_[WG_HDOM_INFO_OUTER])) return $this->_[WG_HDOM_INFO_OUTER];
388
- if (isset($this->_[WG_HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[WG_HDOM_INFO_TEXT]);
 
 
 
 
389
 
390
  // render begin tag
391
- if ($this->dom && $this->dom->nodes[$this->_[WG_HDOM_INFO_BEGIN]])
392
- {
393
  $ret = $this->dom->nodes[$this->_[WG_HDOM_INFO_BEGIN]]->makeup();
394
  } else {
395
  $ret = "";
396
  }
397
 
398
  // render inner text
399
- if (isset($this->_[WG_HDOM_INFO_INNER]))
400
- {
401
  // If it's a br tag... don't return the WG_HDOM_INNER_INFO that we may or may not have added.
402
- if ($this->tag != "br")
403
- {
404
  $ret .= $this->_[WG_HDOM_INFO_INNER];
405
  }
406
  } else {
407
- if ($this->nodes)
408
- {
409
- foreach ($this->nodes as $n)
410
- {
411
  $ret .= $this->convert_text($n->outertext());
412
  }
413
  }
414
  }
415
 
416
  // render end tag
417
- if (isset($this->_[WG_HDOM_INFO_END]) && $this->_[WG_HDOM_INFO_END]!=0)
418
  $ret .= '</'.$this->tag.'>';
 
419
  return $ret;
420
  }
421
 
422
  // get dom node's plain text
423
- function text()
424
  {
425
- if (isset($this->_[WG_HDOM_INFO_INNER])) return $this->_[WG_HDOM_INFO_INNER];
426
- switch ($this->nodetype)
427
- {
 
428
  case WG_HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[WG_HDOM_INFO_TEXT]);
429
  case WG_HDOM_TYPE_COMMENT: return '';
430
  case WG_HDOM_TYPE_UNKNOWN: return '';
431
  }
432
- if (strcasecmp($this->tag, 'script')===0) return '';
433
- if (strcasecmp($this->tag, 'style')===0) return '';
 
 
 
 
434
 
435
  $ret = '';
436
  // In rare cases, (always node type 1 or WG_HDOM_TYPE_ELEMENT - observed for some span tags, and some p tags) $this->nodes is set to NULL.
437
  // NOTE: This indicates that there is a problem where it's set to NULL without a clear happening.
438
  // WHY is this happening?
439
- if (!is_null($this->nodes))
440
- {
441
- foreach ($this->nodes as $n)
442
- {
443
  $ret .= $this->convert_text($n->text());
444
  }
445
 
446
  // If this node is a span... add a space at the end of it so multiple spans don't run into each other. This is plaintext after all.
447
- if ($this->tag == "span")
448
- {
449
  $ret .= $this->dom->WG_DEFAULT_SPAN_TEXT;
450
  }
451
-
452
-
453
  }
454
  return $ret;
455
  }
456
 
457
- function xmltext()
458
  {
459
  $ret = $this->innertext();
460
  $ret = str_ireplace('<![CDATA[', '', $ret);
@@ -463,29 +450,30 @@ class simple_html_dom_node
463
  }
464
 
465
  // build node's text with tag
466
- function makeup()
467
  {
468
  // text, comment, unknown
469
- if (isset($this->_[WG_HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[WG_HDOM_INFO_TEXT]);
 
 
470
 
471
  $ret = '<'.$this->tag;
472
  $i = -1;
473
 
474
- foreach ($this->attr as $key=>$val)
475
- {
476
  ++$i;
477
 
478
  // skip removed attribute
479
- if ($val===null || $val===false)
480
  continue;
 
481
 
482
  $ret .= $this->_[WG_HDOM_INFO_SPACE][$i][0];
483
  //no value attr: nowrap, checked selected...
484
- if ($val===true)
485
  $ret .= $key;
486
- else {
487
- switch ($this->_[WG_HDOM_INFO_QUOTE][$i])
488
- {
489
  case WG_HDOM_QUOTE_DOUBLE: $quote = '"'; break;
490
  case WG_HDOM_QUOTE_SINGLE: $quote = '\''; break;
491
  default: $quote = '';
@@ -499,28 +487,31 @@ class simple_html_dom_node
499
 
500
  // find elements by css selector
501
  //PaperG - added ability for find to lowercase the value of the selector.
502
- function find($selector, $idx=null, $lowercase=false)
503
  {
504
  $selectors = $this->parse_selector($selector);
505
- if (($count=count($selectors))===0) return array();
 
 
506
  $found_keys = array();
507
 
508
  // find each selector
509
- for ($c=0; $c<$count; ++$c)
510
- {
511
  // The change on the below line was documented on the sourceforge code tracker id 2788009
512
  // used to be: if (($levle=count($selectors[0]))===0) return array();
513
- if (($levle=count($selectors[$c]))===0) return array();
514
- if (!isset($this->_[WG_HDOM_INFO_BEGIN])) return array();
 
 
 
 
515
 
516
  $head = array($this->_[WG_HDOM_INFO_BEGIN]=>1);
517
 
518
  // handle descendant selectors, no recursive!
519
- for ($l=0; $l<$levle; ++$l)
520
- {
521
  $ret = array();
522
- foreach ($head as $k=>$v)
523
- {
524
  $n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k];
525
  //PaperG - Pass this optional parameter on to the seek function.
526
  $n->seek($selectors[$c][$l], $ret, $lowercase);
@@ -528,10 +519,10 @@ class simple_html_dom_node
528
  $head = $ret;
529
  }
530
 
531
- foreach ($head as $k=>$v)
532
- {
533
- if (!isset($found_keys[$k]))
534
  $found_keys[$k] = 1;
 
535
  }
536
  }
537
 
@@ -539,12 +530,16 @@ class simple_html_dom_node
539
  ksort($found_keys);
540
 
541
  $found = array();
542
- foreach ($found_keys as $k=>$v)
543
  $found[] = $this->dom->nodes[$k];
 
544
 
545
  // return nth-element or array
546
- if (is_null($idx)) return $found;
547
- else if ($idx<0) $idx = count($found) + $idx;
 
 
 
548
  return (isset($found[$idx])) ? $found[$idx] : null;
549
  }
550
 
@@ -553,16 +548,16 @@ class simple_html_dom_node
553
  protected function seek($selector, &$ret, $lowercase=false)
554
  {
555
  global $debugObject;
556
- if (is_object($debugObject)) { $debugObject->debugLogEntry(1); }
 
 
557
 
558
  list($tag, $key, $val, $exp, $no_key) = $selector;
559
 
560
  // xpath index
561
- if ($tag && $key && is_numeric($key))
562
- {
563
  $count = 0;
564
- foreach ($this->children as $c)
565
- {
566
  if ($tag==='*' || $tag===$c->tag) {
567
  if (++$count==$key) {
568
  $ret[$c->_[WG_HDOM_INFO_BEGIN]] = 1;
@@ -589,19 +584,26 @@ class simple_html_dom_node
589
  $pass = true;
590
 
591
  if ($tag==='*' && !$key) {
592
- if (in_array($node, $this->children, true))
593
  $ret[$i] = 1;
 
594
  continue;
595
  }
596
 
597
  // compare tag
598
- if ($tag && $tag!=$node->tag && $tag!=='*') {$pass=false;}
 
 
599
  // compare key
600
  if ($pass && $key) {
601
  if ($no_key) {
602
- if (isset($node->attr[$key])) $pass=false;
 
 
603
  } else {
604
- if (($key != "plaintext") && !isset($node->attr[$key])) $pass=false;
 
 
605
  }
606
  }
607
  // compare value
@@ -614,7 +616,9 @@ class simple_html_dom_node
614
  // this is a normal search, we want the value of that attribute of the tag.
615
  $nodeKeyValue = $node->attr[$key];
616
  }
617
- if (is_object($debugObject)) {$debugObject->debugLog(2, "testing node: " . $node->tag . " for attribute: " . $key . $exp . $val . " where nodes value is: " . $nodeKeyValue);}
 
 
618
 
619
  //PaperG - If lowercase is set, do a case insensitive test of the value of the selector.
620
  if ($lowercase) {
@@ -622,11 +626,13 @@ class simple_html_dom_node
622
  } else {
623
  $check = $this->match($exp, $val, $nodeKeyValue);
624
  }
625
- if (is_object($debugObject)) {$debugObject->debugLog(2, "after match: " . ($check ? "true" : "false"));}
 
 
626
 
627
  // handle multiple class
628
  if (!$check && strcasecmp($key, 'class')===0) {
629
- foreach (explode(' ',$node->attr[$key]) as $k) {
630
  // Without this, there were cases where leading, trailing, or double spaces lead to our comparing blanks - bad form.
631
  if (!empty($k)) {
632
  if ($lowercase) {
@@ -634,22 +640,33 @@ class simple_html_dom_node
634
  } else {
635
  $check = $this->match($exp, $val, $k);
636
  }
637
- if ($check) break;
 
 
638
  }
639
  }
640
  }
641
- if (!$check) $pass = false;
 
 
 
 
 
642
  }
643
- if ($pass) $ret[$i] = 1;
644
  unset($node);
645
  }
646
  // It's passed by reference so this is actually what this function returns.
647
- if (is_object($debugObject)) {$debugObject->debugLog(1, "EXIT - ret: ", $ret);}
 
 
648
  }
649
 
650
- protected function match($exp, $pattern, $value) {
 
651
  global $debugObject;
652
- if (is_object($debugObject)) {$debugObject->debugLogEntry(1);}
 
 
653
 
654
  switch ($exp) {
655
  case '=':
@@ -657,9 +674,9 @@ class simple_html_dom_node
657
  case '!=':
658
  return ($value!==$pattern);
659
  case '^=':
660
- return preg_match("/^".preg_quote($pattern,'/')."/", $value);
661
  case '$=':
662
- return preg_match("/".preg_quote($pattern,'/')."$/", $value);
663
  case '*=':
664
  if ($pattern[0]=='/') {
665
  return preg_match($pattern, $value);
@@ -669,20 +686,25 @@ class simple_html_dom_node
669
  return false;
670
  }
671
 
672
- protected function parse_selector($selector_string) {
 
673
  global $debugObject;
674
- if (is_object($debugObject)) {$debugObject->debugLogEntry(1);}
 
 
675
 
676
  // pattern of CSS selectors, modified from mootools
677
  // Paperg: Add the colon to the attrbute, so that it properly finds <tag attr:ibute="something" > like google does.
678
  // Note: if you try to look at this attribute, yo MUST use getAttribute since $dom->x:y will fail the php syntax check.
679
- // Notice the \[ starting the attbute? and the @? following? This implies that an attribute can begin with an @ sign that is not captured.
680
- // This implies that an html attribute specifier may start with an @ sign that is NOT captured by the expression.
681
- // farther study is required to determine of this should be documented or removed.
682
  // $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is";
683
  $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-:]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is";
684
  preg_match_all($pattern, trim($selector_string).' ', $matches, PREG_SET_ORDER);
685
- if (is_object($debugObject)) {$debugObject->debugLog(2, "Matches Array: ", $matches);}
 
 
686
 
687
  $selectors = array();
688
  $result = array();
@@ -690,21 +712,43 @@ class simple_html_dom_node
690
 
691
  foreach ($matches as $m) {
692
  $m[0] = trim($m[0]);
693
- if ($m[0]==='' || $m[0]==='/' || $m[0]==='//') continue;
 
 
694
  // for browser generated xpath
695
- if ($m[1]==='tbody') continue;
 
 
696
 
697
  list($tag, $key, $val, $exp, $no_key) = array($m[1], null, null, '=', false);
698
- if (!empty($m[2])) {$key='id'; $val=$m[2];}
699
- if (!empty($m[3])) {$key='class'; $val=$m[3];}
700
- if (!empty($m[4])) {$key=$m[4];}
701
- if (!empty($m[5])) {$exp=$m[5];}
702
- if (!empty($m[6])) {$val=$m[6];}
 
 
 
 
 
 
 
 
 
 
 
 
703
 
704
  // convert to lowercase
705
- if ($this->dom->lowercase) {$tag=strtolower($tag); $key=strtolower($key);}
 
 
 
706
  //elements that do NOT have the specified attribute
707
- if (isset($key[0]) && $key[0]==='!') {$key=substr($key, 1); $no_key=true;}
 
 
 
708
 
709
  $result[] = array($tag, $key, $val, $exp, $no_key);
710
  if (trim($m[7])===',') {
@@ -712,14 +756,15 @@ class simple_html_dom_node
712
  $result = array();
713
  }
714
  }
715
- if (count($result)>0)
716
  $selectors[] = $result;
 
717
  return $selectors;
718
  }
719
 
720
- function __get($name) {
721
- if (isset($this->attr[$name]))
722
- {
723
  return $this->convert_text($this->attr[$name]);
724
  }
725
  switch ($name) {
@@ -731,11 +776,14 @@ class simple_html_dom_node
731
  }
732
  }
733
 
734
- function __set($name, $value) {
 
735
  switch ($name) {
736
  case 'outertext': return $this->_[WG_HDOM_INFO_OUTER] = $value;
737
  case 'innertext':
738
- if (isset($this->_[WG_HDOM_INFO_TEXT])) return $this->_[WG_HDOM_INFO_TEXT] = $value;
 
 
739
  return $this->_[WG_HDOM_INFO_INNER] = $value;
740
  }
741
  if (!isset($this->attr[$name])) {
@@ -745,7 +793,8 @@ class simple_html_dom_node
745
  $this->attr[$name] = $value;
746
  }
747
 
748
- function __isset($name) {
 
749
  switch ($name) {
750
  case 'outertext': return true;
751
  case 'innertext': return true;
@@ -755,51 +804,49 @@ class simple_html_dom_node
755
  return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]);
756
  }
757
 
758
- function __unset($name) {
759
- if (isset($this->attr[$name]))
 
760
  unset($this->attr[$name]);
 
761
  }
762
 
763
  // PaperG - Function to convert the text from one character set to another if the two sets are not the same.
764
- function convert_text($text)
765
  {
766
  global $debugObject;
767
- if (is_object($debugObject)) {$debugObject->debugLogEntry(1);}
 
 
768
 
769
  $converted_text = $text;
770
 
771
  $sourceCharset = "";
772
  $targetCharset = "";
773
 
774
- if ($this->dom)
775
- {
776
  $sourceCharset = strtoupper($this->dom->_charset);
777
  $targetCharset = strtoupper($this->dom->_target_charset);
778
  }
779
- if (is_object($debugObject)) {$debugObject->debugLog(3, "source charset: " . $sourceCharset . " target charaset: " . $targetCharset);}
 
 
780
 
781
- if (!empty($sourceCharset) && !empty($targetCharset) && (strcasecmp($sourceCharset, $targetCharset) != 0))
782
- {
783
  // Check if the reported encoding could have been incorrect and the text is actually already UTF-8
784
- if ((strcasecmp($targetCharset, 'UTF-8') == 0) && ($this->is_utf8($text)))
785
- {
786
  $converted_text = $text;
787
- }
788
- else
789
- {
790
  $converted_text = iconv($sourceCharset, $targetCharset, $text);
791
  }
792
  }
793
 
794
  // Lets make sure that we don't have that silly BOM issue with any of the utf-8 text we output.
795
- if ($targetCharset == 'UTF-8')
796
- {
797
- if (substr($converted_text, 0, 3) == "\xef\xbb\xbf")
798
- {
799
  $converted_text = substr($converted_text, 3);
800
  }
801
- if (substr($converted_text, -3) == "\xef\xbb\xbf")
802
- {
803
  $converted_text = substr($converted_text, 0, -3);
804
  }
805
  }
@@ -813,29 +860,39 @@ class simple_html_dom_node
813
  * @param mixed $str String to be tested
814
  * @return boolean
815
  */
816
- static function is_utf8($str)
817
  {
818
- $c=0; $b=0;
 
819
  $bits=0;
820
  $len=strlen($str);
821
- for($i=0; $i<$len; $i++)
822
- {
823
  $c=ord($str[$i]);
824
- if($c > 128)
825
- {
826
- if(($c >= 254)) return false;
827
- elseif($c >= 252) $bits=6;
828
- elseif($c >= 248) $bits=5;
829
- elseif($c >= 240) $bits=4;
830
- elseif($c >= 224) $bits=3;
831
- elseif($c >= 192) $bits=2;
832
- else return false;
833
- if(($i+$bits) > $len) return false;
834
- while($bits > 1)
835
- {
 
 
 
 
 
 
 
 
836
  $i++;
837
  $b=ord($str[$i]);
838
- if($b < 128 || $b > 191) return false;
 
 
839
  $bits--;
840
  }
841
  }
@@ -858,69 +915,58 @@ class simple_html_dom_node
858
  * @version April 19 2012
859
  * @return array an array containing the 'height' and 'width' of the image on the page or -1 if we can't figure it out.
860
  */
861
- function get_display_size()
862
  {
863
  global $debugObject;
864
 
865
  $width = -1;
866
  $height = -1;
867
 
868
- if ($this->tag !== 'img')
869
- {
870
  return false;
871
  }
872
 
873
  // See if there is aheight or width attribute in the tag itself.
874
- if (isset($this->attr['width']))
875
- {
876
  $width = $this->attr['width'];
877
  }
878
 
879
- if (isset($this->attr['height']))
880
- {
881
  $height = $this->attr['height'];
882
  }
883
 
884
  // Now look for an inline style.
885
- if (isset($this->attr['style']))
886
- {
887
  // Thanks to user gnarf from stackoverflow for this regular expression.
888
  $attributes = array();
889
  preg_match_all("/([\w-]+)\s*:\s*([^;]+)\s*;?/", $this->attr['style'], $matches, PREG_SET_ORDER);
890
  foreach ($matches as $match) {
891
- $attributes[$match[1]] = $match[2];
892
  }
893
 
894
  // If there is a width in the style attributes:
895
- if (isset($attributes['width']) && $width == -1)
896
- {
897
  // check that the last two characters are px (pixels)
898
- if (strtolower(substr($attributes['width'], -2)) == 'px')
899
- {
900
  $proposed_width = substr($attributes['width'], 0, -2);
901
  // Now make sure that it's an integer and not something stupid.
902
- if (filter_var($proposed_width, FILTER_VALIDATE_INT))
903
- {
904
  $width = $proposed_width;
905
  }
906
  }
907
  }
908
 
909
  // If there is a width in the style attributes:
910
- if (isset($attributes['height']) && $height == -1)
911
- {
912
  // check that the last two characters are px (pixels)
913
- if (strtolower(substr($attributes['height'], -2)) == 'px')
914
- {
915
  $proposed_height = substr($attributes['height'], 0, -2);
916
  // Now make sure that it's an integer and not something stupid.
917
- if (filter_var($proposed_height, FILTER_VALIDATE_INT))
918
- {
919
  $height = $proposed_height;
920
  }
921
  }
922
  }
923
-
924
  }
925
 
926
  // Future enhancement:
@@ -939,25 +985,79 @@ class simple_html_dom_node
939
  }
940
 
941
  // camel naming conventions
942
- function getAllAttributes() {return $this->attr;}
943
- function getAttribute($name) {return $this->__get($name);}
944
- function setAttribute($name, $value) {$this->__set($name, $value);}
945
- function hasAttribute($name) {return $this->__isset($name);}
946
- function removeAttribute($name) {$this->__set($name, null);}
947
- function getElementById($id) {return $this->find("#$id", 0);}
948
- function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);}
949
- function getElementByTagName($name) {return $this->find($name, 0);}
950
- function getElementsByTagName($name, $idx=null) {return $this->find($name, $idx);}
951
- function parentNode() {return $this->parent();}
952
- function childNodes($idx=-1) {return $this->children($idx);}
953
- function firstChild() {return $this->first_child();}
954
- function lastChild() {return $this->last_child();}
955
- function nextSibling() {return $this->next_sibling();}
956
- function previousSibling() {return $this->prev_sibling();}
957
- function hasChildNodes() {return $this->has_child();}
958
- function nodeName() {return $this->tag;}
959
- function appendChild($node) {$node->parent($this); return $node;}
960
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
961
  }
962
 
963
  /**
@@ -1009,20 +1109,16 @@ class simple_html_dom
1009
  'p'=>array('p'=>1),
1010
  'nobr'=>array('nobr'=>1),
1011
  'b'=>array('b'=>1),
1012
- 'option'=>array('option'=>1),
1013
  'source'=>array('source'=>1)
1014
  );
1015
 
1016
- function __construct($str=null, $lowercase=true, $forceTagsClosed=true, $target_charset=WG_DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=WG_DEFAULT_BR_TEXT, $defaultSpanText=WG_DEFAULT_SPAN_TEXT)
1017
  {
1018
- if ($str)
1019
- {
1020
- if (preg_match("/^http:\/\//i",$str) || is_file($str))
1021
- {
1022
  $this->load_file($str);
1023
- }
1024
- else
1025
- {
1026
  $this->load($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText);
1027
  }
1028
  }
@@ -1033,13 +1129,13 @@ class simple_html_dom
1033
  $this->_target_charset = $target_charset;
1034
  }
1035
 
1036
- function __destruct()
1037
  {
1038
  $this->clear();
1039
  }
1040
 
1041
  // load html from string
1042
- function load($str, $lowercase=true, $stripRN=true, $defaultBRText=WG_DEFAULT_BR_TEXT, $defaultSpanText=WG_DEFAULT_SPAN_TEXT)
1043
  {
1044
  global $debugObject;
1045
 
@@ -1073,11 +1169,10 @@ class simple_html_dom
1073
 
1074
  // make load function chainable
1075
  return $this;
1076
-
1077
  }
1078
 
1079
  // load html from file
1080
- function load_file()
1081
  {
1082
  $args = func_get_args();
1083
  $this->load(call_user_func_array('file_get_contents', $args), true);
@@ -1089,45 +1184,61 @@ class simple_html_dom
1089
  }
1090
 
1091
  // set callback function
1092
- function set_callback($function_name)
1093
  {
1094
  $this->callback = $function_name;
1095
  }
1096
 
1097
  // remove callback function
1098
- function remove_callback()
1099
  {
1100
  $this->callback = null;
1101
  }
1102
 
1103
  // save dom as string
1104
- function save($filepath='')
1105
  {
1106
  $ret = $this->root->innertext();
1107
- if ($filepath!=='') file_put_contents($filepath, $ret, LOCK_EX);
 
 
1108
  return $ret;
1109
  }
1110
 
1111
  // find dom node by css selector
1112
  // Paperg - allow us to specify that we want case insensitive testing of the value of the selector.
1113
- function find($selector, $idx=null, $lowercase=false)
1114
  {
1115
  return $this->root->find($selector, $idx, $lowercase);
1116
  }
1117
 
1118
  // clean up memory due to php5 circular references memory leak...
1119
- function clear()
1120
  {
1121
- foreach ($this->nodes as $n) {$n->clear(); $n = null;}
 
 
 
1122
  // This add next line is documented in the sourceforge repository. 2977248 as a fix for ongoing memory leaks that occur even with the use of clear.
1123
- if (isset($this->children)) foreach ($this->children as $n) {$n->clear(); $n = null;}
1124
- if (isset($this->parent)) {$this->parent->clear(); unset($this->parent);}
1125
- if (isset($this->root)) {$this->root->clear(); unset($this->root);}
 
 
 
 
 
 
 
 
 
 
 
1126
  unset($this->doc);
1127
  unset($this->noise);
1128
  }
1129
 
1130
- function dump($show_attr=true)
1131
  {
1132
  $this->root->dump($show_attr);
1133
  }
@@ -1164,14 +1275,15 @@ class simple_html_dom
1164
  $this->root->_[WG_HDOM_INFO_BEGIN] = -1;
1165
  $this->root->nodetype = WG_HDOM_TYPE_ROOT;
1166
  $this->parent = $this->root;
1167
- if ($this->size>0) $this->char = $this->doc[0];
 
 
1168
  }
1169
 
1170
  // parse html content
1171
  protected function parse()
1172
  {
1173
- if (($s = $this->copy_until_char('<'))==='')
1174
- {
1175
  return $this->read_tag();
1176
  }
1177
 
@@ -1192,37 +1304,34 @@ class simple_html_dom
1192
 
1193
  $charset = null;
1194
 
1195
- if (function_exists('get_last_retrieve_url_contents_content_type'))
1196
- {
1197
  $contentTypeHeader = get_last_retrieve_url_contents_content_type();
1198
  $success = preg_match('/charset=(.+)/', $contentTypeHeader, $matches);
1199
- if ($success)
1200
- {
1201
  $charset = $matches[1];
1202
- if (is_object($debugObject)) {$debugObject->debugLog(2, 'header content-type found charset of: ' . $charset);}
 
 
1203
  }
1204
-
1205
  }
1206
 
1207
- if (empty($charset))
1208
- {
1209
- $el = $this->root->find('meta[http-equiv=Content-Type]',0);
1210
- if (!empty($el))
1211
- {
1212
  $fullvalue = $el->content;
1213
- if (is_object($debugObject)) {$debugObject->debugLog(2, 'meta content-type tag found' . $fullvalue);}
 
 
1214
 
1215
- if (!empty($fullvalue))
1216
- {
1217
  $success = preg_match('/charset=(.+)/', $fullvalue, $matches);
1218
- if ($success)
1219
- {
1220
  $charset = $matches[1];
1221
- }
1222
- else
1223
- {
1224
  // If there is a meta tag, and they don't specify the character set, research says that it's typically ISO-8859-1
1225
- if (is_object($debugObject)) {$debugObject->debugLog(2, 'meta content-type tag couldn\'t be parsed. using iso-8859 default.');}
 
 
1226
  $charset = 'ISO-8859-1';
1227
  }
1228
  }
@@ -1230,30 +1339,35 @@ class simple_html_dom
1230
  }
1231
 
1232
  // If we couldn't find a charset above, then lets try to detect one based on the text we got...
1233
- if (empty($charset))
1234
- {
1235
  // Have php try to detect the encoding from the text given to us.
1236
- if(function_exists('mb_detect_encoding')) {
1237
- $charset = mb_detect_encoding($this->root->plaintext . "ascii", $encoding_list = array( "UTF-8", "CP1252" ) );
1238
- }
1239
- if (is_object($debugObject)) {$debugObject->debugLog(2, 'mb_detect found: ' . $charset);}
 
 
1240
 
1241
  // and if this doesn't work... then we need to just wrongheadedly assume it's UTF-8 so that we can move on - cause this will usually give us most of what we need...
1242
- if ($charset === false)
1243
- {
1244
- if (is_object($debugObject)) {$debugObject->debugLog(2, 'since mb_detect failed - using default of utf-8');}
 
1245
  $charset = 'UTF-8';
1246
  }
1247
  }
1248
 
1249
  // Since CP1252 is a superset, if we get one of it's subsets, we want it instead.
1250
- if ((strtolower($charset) == strtolower('ISO-8859-1')) || (strtolower($charset) == strtolower('Latin1')) || (strtolower($charset) == strtolower('Latin-1')))
1251
- {
1252
- if (is_object($debugObject)) {$debugObject->debugLog(2, 'replacing ' . $charset . ' with CP1252 as its a superset');}
 
1253
  $charset = 'CP1252';
1254
  }
1255
 
1256
- if (is_object($debugObject)) {$debugObject->debugLog(1, 'EXIT - ' . $charset);}
 
 
1257
 
1258
  return $this->_charset = $charset;
1259
  }
@@ -1261,8 +1375,7 @@ class simple_html_dom
1261
  // read tag info
1262
  protected function read_tag()
1263
  {
1264
- if ($this->char!=='<')
1265
- {
1266
  $this->root->_[WG_HDOM_INFO_END] = $this->cursor;
1267
  return false;
1268
  }
@@ -1270,8 +1383,7 @@ class simple_html_dom
1270
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1271
 
1272
  // end tag
1273
- if ($this->char==='/')
1274
- {
1275
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1276
  // This represents the change in the simple_html_dom trunk from revision 180 to 181.
1277
  // $this->skip($this->token_blank_t);
@@ -1279,55 +1391,55 @@ class simple_html_dom
1279
  $tag = $this->copy_until_char('>');
1280
 
1281
  // skip attributes in end tag
1282
- if (($pos = strpos($tag, ' '))!==false)
1283
  $tag = substr($tag, 0, $pos);
 
1284
 
1285
  $parent_lower = strtolower($this->parent->tag);
1286
  $tag_lower = strtolower($tag);
1287
 
1288
- if ($parent_lower!==$tag_lower)
1289
- {
1290
- if (isset($this->optional_closing_tags[$parent_lower]) && isset($this->block_tags[$tag_lower]))
1291
- {
1292
  $this->parent->_[WG_HDOM_INFO_END] = 0;
1293
  $org_parent = $this->parent;
1294
 
1295
- while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower)
1296
  $this->parent = $this->parent->parent;
 
1297
 
1298
  if (strtolower($this->parent->tag)!==$tag_lower) {
1299
  $this->parent = $org_parent; // restore origonal parent
1300
- if ($this->parent->parent) $this->parent = $this->parent->parent;
 
 
1301
  $this->parent->_[WG_HDOM_INFO_END] = $this->cursor;
1302
  return $this->as_text_node($tag);
1303
  }
1304
- }
1305
- else if (($this->parent->parent) && isset($this->block_tags[$tag_lower]))
1306
- {
1307
  $this->parent->_[WG_HDOM_INFO_END] = 0;
1308
  $org_parent = $this->parent;
1309
 
1310
- while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower)
1311
  $this->parent = $this->parent->parent;
 
1312
 
1313
- if (strtolower($this->parent->tag)!==$tag_lower)
1314
- {
1315
  $this->parent = $org_parent; // restore origonal parent
1316
  $this->parent->_[WG_HDOM_INFO_END] = $this->cursor;
1317
  return $this->as_text_node($tag);
1318
  }
1319
- }
1320
- else if (($this->parent->parent) && strtolower($this->parent->parent->tag)===$tag_lower)
1321
- {
1322
  $this->parent->_[WG_HDOM_INFO_END] = 0;
1323
  $this->parent = $this->parent->parent;
1324
- }
1325
- else
1326
  return $this->as_text_node($tag);
 
1327
  }
1328
 
1329
  $this->parent->_[WG_HDOM_INFO_END] = $this->cursor;
1330
- if ($this->parent->parent) $this->parent = $this->parent->parent;
 
 
1331
 
1332
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1333
  return true;
@@ -1350,7 +1462,9 @@ class simple_html_dom
1350
  $node->nodetype = WG_HDOM_TYPE_UNKNOWN;
1351
  $node->tag = 'unknown';
1352
  }
1353
- if ($this->char==='>') $node->_[WG_HDOM_INFO_TEXT].='>';
 
 
1354
  $this->link_nodes($node, true);
1355
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1356
  return true;
@@ -1372,7 +1486,9 @@ class simple_html_dom
1372
  return true;
1373
  }
1374
 
1375
- if ($this->char==='>') $node->_[WG_HDOM_INFO_TEXT].='>';
 
 
1376
  $this->link_nodes($node, false);
1377
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1378
  return true;
@@ -1384,10 +1500,8 @@ class simple_html_dom
1384
  $node->tag = ($this->lowercase) ? $tag_lower : $tag;
1385
 
1386
  // handle optional closing tags
1387
- if (isset($this->optional_closing_tags[$tag_lower]) )
1388
- {
1389
- while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)]))
1390
- {
1391
  $this->parent->_[WG_HDOM_INFO_END] = 0;
1392
  $this->parent = $this->parent->parent;
1393
  }
@@ -1398,15 +1512,12 @@ class simple_html_dom
1398
  $space = array($this->copy_skip($this->token_blank), '', '');
1399
 
1400
  // attributes
1401
- do
1402
- {
1403
- if ($this->char!==null && $space[0]==='')
1404
- {
1405
  //break;
1406
  }
1407
  $name = $this->copy_until($this->token_equal);
1408
- if ($guard===$this->pos)
1409
- {
1410
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1411
  continue;
1412
  }
@@ -1438,45 +1549,46 @@ class simple_html_dom
1438
  if ($name!=='/' && $name!=='') {
1439
  $space[1] = $this->copy_skip($this->token_blank);
1440
  $name = $this->restore_noise($name);
1441
- if ($this->lowercase) $name = strtolower($name);
 
 
1442
  if ($this->char==='=') {
1443
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1444
  $this->parse_attr($node, $name, $space);
1445
- }
1446
- else {
1447
  //no value attr: nowrap, checked selected...
1448
  $node->_[WG_HDOM_INFO_QUOTE][] = WG_HDOM_QUOTE_NO;
1449
  $node->attr[$name] = true;
1450
- if ($this->char!='>') $this->char = $this->doc[--$this->pos]; // prev
 
 
1451
  }
1452
  $node->_[WG_HDOM_INFO_SPACE][] = $space;
1453
  $space = array($this->copy_skip($this->token_blank), '', '');
1454
- }
1455
- else
1456
  break;
 
1457
  } while ($this->char!=='>' && $this->char!=='/');
1458
 
1459
  $this->link_nodes($node, true);
1460
  $node->_[WG_HDOM_INFO_ENDSPACE] = $space[0];
1461
 
1462
  // check self closing
1463
- if ($this->copy_until_char_escape('>')==='/')
1464
- {
1465
  $node->_[WG_HDOM_INFO_ENDSPACE] .= '/';
1466
  $node->_[WG_HDOM_INFO_END] = 0;
1467
- }
1468
- else
1469
- {
1470
  // reset parent
1471
- if (!isset($this->self_closing_tags[strtolower($node->tag)])) $this->parent = $node;
 
 
1472
  }
1473
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1474
 
1475
  // If it's a BR tag, we need to set it's text to the default text.
1476
  // This way when we see it in plaintext, we can generate formatting that the user wants.
1477
  // since a br tag never has sub nodes, this works well.
1478
- if ($node->tag == "br")
1479
- {
1480
  $node->_[WG_HDOM_INFO_INNER] = $this->WG_DEFAULT_BR_TEXT;
1481
  }
1482
 
@@ -1488,8 +1600,7 @@ class simple_html_dom
1488
  {
1489
  // Per sourceforge: http://sourceforge.net/tracker/?func=detail&aid=3061408&group_id=218559&atid=1044037
1490
  // If the attribute is already defined inside a tag, only pay atetntion to the first one as opposed to the last one.
1491
- if (isset($node->attr[$name]))
1492
- {
1493
  return;
1494
  }
1495
 
@@ -1525,8 +1636,7 @@ class simple_html_dom
1525
  {
1526
  $node->parent = $this->parent;
1527
  $this->parent->nodes[] = $node;
1528
- if ($is_child)
1529
- {
1530
  $this->parent->children[] = $node;
1531
  }
1532
  }
@@ -1554,7 +1664,9 @@ class simple_html_dom
1554
  $len = strspn($this->doc, $chars, $pos);
1555
  $this->pos += $len;
1556
  $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1557
- if ($len===0) return '';
 
 
1558
  return substr($this->doc, $pos, $len);
1559
  }
1560
 
@@ -1569,7 +1681,9 @@ class simple_html_dom
1569
 
1570
  protected function copy_until_char($char)
1571
  {
1572
- if ($this->char===null) return '';
 
 
1573
 
1574
  if (($pos = strpos($this->doc, $char, $this->pos))===false) {
1575
  $ret = substr($this->doc, $this->pos, $this->size-$this->pos);
@@ -1578,7 +1692,9 @@ class simple_html_dom
1578
  return $ret;
1579
  }
1580
 
1581
- if ($pos===$this->pos) return '';
 
 
1582
  $pos_old = $this->pos;
1583
  $this->char = $this->doc[$pos];
1584
  $this->pos = $pos;
@@ -1587,20 +1703,22 @@ class simple_html_dom
1587
 
1588
  protected function copy_until_char_escape($char)
1589
  {
1590
- if ($this->char===null) return '';
 
 
1591
 
1592
  $start = $this->pos;
1593
- while (1)
1594
- {
1595
- if (($pos = strpos($this->doc, $char, $start))===false)
1596
- {
1597
  $ret = substr($this->doc, $this->pos, $this->size-$this->pos);
1598
  $this->char = null;
1599
  $this->pos = $this->size;
1600
  return $ret;
1601
  }
1602
 
1603
- if ($pos===$this->pos) return '';
 
 
1604
 
1605
  if ($this->doc[$pos-1]==='\\') {
1606
  $start = $pos+1;
@@ -1619,14 +1737,17 @@ class simple_html_dom
1619
  protected function remove_noise($pattern, $remove_tag=false)
1620
  {
1621
  global $debugObject;
1622
- if (is_object($debugObject)) { $debugObject->debugLogEntry(1); }
 
 
1623
 
1624
  $count = preg_match_all($pattern, $this->doc, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
1625
 
1626
- for ($i=$count-1; $i>-1; --$i)
1627
- {
1628
  $key = '___noise___'.sprintf('% 5d', count($this->noise)+1000);
1629
- if (is_object($debugObject)) { $debugObject->debugLog(2, 'key is: ' . $key); }
 
 
1630
  $idx = ($remove_tag) ? 0 : 1;
1631
  $this->noise[$key] = $matches[$i][$idx][0];
1632
  $this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0]));
@@ -1634,38 +1755,34 @@ class simple_html_dom
1634
 
1635
  // reset the length of content
1636
  $this->size = strlen($this->doc);
1637
- if ($this->size>0)
1638
- {
1639
  $this->char = $this->doc[0];
1640
  }
1641
  }
1642
 
1643
  // restore noise to html content
1644
- function restore_noise($text)
1645
  {
1646
  global $debugObject;
1647
- if (is_object($debugObject)) { $debugObject->debugLogEntry(1); }
 
 
1648
 
1649
- while (($pos=strpos($text, '___noise___'))!==false)
1650
- {
1651
  // Sometimes there is a broken piece of markup, and we don't GET the pos+11 etc... token which indicates a problem outside of us...
1652
- if (strlen($text) > $pos+15)
1653
- {
1654
  $key = '___noise___'.$text[$pos+11].$text[$pos+12].$text[$pos+13].$text[$pos+14].$text[$pos+15];
1655
- if (is_object($debugObject)) { $debugObject->debugLog(2, 'located key of: ' . $key); }
 
 
1656
 
1657
- if (isset($this->noise[$key]))
1658
- {
1659
  $text = substr($text, 0, $pos).$this->noise[$key].substr($text, $pos+16);
1660
- }
1661
- else
1662
- {
1663
  // do this to prevent an infinite loop.
1664
  $text = substr($text, 0, $pos).'UNDEFINED NOISE FOR KEY: '.$key . substr($text, $pos+16);
1665
  }
1666
- }
1667
- else
1668
- {
1669
  // There is no valid key being given back to us... We must get rid of the ___noise___ or we will have a problem.
1670
  $text = substr($text, 0, $pos).'NO NUMERIC NOISE KEY' . substr($text, $pos+11);
1671
  }
@@ -1674,28 +1791,27 @@ class simple_html_dom
1674
  }
1675
 
1676
  // Sometimes we NEED one of the noise elements.
1677
- function search_noise($text)
1678
  {
1679
  global $debugObject;
1680
- if (is_object($debugObject)) { $debugObject->debugLogEntry(1); }
 
 
1681
 
1682
- foreach($this->noise as $noiseElement)
1683
- {
1684
- if (strpos($noiseElement, $text)!==false)
1685
- {
1686
  return $noiseElement;
1687
  }
1688
  }
1689
  }
1690
- function __toString()
1691
  {
1692
  return $this->root->innertext();
1693
  }
1694
 
1695
- function __get($name)
1696
  {
1697
- switch ($name)
1698
- {
1699
  case 'outertext':
1700
  return $this->root->innertext();
1701
  case 'innertext':
@@ -1710,16 +1826,46 @@ class simple_html_dom
1710
  }
1711
 
1712
  // camel naming conventions
1713
- function childNodes($idx=-1) {return $this->root->childNodes($idx);}
1714
- function firstChild() {return $this->root->first_child();}
1715
- function lastChild() {return $this->root->last_child();}
1716
- function createElement($name, $value=null) {return @str_get_html("<$name>$value</$name>")->first_child();}
1717
- function createTextNode($value) {return @end(str_get_html($value)->nodes);}
1718
- function getElementById($id) {return $this->find("#$id", 0);}
1719
- function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);}
1720
- function getElementByTagName($name) {return $this->find($name, 0);}
1721
- function getElementsByTagName($name, $idx=-1) {return $this->find($name, $idx);}
1722
- function loadFile() {$args = func_get_args();$this->load_file($args);}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1723
  }
1724
  }
1725
- ?>
44
  */
45
  define('WG_HDOM_TYPE_ELEMENT', 1);
46
  define('WG_HDOM_TYPE_COMMENT', 2);
47
+ define('WG_HDOM_TYPE_TEXT', 3);
48
+ define('WG_HDOM_TYPE_ENDTAG', 4);
49
+ define('WG_HDOM_TYPE_ROOT', 5);
50
  define('WG_HDOM_TYPE_UNKNOWN', 6);
51
  define('WG_HDOM_QUOTE_DOUBLE', 0);
52
  define('WG_HDOM_QUOTE_SINGLE', 1);
53
+ define('WG_HDOM_QUOTE_NO', 3);
54
+ define('WG_HDOM_INFO_BEGIN', 0);
55
+ define('WG_HDOM_INFO_END', 1);
56
+ define('WG_HDOM_INFO_QUOTE', 2);
57
+ define('WG_HDOM_INFO_SPACE', 3);
58
+ define('WG_HDOM_INFO_TEXT', 4);
59
+ define('WG_HDOM_INFO_INNER', 5);
60
+ define('WG_HDOM_INFO_OUTER', 6);
61
+ define('WG_HDOM_INFO_ENDSPACE', 7);
62
  define('WG_DEFAULT_TARGET_CHARSET', 'UTF-8');
63
  define('WG_DEFAULT_BR_TEXT', "\r\n");
64
  define('WG_DEFAULT_SPAN_TEXT', " ");
75
  $contents = file_get_contents($url, $use_include_path, $context, $offset);
76
  // Paperg - use our own mechanism for getting the contents as we want to control the timeout.
77
  //$contents = retrieve_url_contents($url);
78
+ if (empty($contents) || strlen($contents) > WG_MAX_FILE_SIZE) {
 
79
  return false;
80
  }
81
  // The second parameter can force the selectors to all be lowercase.
87
  function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = WG_DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=WG_DEFAULT_BR_TEXT, $defaultSpanText=WG_DEFAULT_SPAN_TEXT)
88
  {
89
  $dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText);
90
+ if (empty($str) || strlen($str) > WG_MAX_FILE_SIZE) {
 
91
  $dom->clear();
92
  return false;
93
  }
122
  public $tag_start = 0;
123
  private $dom = null;
124
 
125
+ public function __construct($dom)
126
  {
127
  $this->dom = $dom;
128
  $dom->nodes[] = $this;
129
  }
130
 
131
+ public function __destruct()
132
  {
133
  $this->clear();
134
  }
135
 
136
+ public function __toString()
137
  {
138
  return $this->outertext();
139
  }
140
 
141
  // clean up memory due to php5 circular references memory leak...
142
+ public function clear()
143
  {
144
  $this->dom = null;
145
  $this->nodes = null;
148
  }
149
 
150
  // dump node's tree
151
+ public function dump($show_attr=true, $deep=0)
152
  {
153
  $lead = str_repeat(' ', $deep);
154
 
155
  echo $lead.$this->tag;
156
+ if ($show_attr && count($this->attr)>0) {
 
157
  echo '(';
158
+ foreach ($this->attr as $k=>$v) {
159
  echo "[$k]=>\"".$this->$k.'", ';
160
+ }
161
  echo ')';
162
  }
163
  echo "\n";
164
 
165
+ if ($this->nodes) {
166
+ foreach ($this->nodes as $c) {
 
 
167
  $c->dump($show_attr, $deep+1);
168
  }
169
  }
171
 
172
 
173
  // Debugging function to dump a single dom node with a bunch of information about it.
174
+ public function dump_node($echo=true)
175
  {
 
176
  $string = $this->tag;
177
+ if (count($this->attr)>0) {
 
178
  $string .= '(';
179
+ foreach ($this->attr as $k=>$v) {
 
180
  $string .= "[$k]=>\"".$this->$k.'", ';
181
  }
182
  $string .= ')';
183
  }
184
+ if (count($this->_)>0) {
 
185
  $string .= ' $_ (';
186
+ foreach ($this->_ as $k=>$v) {
187
+ if (is_array($v)) {
 
 
188
  $string .= "[$k]=>(";
189
+ foreach ($v as $k2=>$v2) {
 
190
  $string .= "[$k2]=>\"".$v2.'", ';
191
  }
192
  $string .= ")";
197
  $string .= ")";
198
  }
199
 
200
+ if (isset($this->text)) {
 
201
  $string .= " text: (" . $this->text . ")";
202
  }
203
 
204
  $string .= " WG_HDOM_INNER_INFO: '";
205
+ if (isset($node->_[WG_HDOM_INFO_INNER])) {
 
206
  $string .= $node->_[WG_HDOM_INFO_INNER] . "'";
207
+ } else {
 
 
208
  $string .= ' NULL ';
209
  }
210
 
213
  $string .= " tag_start: " . $this->tag_start;
214
  $string .= "\n";
215
 
216
+ if ($echo) {
 
217
  echo $string;
218
  return;
219
+ } else {
 
 
220
  return $string;
221
  }
222
  }
223
 
224
  // returns the parent of node
225
  // If a node is passed in, it will reset the parent of the current node to that one.
226
+ public function parent($parent=null)
227
  {
228
  // I am SURE that this doesn't work properly.
229
  // It fails to unset the current node from it's current parents nodes or children list first.
230
+ if ($parent !== null) {
 
231
  $this->parent = $parent;
232
  $this->parent->nodes[] = $this;
233
  $this->parent->children[] = $this;
237
  }
238
 
239
  // verify that node has children
240
+ public function has_child()
241
  {
242
  return !empty($this->children);
243
  }
244
 
245
  // returns children of node
246
+ public function children($idx=-1)
247
  {
248
+ if ($idx===-1) {
 
249
  return $this->children;
250
  }
251
+ if (isset($this->children[$idx])) {
252
+ return $this->children[$idx];
253
+ }
254
  return null;
255
  }
256
 
257
  // returns the first child of node
258
+ public function first_child()
259
  {
260
+ if (count($this->children)>0) {
 
261
  return $this->children[0];
262
  }
263
  return null;
264
  }
265
 
266
  // returns the last child of node
267
+ public function last_child()
268
  {
269
+ if (($count=count($this->children))>0) {
 
270
  return $this->children[$count-1];
271
  }
272
  return null;
273
  }
274
 
275
  // returns the next sibling of node
276
+ public function next_sibling()
277
  {
278
+ if ($this->parent===null) {
 
279
  return null;
280
  }
281
 
282
  $idx = 0;
283
  $count = count($this->parent->children);
284
+ while ($idx<$count && $this!==$this->parent->children[$idx]) {
 
285
  ++$idx;
286
  }
287
+ if (++$idx>=$count) {
 
288
  return null;
289
  }
290
  return $this->parent->children[$idx];
291
  }
292
 
293
  // returns the previous sibling of node
294
+ public function prev_sibling()
295
  {
296
+ if ($this->parent===null) {
297
+ return null;
298
+ }
299
  $idx = 0;
300
  $count = count($this->parent->children);
301
+ while ($idx<$count && $this!==$this->parent->children[$idx]) {
302
  ++$idx;
303
+ }
304
+ if (--$idx<0) {
305
+ return null;
306
+ }
307
  return $this->parent->children[$idx];
308
  }
309
 
310
  // function to locate a specific ancestor tag in the path to the root.
311
+ public function find_ancestor_tag($tag)
312
  {
313
  global $debugObject;
314
+ if (is_object($debugObject)) {
315
+ $debugObject->debugLogEntry(1);
316
+ }
317
 
318
  // Start by including ourselves in the comparison.
319
  $returnDom = $this;
320
 
321
+ while (!is_null($returnDom)) {
322
+ if (is_object($debugObject)) {
323
+ $debugObject->debugLog(2, "Current tag is: " . $returnDom->tag);
324
+ }
325
 
326
+ if ($returnDom->tag == $tag) {
 
327
  break;
328
  }
329
  $returnDom = $returnDom->parent;
332
  }
333
 
334
  // get dom node's inner html
335
+ public function innertext()
336
  {
337
+ if (isset($this->_[WG_HDOM_INFO_INNER])) {
338
+ return $this->_[WG_HDOM_INFO_INNER];
339
+ }
340
+ if (isset($this->_[WG_HDOM_INFO_TEXT])) {
341
+ return $this->dom->restore_noise($this->_[WG_HDOM_INFO_TEXT]);
342
+ }
343
 
344
  $ret = '';
345
+ foreach ($this->nodes as $n) {
346
  $ret .= $n->outertext();
347
+ }
348
  return $ret;
349
  }
350
 
351
  // get dom node's outer text (with tag)
352
+ public function outertext()
353
  {
354
  global $debugObject;
355
+ if (is_object($debugObject)) {
 
356
  $text = '';
357
+ if ($this->tag == 'text') {
358
+ if (!empty($this->text)) {
 
 
359
  $text = " with text: " . $this->text;
360
  }
361
  }
362
  $debugObject->debugLog(1, 'Innertext of tag: ' . $this->tag . $text);
363
  }
364
 
365
+ if ($this->tag==='root') {
366
+ return $this->innertext();
367
+ }
368
 
369
  // trigger callback
370
+ if ($this->dom && $this->dom->callback!==null) {
 
371
  call_user_func_array($this->dom->callback, array($this));
372
  }
373
 
374
+ if (isset($this->_[WG_HDOM_INFO_OUTER])) {
375
+ return $this->_[WG_HDOM_INFO_OUTER];
376
+ }
377
+ if (isset($this->_[WG_HDOM_INFO_TEXT])) {
378
+ return $this->dom->restore_noise($this->_[WG_HDOM_INFO_TEXT]);
379
+ }
380
 
381
  // render begin tag
382
+ if ($this->dom && $this->dom->nodes[$this->_[WG_HDOM_INFO_BEGIN]]) {
 
383
  $ret = $this->dom->nodes[$this->_[WG_HDOM_INFO_BEGIN]]->makeup();
384
  } else {
385
  $ret = "";
386
  }
387
 
388
  // render inner text
389
+ if (isset($this->_[WG_HDOM_INFO_INNER])) {
 
390
  // If it's a br tag... don't return the WG_HDOM_INNER_INFO that we may or may not have added.
391
+ if ($this->tag != "br") {
 
392
  $ret .= $this->_[WG_HDOM_INFO_INNER];
393
  }
394
  } else {
395
+ if ($this->nodes) {
396
+ foreach ($this->nodes as $n) {
 
 
397
  $ret .= $this->convert_text($n->outertext());
398
  }
399
  }
400
  }
401
 
402
  // render end tag
403
+ if (isset($this->_[WG_HDOM_INFO_END]) && $this->_[WG_HDOM_INFO_END]!=0) {
404
  $ret .= '</'.$this->tag.'>';
405
+ }
406
  return $ret;
407
  }
408
 
409
  // get dom node's plain text
410
+ public function text()
411
  {
412
+ if (isset($this->_[WG_HDOM_INFO_INNER])) {
413
+ return $this->_[WG_HDOM_INFO_INNER];
414
+ }
415
+ switch ($this->nodetype) {
416
  case WG_HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[WG_HDOM_INFO_TEXT]);
417
  case WG_HDOM_TYPE_COMMENT: return '';
418
  case WG_HDOM_TYPE_UNKNOWN: return '';
419
  }
420
+ if (strcasecmp($this->tag, 'script')===0) {
421
+ return '';
422
+ }
423
+ if (strcasecmp($this->tag, 'style')===0) {
424
+ return '';
425
+ }
426
 
427
  $ret = '';
428
  // In rare cases, (always node type 1 or WG_HDOM_TYPE_ELEMENT - observed for some span tags, and some p tags) $this->nodes is set to NULL.
429
  // NOTE: This indicates that there is a problem where it's set to NULL without a clear happening.
430
  // WHY is this happening?
431
+ if (!is_null($this->nodes)) {
432
+ foreach ($this->nodes as $n) {
 
 
433
  $ret .= $this->convert_text($n->text());
434
  }
435
 
436
  // If this node is a span... add a space at the end of it so multiple spans don't run into each other. This is plaintext after all.
437
+ if ($this->tag == "span") {
 
438
  $ret .= $this->dom->WG_DEFAULT_SPAN_TEXT;
439
  }
 
 
440
  }
441
  return $ret;
442
  }
443
 
444
+ public function xmltext()
445
  {
446
  $ret = $this->innertext();
447
  $ret = str_ireplace('<![CDATA[', '', $ret);
450
  }
451
 
452
  // build node's text with tag
453
+ public function makeup()
454
  {
455
  // text, comment, unknown
456
+ if (isset($this->_[WG_HDOM_INFO_TEXT])) {
457
+ return $this->dom->restore_noise($this->_[WG_HDOM_INFO_TEXT]);
458
+ }
459
 
460
  $ret = '<'.$this->tag;
461
  $i = -1;
462
 
463
+ foreach ($this->attr as $key=>$val) {
 
464
  ++$i;
465
 
466
  // skip removed attribute
467
+ if ($val===null || $val===false) {
468
  continue;
469
+ }
470
 
471
  $ret .= $this->_[WG_HDOM_INFO_SPACE][$i][0];
472
  //no value attr: nowrap, checked selected...
473
+ if ($val===true) {
474
  $ret .= $key;
475
+ } else {
476
+ switch ($this->_[WG_HDOM_INFO_QUOTE][$i]) {
 
477
  case WG_HDOM_QUOTE_DOUBLE: $quote = '"'; break;
478
  case WG_HDOM_QUOTE_SINGLE: $quote = '\''; break;
479
  default: $quote = '';
487
 
488
  // find elements by css selector
489
  //PaperG - added ability for find to lowercase the value of the selector.
490
+ public function find($selector, $idx=null, $lowercase=false)
491
  {
492
  $selectors = $this->parse_selector($selector);
493
+ if (($count=count($selectors))===0) {
494
+ return array();
495
+ }
496
  $found_keys = array();
497
 
498
  // find each selector
499
+ for ($c=0; $c<$count; ++$c) {
 
500
  // The change on the below line was documented on the sourceforge code tracker id 2788009
501
  // used to be: if (($levle=count($selectors[0]))===0) return array();
502
+ if (($levle=count($selectors[$c]))===0) {
503
+ return array();
504
+ }
505
+ if (!isset($this->_[WG_HDOM_INFO_BEGIN])) {
506
+ return array();
507
+ }
508
 
509
  $head = array($this->_[WG_HDOM_INFO_BEGIN]=>1);
510
 
511
  // handle descendant selectors, no recursive!
512
+ for ($l=0; $l<$levle; ++$l) {
 
513
  $ret = array();
514
+ foreach ($head as $k=>$v) {
 
515
  $n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k];
516
  //PaperG - Pass this optional parameter on to the seek function.
517
  $n->seek($selectors[$c][$l], $ret, $lowercase);
519
  $head = $ret;
520
  }
521
 
522
+ foreach ($head as $k=>$v) {
523
+ if (!isset($found_keys[$k])) {
 
524
  $found_keys[$k] = 1;
525
+ }
526
  }
527
  }
528
 
530
  ksort($found_keys);
531
 
532
  $found = array();
533
+ foreach ($found_keys as $k=>$v) {
534
  $found[] = $this->dom->nodes[$k];
535
+ }
536
 
537
  // return nth-element or array
538
+ if (is_null($idx)) {
539
+ return $found;
540
+ } elseif ($idx<0) {
541
+ $idx = count($found) + $idx;
542
+ }
543
  return (isset($found[$idx])) ? $found[$idx] : null;
544
  }
545
 
548
  protected function seek($selector, &$ret, $lowercase=false)
549
  {
550
  global $debugObject;
551
+ if (is_object($debugObject)) {
552
+ $debugObject->debugLogEntry(1);
553
+ }
554
 
555
  list($tag, $key, $val, $exp, $no_key) = $selector;
556
 
557
  // xpath index
558
+ if ($tag && $key && is_numeric($key)) {
 
559
  $count = 0;
560
+ foreach ($this->children as $c) {
 
561
  if ($tag==='*' || $tag===$c->tag) {
562
  if (++$count==$key) {
563
  $ret[$c->_[WG_HDOM_INFO_BEGIN]] = 1;
584
  $pass = true;
585
 
586
  if ($tag==='*' && !$key) {
587
+ if (in_array($node, $this->children, true)) {
588
  $ret[$i] = 1;
589
+ }
590
  continue;
591
  }
592
 
593
  // compare tag
594
+ if ($tag && $tag!=$node->tag && $tag!=='*') {
595
+ $pass=false;
596
+ }
597
  // compare key
598
  if ($pass && $key) {
599
  if ($no_key) {
600
+ if (isset($node->attr[$key])) {
601
+ $pass=false;
602
+ }
603
  } else {
604
+ if (($key != "plaintext") && !isset($node->attr[$key])) {
605
+ $pass=false;
606
+ }
607
  }
608
  }
609
  // compare value
616
  // this is a normal search, we want the value of that attribute of the tag.
617
  $nodeKeyValue = $node->attr[$key];
618
  }
619
+ if (is_object($debugObject)) {
620
+ $debugObject->debugLog(2, "testing node: " . $node->tag . " for attribute: " . $key . $exp . $val . " where nodes value is: " . $nodeKeyValue);
621
+ }
622
 
623
  //PaperG - If lowercase is set, do a case insensitive test of the value of the selector.
624
  if ($lowercase) {
626
  } else {
627
  $check = $this->match($exp, $val, $nodeKeyValue);
628
  }
629
+ if (is_object($debugObject)) {
630
+ $debugObject->debugLog(2, "after match: " . ($check ? "true" : "false"));
631
+ }
632
 
633
  // handle multiple class
634
  if (!$check && strcasecmp($key, 'class')===0) {
635
+ foreach (explode(' ', $node->attr[$key]) as $k) {
636
  // Without this, there were cases where leading, trailing, or double spaces lead to our comparing blanks - bad form.
637
  if (!empty($k)) {
638
  if ($lowercase) {
640
  } else {
641
  $check = $this->match($exp, $val, $k);
642
  }
643
+ if ($check) {
644
+ break;
645
+ }
646
  }
647
  }
648
  }
649
+ if (!$check) {
650
+ $pass = false;
651
+ }
652
+ }
653
+ if ($pass) {
654
+ $ret[$i] = 1;
655
  }
 
656
  unset($node);
657
  }
658
  // It's passed by reference so this is actually what this function returns.
659
+ if (is_object($debugObject)) {
660
+ $debugObject->debugLog(1, "EXIT - ret: ", $ret);
661
+ }
662
  }
663
 
664
+ protected function match($exp, $pattern, $value)
665
+ {
666
  global $debugObject;
667
+ if (is_object($debugObject)) {
668
+ $debugObject->debugLogEntry(1);
669
+ }
670
 
671
  switch ($exp) {
672
  case '=':
674
  case '!=':
675
  return ($value!==$pattern);
676
  case '^=':
677
+ return preg_match("/^".preg_quote($pattern, '/')."/", $value);
678
  case '$=':
679
+ return preg_match("/".preg_quote($pattern, '/')."$/", $value);
680
  case '*=':
681
  if ($pattern[0]=='/') {
682
  return preg_match($pattern, $value);
686
  return false;
687
  }
688
 
689
+ protected function parse_selector($selector_string)
690
+ {
691
  global $debugObject;
692
+ if (is_object($debugObject)) {
693
+ $debugObject->debugLogEntry(1);
694
+ }
695
 
696
  // pattern of CSS selectors, modified from mootools
697
  // Paperg: Add the colon to the attrbute, so that it properly finds <tag attr:ibute="something" > like google does.
698
  // Note: if you try to look at this attribute, yo MUST use getAttribute since $dom->x:y will fail the php syntax check.
699
+ // Notice the \[ starting the attbute? and the @? following? This implies that an attribute can begin with an @ sign that is not captured.
700
+ // This implies that an html attribute specifier may start with an @ sign that is NOT captured by the expression.
701
+ // farther study is required to determine of this should be documented or removed.
702
  // $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is";
703
  $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-:]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is";
704
  preg_match_all($pattern, trim($selector_string).' ', $matches, PREG_SET_ORDER);
705
+ if (is_object($debugObject)) {
706
+ $debugObject->debugLog(2, "Matches Array: ", $matches);
707
+ }
708
 
709
  $selectors = array();
710
  $result = array();
712
 
713
  foreach ($matches as $m) {
714
  $m[0] = trim($m[0]);
715
+ if ($m[0]==='' || $m[0]==='/' || $m[0]==='//') {
716
+ continue;
717
+ }
718
  // for browser generated xpath
719
+ if ($m[1]==='tbody') {
720
+ continue;
721
+ }
722
 
723
  list($tag, $key, $val, $exp, $no_key) = array($m[1], null, null, '=', false);
724
+ if (!empty($m[2])) {
725
+ $key='id';
726
+ $val=$m[2];
727
+ }
728
+ if (!empty($m[3])) {
729
+ $key='class';
730
+ $val=$m[3];
731
+ }
732
+ if (!empty($m[4])) {
733
+ $key=$m[4];
734
+ }
735
+ if (!empty($m[5])) {
736
+ $exp=$m[5];
737
+ }
738
+ if (!empty($m[6])) {
739
+ $val=$m[6];
740
+ }
741
 
742
  // convert to lowercase
743
+ if ($this->dom->lowercase) {
744
+ $tag=strtolower($tag);
745
+ $key=strtolower($key);
746
+ }
747
  //elements that do NOT have the specified attribute
748
+ if (isset($key[0]) && $key[0]==='!') {
749
+ $key=substr($key, 1);
750
+ $no_key=true;
751
+ }
752
 
753
  $result[] = array($tag, $key, $val, $exp, $no_key);
754
  if (trim($m[7])===',') {
756
  $result = array();
757
  }
758
  }
759
+ if (count($result)>0) {
760
  $selectors[] = $result;
761
+ }
762
  return $selectors;
763
  }
764
 
765
+ public function __get($name)
766
+ {
767
+ if (isset($this->attr[$name])) {
768
  return $this->convert_text($this->attr[$name]);
769
  }
770
  switch ($name) {
776
  }
777
  }
778
 
779
+ public function __set($name, $value)
780
+ {
781
  switch ($name) {
782
  case 'outertext': return $this->_[WG_HDOM_INFO_OUTER] = $value;
783
  case 'innertext':
784
+ if (isset($this->_[WG_HDOM_INFO_TEXT])) {
785
+ return $this->_[WG_HDOM_INFO_TEXT] = $value;
786
+ }
787
  return $this->_[WG_HDOM_INFO_INNER] = $value;
788
  }
789
  if (!isset($this->attr[$name])) {
793
  $this->attr[$name] = $value;
794
  }
795
 
796
+ public function __isset($name)
797
+ {
798
  switch ($name) {
799
  case 'outertext': return true;
800
  case 'innertext': return true;
804
  return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]);
805
  }
806
 
807
+ public function __unset($name)
808
+ {
809
+ if (isset($this->attr[$name])) {
810
  unset($this->attr[$name]);
811
+ }
812
  }
813
 
814
  // PaperG - Function to convert the text from one character set to another if the two sets are not the same.
815
+ public function convert_text($text)
816
  {
817
  global $debugObject;
818
+ if (is_object($debugObject)) {
819
+ $debugObject->debugLogEntry(1);
820
+ }
821
 
822
  $converted_text = $text;
823
 
824
  $sourceCharset = "";
825
  $targetCharset = "";
826
 
827
+ if ($this->dom) {
 
828
  $sourceCharset = strtoupper($this->dom->_charset);
829
  $targetCharset = strtoupper($this->dom->_target_charset);
830
  }
831
+ if (is_object($debugObject)) {
832
+ $debugObject->debugLog(3, "source charset: " . $sourceCharset . " target charaset: " . $targetCharset);
833
+ }
834
 
835
+ if (!empty($sourceCharset) && !empty($targetCharset) && (strcasecmp($sourceCharset, $targetCharset) != 0)) {
 
836
  // Check if the reported encoding could have been incorrect and the text is actually already UTF-8
837
+ if ((strcasecmp($targetCharset, 'UTF-8') == 0) && ($this->is_utf8($text))) {
 
838
  $converted_text = $text;
839
+ } else {
 
 
840
  $converted_text = iconv($sourceCharset, $targetCharset, $text);
841
  }
842
  }
843
 
844
  // Lets make sure that we don't have that silly BOM issue with any of the utf-8 text we output.
845
+ if ($targetCharset == 'UTF-8') {
846
+ if (substr($converted_text, 0, 3) == "\xef\xbb\xbf") {
 
 
847
  $converted_text = substr($converted_text, 3);
848
  }
849
+ if (substr($converted_text, -3) == "\xef\xbb\xbf") {
 
850
  $converted_text = substr($converted_text, 0, -3);
851
  }
852
  }
860
  * @param mixed $str String to be tested
861
  * @return boolean
862
  */
863
+ public static function is_utf8($str)
864
  {
865
+ $c=0;
866
+ $b=0;
867
  $bits=0;
868
  $len=strlen($str);
869
+ for ($i=0; $i<$len; $i++) {
 
870
  $c=ord($str[$i]);
871
+ if ($c > 128) {
872
+ if (($c >= 254)) {
873
+ return false;
874
+ } elseif ($c >= 252) {
875
+ $bits=6;
876
+ } elseif ($c >= 248) {
877
+ $bits=5;
878
+ } elseif ($c >= 240) {
879
+ $bits=4;
880
+ } elseif ($c >= 224) {
881
+ $bits=3;
882
+ } elseif ($c >= 192) {
883
+ $bits=2;
884
+ } else {
885
+ return false;
886
+ }
887
+ if (($i+$bits) > $len) {
888
+ return false;
889
+ }
890
+ while ($bits > 1) {
891
  $i++;
892
  $b=ord($str[$i]);
893
+ if ($b < 128 || $b > 191) {
894
+ return false;
895
+ }
896
  $bits--;
897
  }
898
  }
915
  * @version April 19 2012
916
  * @return array an array containing the 'height' and 'width' of the image on the page or -1 if we can't figure it out.
917
  */
918
+ public function get_display_size()
919
  {
920
  global $debugObject;
921
 
922
  $width = -1;
923
  $height = -1;
924
 
925
+ if ($this->tag !== 'img') {
 
926
  return false;
927
  }
928
 
929
  // See if there is aheight or width attribute in the tag itself.
930
+ if (isset($this->attr['width'])) {
 
931
  $width = $this->attr['width'];
932
  }
933
 
934
+ if (isset($this->attr['height'])) {
 
935
  $height = $this->attr['height'];
936
  }
937
 
938
  // Now look for an inline style.
939
+ if (isset($this->attr['style'])) {
 
940
  // Thanks to user gnarf from stackoverflow for this regular expression.
941
  $attributes = array();
942
  preg_match_all("/([\w-]+)\s*:\s*([^;]+)\s*;?/", $this->attr['style'], $matches, PREG_SET_ORDER);
943
  foreach ($matches as $match) {
944
+ $attributes[$match[1]] = $match[2];
945
  }
946
 
947
  // If there is a width in the style attributes:
948
+ if (isset($attributes['width']) && $width == -1) {
 
949
  // check that the last two characters are px (pixels)
950
+ if (strtolower(substr($attributes['width'], -2)) == 'px') {
 
951
  $proposed_width = substr($attributes['width'], 0, -2);
952
  // Now make sure that it's an integer and not something stupid.
953
+ if (filter_var($proposed_width, FILTER_VALIDATE_INT)) {
 
954
  $width = $proposed_width;
955
  }
956
  }
957
  }
958
 
959
  // If there is a width in the style attributes:
960
+ if (isset($attributes['height']) && $height == -1) {
 
961
  // check that the last two characters are px (pixels)
962
+ if (strtolower(substr($attributes['height'], -2)) == 'px') {
 
963
  $proposed_height = substr($attributes['height'], 0, -2);
964
  // Now make sure that it's an integer and not something stupid.
965
+ if (filter_var($proposed_height, FILTER_VALIDATE_INT)) {
 
966
  $height = $proposed_height;
967
  }
968
  }
969
  }
 
970
  }
971
 
972
  // Future enhancement:
985
  }
986
 
987
  // camel naming conventions
988
+ public function getAllAttributes()
989
+ {
990
+ return $this->attr;
991
+ }
992
+ public function getAttribute($name)
993
+ {
994
+ return $this->__get($name);
995
+ }
996
+ public function setAttribute($name, $value)
997
+ {
998
+ $this->__set($name, $value);
999
+ }
1000
+ public function hasAttribute($name)
1001
+ {
1002
+ return $this->__isset($name);
1003
+ }
1004
+ public function removeAttribute($name)
1005
+ {
1006
+ $this->__set($name, null);
1007
+ }
1008
+ public function getElementById($id)
1009
+ {
1010
+ return $this->find("#$id", 0);
1011
+ }
1012
+ public function getElementsById($id, $idx=null)
1013
+ {
1014
+ return $this->find("#$id", $idx);
1015
+ }
1016
+ public function getElementByTagName($name)
1017
+ {
1018
+ return $this->find($name, 0);
1019
+ }
1020
+ public function getElementsByTagName($name, $idx=null)
1021
+ {
1022
+ return $this->find($name, $idx);
1023
+ }
1024
+ public function parentNode()
1025
+ {
1026
+ return $this->parent();
1027
+ }
1028
+ public function childNodes($idx=-1)
1029
+ {
1030
+ return $this->children($idx);
1031
+ }
1032
+ public function firstChild()
1033
+ {
1034
+ return $this->first_child();
1035
+ }
1036
+ public function lastChild()
1037
+ {
1038
+ return $this->last_child();
1039
+ }
1040
+ public function nextSibling()
1041
+ {
1042
+ return $this->next_sibling();
1043
+ }
1044
+ public function previousSibling()
1045
+ {
1046
+ return $this->prev_sibling();
1047
+ }
1048
+ public function hasChildNodes()
1049
+ {
1050
+ return $this->has_child();
1051
+ }
1052
+ public function nodeName()
1053
+ {
1054
+ return $this->tag;
1055
+ }
1056
+ public function appendChild($node)
1057
+ {
1058
+ $node->parent($this);
1059
+ return $node;
1060
+ }
1061
  }
1062
 
1063
  /**
1109
  'p'=>array('p'=>1),
1110
  'nobr'=>array('nobr'=>1),
1111
  'b'=>array('b'=>1),
1112
+ 'option'=>array('option'=>1),
1113
  'source'=>array('source'=>1)
1114
  );
1115
 
1116
+ public function __construct($str=null, $lowercase=true, $forceTagsClosed=true, $target_charset=WG_DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=WG_DEFAULT_BR_TEXT, $defaultSpanText=WG_DEFAULT_SPAN_TEXT)
1117
  {
1118
+ if ($str) {
1119
+ if (preg_match("/^http:\/\//i", $str) || is_file($str)) {
 
 
1120
  $this->load_file($str);
1121
+ } else {
 
 
1122
  $this->load($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText);
1123
  }
1124
  }
1129
  $this->_target_charset = $target_charset;
1130
  }
1131
 
1132
+ public function __destruct()
1133
  {
1134
  $this->clear();
1135
  }
1136
 
1137
  // load html from string
1138
+ public function load($str, $lowercase=true, $stripRN=true, $defaultBRText=WG_DEFAULT_BR_TEXT, $defaultSpanText=WG_DEFAULT_SPAN_TEXT)
1139
  {
1140
  global $debugObject;
1141
 
1169
 
1170
  // make load function chainable
1171
  return $this;
 
1172
  }
1173
 
1174
  // load html from file
1175
+ public function load_file()
1176
  {
1177
  $args = func_get_args();
1178
  $this->load(call_user_func_array('file_get_contents', $args), true);
1184
  }
1185
 
1186
  // set callback function
1187
+ public function set_callback($function_name)
1188
  {
1189
  $this->callback = $function_name;
1190
  }
1191
 
1192
  // remove callback function
1193
+ public function remove_callback()
1194
  {
1195
  $this->callback = null;
1196
  }
1197
 
1198
  // save dom as string
1199
+ public function save($filepath='')
1200
  {
1201
  $ret = $this->root->innertext();
1202
+ if ($filepath!=='') {
1203
+ file_put_contents($filepath, $ret, LOCK_EX);
1204
+ }
1205
  return $ret;
1206
  }
1207
 
1208
  // find dom node by css selector
1209
  // Paperg - allow us to specify that we want case insensitive testing of the value of the selector.
1210
+ public function find($selector, $idx=null, $lowercase=false)
1211
  {
1212
  return $this->root->find($selector, $idx, $lowercase);
1213
  }
1214
 
1215
  // clean up memory due to php5 circular references memory leak...
1216
+ public function clear()
1217
  {
1218
+ foreach ($this->nodes as $n) {
1219
+ $n->clear();
1220
+ $n = null;
1221
+ }
1222
  // This add next line is documented in the sourceforge repository. 2977248 as a fix for ongoing memory leaks that occur even with the use of clear.
1223
+ if (isset($this->children)) {
1224
+ foreach ($this->children as $n) {
1225
+ $n->clear();
1226
+ $n = null;
1227
+ }
1228
+ }
1229
+ if (isset($this->parent)) {
1230
+ $this->parent->clear();
1231
+ unset($this->parent);
1232
+ }
1233
+ if (isset($this->root)) {
1234
+ $this->root->clear();
1235
+ unset($this->root);
1236
+ }
1237
  unset($this->doc);
1238
  unset($this->noise);
1239
  }
1240
 
1241
+ public function dump($show_attr=true)
1242
  {
1243
  $this->root->dump($show_attr);
1244
  }
1275
  $this->root->_[WG_HDOM_INFO_BEGIN] = -1;
1276
  $this->root->nodetype = WG_HDOM_TYPE_ROOT;
1277
  $this->parent = $this->root;
1278
+ if ($this->size>0) {
1279
+ $this->char = $this->doc[0];
1280
+ }
1281
  }
1282
 
1283
  // parse html content
1284
  protected function parse()
1285
  {
1286
+ if (($s = $this->copy_until_char('<'))==='') {
 
1287
  return $this->read_tag();
1288
  }
1289
 
1304
 
1305
  $charset = null;
1306
 
1307
+ if (function_exists('get_last_retrieve_url_contents_content_type')) {
 
1308
  $contentTypeHeader = get_last_retrieve_url_contents_content_type();
1309
  $success = preg_match('/charset=(.+)/', $contentTypeHeader, $matches);
1310
+ if ($success) {
 
1311
  $charset = $matches[1];
1312
+ if (is_object($debugObject)) {
1313
+ $debugObject->debugLog(2, 'header content-type found charset of: ' . $charset);
1314
+ }
1315
  }
 
1316
  }
1317
 
1318
+ if (empty($charset)) {
1319
+ $el = $this->root->find('meta[http-equiv=Content-Type]', 0);
1320
+ if (!empty($el)) {
 
 
1321
  $fullvalue = $el->content;
1322
+ if (is_object($debugObject)) {
1323
+ $debugObject->debugLog(2, 'meta content-type tag found' . $fullvalue);
1324
+ }
1325
 
1326
+ if (!empty($fullvalue)) {
 
1327
  $success = preg_match('/charset=(.+)/', $fullvalue, $matches);
1328
+ if ($success) {
 
1329
  $charset = $matches[1];
1330
+ } else {
 
 
1331
  // If there is a meta tag, and they don't specify the character set, research says that it's typically ISO-8859-1
1332
+ if (is_object($debugObject)) {
1333
+ $debugObject->debugLog(2, 'meta content-type tag couldn\'t be parsed. using iso-8859 default.');
1334
+ }
1335
  $charset = 'ISO-8859-1';
1336
  }
1337
  }
1339
  }
1340
 
1341
  // If we couldn't find a charset above, then lets try to detect one based on the text we got...
1342
+ if (empty($charset)) {
 
1343
  // Have php try to detect the encoding from the text given to us.
1344
+ if (function_exists('mb_detect_encoding')) {
1345
+ $charset = mb_detect_encoding($this->root->plaintext . "ascii", $encoding_list = array( "UTF-8", "CP1252" ));
1346
+ }
1347
+ if (is_object($debugObject)) {
1348
+ $debugObject->debugLog(2, 'mb_detect found: ' . $charset);
1349
+ }
1350
 
1351
  // and if this doesn't work... then we need to just wrongheadedly assume it's UTF-8 so that we can move on - cause this will usually give us most of what we need...
1352
+ if ($charset === false) {
1353
+ if (is_object($debugObject)) {
1354
+ $debugObject->debugLog(2, 'since mb_detect failed - using default of utf-8');
1355
+ }
1356
  $charset = 'UTF-8';
1357
  }
1358
  }
1359
 
1360
  // Since CP1252 is a superset, if we get one of it's subsets, we want it instead.
1361
+ if ((strtolower($charset) == strtolower('ISO-8859-1')) || (strtolower($charset) == strtolower('Latin1')) || (strtolower($charset) == strtolower('Latin-1'))) {
1362
+ if (is_object($debugObject)) {
1363
+ $debugObject->debugLog(2, 'replacing ' . $charset . ' with CP1252 as its a superset');
1364
+ }
1365
  $charset = 'CP1252';
1366
  }
1367
 
1368
+ if (is_object($debugObject)) {
1369
+ $debugObject->debugLog(1, 'EXIT - ' . $charset);
1370
+ }
1371
 
1372
  return $this->_charset = $charset;
1373
  }
1375
  // read tag info
1376
  protected function read_tag()
1377
  {
1378
+ if ($this->char!=='<') {
 
1379
  $this->root->_[WG_HDOM_INFO_END] = $this->cursor;
1380
  return false;
1381
  }
1383
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1384
 
1385
  // end tag
1386
+ if ($this->char==='/') {
 
1387
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1388
  // This represents the change in the simple_html_dom trunk from revision 180 to 181.
1389
  // $this->skip($this->token_blank_t);
1391
  $tag = $this->copy_until_char('>');
1392
 
1393
  // skip attributes in end tag
1394
+ if (($pos = strpos($tag, ' '))!==false) {
1395
  $tag = substr($tag, 0, $pos);
1396
+ }
1397
 
1398
  $parent_lower = strtolower($this->parent->tag);
1399
  $tag_lower = strtolower($tag);
1400
 
1401
+ if ($parent_lower!==$tag_lower) {
1402
+ if (isset($this->optional_closing_tags[$parent_lower]) && isset($this->block_tags[$tag_lower])) {
 
 
1403
  $this->parent->_[WG_HDOM_INFO_END] = 0;
1404
  $org_parent = $this->parent;
1405
 
1406
+ while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower) {
1407
  $this->parent = $this->parent->parent;
1408
+ }
1409
 
1410
  if (strtolower($this->parent->tag)!==$tag_lower) {
1411
  $this->parent = $org_parent; // restore origonal parent
1412
+ if ($this->parent->parent) {
1413
+ $this->parent = $this->parent->parent;
1414
+ }
1415
  $this->parent->_[WG_HDOM_INFO_END] = $this->cursor;
1416
  return $this->as_text_node($tag);
1417
  }
1418
+ } elseif (($this->parent->parent) && isset($this->block_tags[$tag_lower])) {
 
 
1419
  $this->parent->_[WG_HDOM_INFO_END] = 0;
1420
  $org_parent = $this->parent;
1421
 
1422
+ while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower) {
1423
  $this->parent = $this->parent->parent;
1424
+ }
1425
 
1426
+ if (strtolower($this->parent->tag)!==$tag_lower) {
 
1427
  $this->parent = $org_parent; // restore origonal parent
1428
  $this->parent->_[WG_HDOM_INFO_END] = $this->cursor;
1429
  return $this->as_text_node($tag);
1430
  }
1431
+ } elseif (($this->parent->parent) && strtolower($this->parent->parent->tag)===$tag_lower) {
 
 
1432
  $this->parent->_[WG_HDOM_INFO_END] = 0;
1433
  $this->parent = $this->parent->parent;
1434
+ } else {
 
1435
  return $this->as_text_node($tag);
1436
+ }
1437
  }
1438
 
1439
  $this->parent->_[WG_HDOM_INFO_END] = $this->cursor;
1440
+ if ($this->parent->parent) {
1441
+ $this->parent = $this->parent->parent;
1442
+ }
1443
 
1444
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1445
  return true;
1462
  $node->nodetype = WG_HDOM_TYPE_UNKNOWN;
1463
  $node->tag = 'unknown';
1464
  }
1465
+ if ($this->char==='>') {
1466
+ $node->_[WG_HDOM_INFO_TEXT].='>';
1467
+ }
1468
  $this->link_nodes($node, true);
1469
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1470
  return true;
1486
  return true;
1487
  }
1488
 
1489
+ if ($this->char==='>') {
1490
+ $node->_[WG_HDOM_INFO_TEXT].='>';
1491
+ }
1492
  $this->link_nodes($node, false);
1493
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1494
  return true;
1500
  $node->tag = ($this->lowercase) ? $tag_lower : $tag;
1501
 
1502
  // handle optional closing tags
1503
+ if (isset($this->optional_closing_tags[$tag_lower])) {
1504
+ while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) {
 
 
1505
  $this->parent->_[WG_HDOM_INFO_END] = 0;
1506
  $this->parent = $this->parent->parent;
1507
  }
1512
  $space = array($this->copy_skip($this->token_blank), '', '');
1513
 
1514
  // attributes
1515
+ do {
1516
+ if ($this->char!==null && $space[0]==='') {
 
 
1517
  //break;
1518
  }
1519
  $name = $this->copy_until($this->token_equal);
1520
+ if ($guard===$this->pos) {
 
1521
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1522
  continue;
1523
  }
1549
  if ($name!=='/' && $name!=='') {
1550
  $space[1] = $this->copy_skip($this->token_blank);
1551
  $name = $this->restore_noise($name);
1552
+ if ($this->lowercase) {
1553
+ $name = strtolower($name);
1554
+ }
1555
  if ($this->char==='=') {
1556
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1557
  $this->parse_attr($node, $name, $space);
1558
+ } else {
 
1559
  //no value attr: nowrap, checked selected...
1560
  $node->_[WG_HDOM_INFO_QUOTE][] = WG_HDOM_QUOTE_NO;
1561
  $node->attr[$name] = true;
1562
+ if ($this->char!='>') {
1563
+ $this->char = $this->doc[--$this->pos];
1564
+ } // prev
1565
  }
1566
  $node->_[WG_HDOM_INFO_SPACE][] = $space;
1567
  $space = array($this->copy_skip($this->token_blank), '', '');
1568
+ } else {
 
1569
  break;
1570
+ }
1571
  } while ($this->char!=='>' && $this->char!=='/');
1572
 
1573
  $this->link_nodes($node, true);
1574
  $node->_[WG_HDOM_INFO_ENDSPACE] = $space[0];
1575
 
1576
  // check self closing
1577
+ if ($this->copy_until_char_escape('>')==='/') {
 
1578
  $node->_[WG_HDOM_INFO_ENDSPACE] .= '/';
1579
  $node->_[WG_HDOM_INFO_END] = 0;
1580
+ } else {
 
 
1581
  // reset parent
1582
+ if (!isset($this->self_closing_tags[strtolower($node->tag)])) {
1583
+ $this->parent = $node;
1584
+ }
1585
  }
1586
  $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1587
 
1588
  // If it's a BR tag, we need to set it's text to the default text.
1589
  // This way when we see it in plaintext, we can generate formatting that the user wants.
1590
  // since a br tag never has sub nodes, this works well.
1591
+ if ($node->tag == "br") {
 
1592
  $node->_[WG_HDOM_INFO_INNER] = $this->WG_DEFAULT_BR_TEXT;
1593
  }
1594
 
1600
  {
1601
  // Per sourceforge: http://sourceforge.net/tracker/?func=detail&aid=3061408&group_id=218559&atid=1044037
1602
  // If the attribute is already defined inside a tag, only pay atetntion to the first one as opposed to the last one.
1603
+ if (isset($node->attr[$name])) {
 
1604
  return;
1605
  }
1606
 
1636
  {
1637
  $node->parent = $this->parent;
1638
  $this->parent->nodes[] = $node;
1639
+ if ($is_child) {
 
1640
  $this->parent->children[] = $node;
1641
  }
1642
  }
1664
  $len = strspn($this->doc, $chars, $pos);
1665
  $this->pos += $len;
1666
  $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; // next
1667
+ if ($len===0) {
1668
+ return '';
1669
+ }
1670
  return substr($this->doc, $pos, $len);
1671
  }
1672
 
1681
 
1682
  protected function copy_until_char($char)
1683
  {
1684
+ if ($this->char===null) {
1685
+ return '';
1686
+ }
1687
 
1688
  if (($pos = strpos($this->doc, $char, $this->pos))===false) {
1689
  $ret = substr($this->doc, $this->pos, $this->size-$this->pos);
1692
  return $ret;
1693
  }
1694
 
1695
+ if ($pos===$this->pos) {
1696
+ return '';
1697
+ }
1698
  $pos_old = $this->pos;
1699
  $this->char = $this->doc[$pos];
1700
  $this->pos = $pos;
1703
 
1704
  protected function copy_until_char_escape($char)
1705
  {
1706
+ if ($this->char===null) {
1707
+ return '';
1708
+ }
1709
 
1710
  $start = $this->pos;
1711
+ while (1) {
1712
+ if (($pos = strpos($this->doc, $char, $start))===false) {
 
 
1713
  $ret = substr($this->doc, $this->pos, $this->size-$this->pos);
1714
  $this->char = null;
1715
  $this->pos = $this->size;
1716
  return $ret;
1717
  }
1718
 
1719
+ if ($pos===$this->pos) {
1720
+ return '';
1721
+ }
1722
 
1723
  if ($this->doc[$pos-1]==='\\') {
1724
  $start = $pos+1;
1737
  protected function remove_noise($pattern, $remove_tag=false)
1738
  {
1739
  global $debugObject;
1740
+ if (is_object($debugObject)) {
1741
+ $debugObject->debugLogEntry(1);
1742
+ }
1743
 
1744
  $count = preg_match_all($pattern, $this->doc, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE);
1745
 
1746
+ for ($i=$count-1; $i>-1; --$i) {
 
1747
  $key = '___noise___'.sprintf('% 5d', count($this->noise)+1000);
1748
+ if (is_object($debugObject)) {
1749
+ $debugObject->debugLog(2, 'key is: ' . $key);
1750
+ }
1751
  $idx = ($remove_tag) ? 0 : 1;
1752
  $this->noise[$key] = $matches[$i][$idx][0];
1753
  $this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0]));
1755
 
1756
  // reset the length of content
1757
  $this->size = strlen($this->doc);
1758
+ if ($this->size>0) {
 
1759
  $this->char = $this->doc[0];
1760
  }
1761
  }
1762
 
1763
  // restore noise to html content
1764
+ public function restore_noise($text)
1765
  {
1766
  global $debugObject;
1767
+ if (is_object($debugObject)) {
1768
+ $debugObject->debugLogEntry(1);
1769
+ }
1770
 
1771
+ while (($pos=strpos($text, '___noise___'))!==false) {
 
1772
  // Sometimes there is a broken piece of markup, and we don't GET the pos+11 etc... token which indicates a problem outside of us...
1773
+ if (strlen($text) > $pos+15) {
 
1774
  $key = '___noise___'.$text[$pos+11].$text[$pos+12].$text[$pos+13].$text[$pos+14].$text[$pos+15];
1775
+ if (is_object($debugObject)) {
1776
+ $debugObject->debugLog(2, 'located key of: ' . $key);
1777
+ }
1778
 
1779
+ if (isset($this->noise[$key])) {
 
1780
  $text = substr($text, 0, $pos).$this->noise[$key].substr($text, $pos+16);
1781
+ } else {
 
 
1782
  // do this to prevent an infinite loop.
1783
  $text = substr($text, 0, $pos).'UNDEFINED NOISE FOR KEY: '.$key . substr($text, $pos+16);
1784
  }
1785
+ } else {
 
 
1786
  // There is no valid key being given back to us... We must get rid of the ___noise___ or we will have a problem.
1787
  $text = substr($text, 0, $pos).'NO NUMERIC NOISE KEY' . substr($text, $pos+11);
1788
  }
1791
  }
1792
 
1793
  // Sometimes we NEED one of the noise elements.
1794
+ public function search_noise($text)
1795
  {
1796
  global $debugObject;
1797
+ if (is_object($debugObject)) {
1798
+ $debugObject->debugLogEntry(1);
1799
+ }
1800
 
1801
+ foreach ($this->noise as $noiseElement) {
1802
+ if (strpos($noiseElement, $text)!==false) {
 
 
1803
  return $noiseElement;
1804
  }
1805
  }
1806
  }
1807
+ public function __toString()
1808
  {
1809
  return $this->root->innertext();
1810
  }
1811
 
1812
+ public function __get($name)
1813
  {
1814
+ switch ($name) {
 
1815
  case 'outertext':
1816
  return $this->root->innertext();
1817
  case 'innertext':
1826
  }
1827
 
1828
  // camel naming conventions
1829
+ public function childNodes($idx=-1)
1830
+ {
1831
+ return $this->root->childNodes($idx);
1832
+ }
1833
+ public function firstChild()
1834
+ {
1835
+ return $this->root->first_child();
1836
+ }
1837
+ public function lastChild()
1838
+ {
1839
+ return $this->root->last_child();
1840
+ }
1841
+ public function createElement($name, $value=null)
1842
+ {
1843
+ return @str_get_html("<$name>$value</$name>")->first_child();
1844
+ }
1845
+ public function createTextNode($value)
1846
+ {
1847
+ return @end(str_get_html($value)->nodes);
1848
+ }
1849
+ public function getElementById($id)
1850
+ {
1851
+ return $this->find("#$id", 0);
1852
+ }
1853
+ public function getElementsById($id, $idx=null)
1854
+ {
1855
+ return $this->find("#$id", $idx);
1856
+ }
1857
+ public function getElementByTagName($name)
1858
+ {
1859
+ return $this->find($name, 0);
1860
+ }
1861
+ public function getElementsByTagName($name, $idx=-1)
1862
+ {
1863
+ return $this->find($name, $idx);
1864
+ }
1865
+ public function loadFile()
1866
+ {
1867
+ $args = func_get_args();
1868
+ $this->load_file($args);
1869
+ }
1870
  }
1871
  }
 
src/Client/WeglotClient.php ADDED
@@ -0,0 +1,727 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace Weglot\Client;
3
+
4
+ use Weglot\Exceptions\WeglotException;
5
+ use Weglot\Third\WooCommerce\WeglotTranslateWoo;
6
+ use WeglotSDP;
7
+
8
+ class WeglotClient
9
+ {
10
+ protected $api_key;
11
+
12
+ const API_BASE = 'https://api.weglot.com';
13
+ const API_BASE_OLD = 'https://weglot.com/api/';
14
+
15
+ public function __construct($key)
16
+ {
17
+ $this->api_key = $key;
18
+
19
+ if ($this->api_key == null || mb_strlen($this->api_key) == 0) {
20
+ return null;
21
+ }
22
+
23
+ $this->initThird();
24
+ }
25
+
26
+ public function initThird() // TODO : Dependency injection
27
+ {
28
+ $this->thirds = array();
29
+
30
+ if (class_exists('WooCommerce')) {
31
+ $this->thirds["woocommerce"] = new WeglotTranslateWoo();
32
+ }
33
+ }
34
+
35
+ public function hasAncestorAttribute($node, $attribute)
36
+ {
37
+ $currentNode = $node;
38
+
39
+ if (isset($currentNode->$attribute)) {
40
+ return true;
41
+ }
42
+
43
+ while ($currentNode->parent() && $currentNode->parent()->tag != 'html') {
44
+ if (isset($currentNode->parent()->$attribute)) {
45
+ return true;
46
+ } else {
47
+ $currentNode = $currentNode->parent();
48
+ }
49
+ }
50
+ return false;
51
+ }
52
+
53
+ public function checkTitle($row)
54
+ {
55
+ return true;
56
+ }
57
+
58
+ public function checkText($row)
59
+ {
60
+ return ($row->parent()->tag != 'script'
61
+ && $row->parent()->tag != 'style'
62
+ && $row->parent()->tag != 'noscript'
63
+ && $row->parent()->tag != 'title'
64
+ && $row->parent()->tag != 'code'
65
+ && ! is_numeric($this->full_trim($row->outertext))
66
+ && ! preg_match('/^\d+%$/', $this->full_trim($row->outertext))
67
+ && strpos($row->outertext, '[vc_') === false);
68
+ }
69
+
70
+ public function checkButton($row)
71
+ {
72
+ return (! is_numeric($this->full_trim($row->value))
73
+ && ! preg_match('/^\d+%$/', $this->full_trim($row->value)));
74
+ }
75
+
76
+ public function checkTd_dt($row)
77
+ {
78
+ return true;
79
+ }
80
+
81
+ public function checkInput_dv($row)
82
+ {
83
+ return true;
84
+ }
85
+
86
+ public function checkInput_dobt($row)
87
+ {
88
+ return true;
89
+ }
90
+
91
+ public function checkRad_obt($row)
92
+ {
93
+ return true;
94
+ }
95
+
96
+
97
+ public function checkPlaceholder($row)
98
+ {
99
+ return (! is_numeric($this->full_trim($row->placeholder))
100
+ && ! preg_match('/^\d+%$/', $this->full_trim($row->placeholder)));
101
+ }
102
+
103
+ public function checkMeta_desc($row)
104
+ {
105
+ return (! is_numeric($this->full_trim($row->placeholder))
106
+ && ! preg_match('/^\d+%$/', $this->full_trim($row->placeholder)));
107
+ }
108
+
109
+ public function checkIframe_src($row)
110
+ {
111
+ return (strpos($this->full_trim($row->src), 'youtube.') !== false);
112
+ }
113
+
114
+ public function checkSource_src($row)
115
+ {
116
+ return true;
117
+ }
118
+
119
+ public function checkImg_src($row)
120
+ {
121
+ return true;
122
+ }
123
+
124
+ public function checkImg_alt($row)
125
+ {
126
+ return true;
127
+ }
128
+
129
+ public function checkA_pdf($row)
130
+ {
131
+ return (
132
+ strtolower(substr($this->full_trim($row->href), -4)) == '.pdf'
133
+ || strtolower(substr($this->full_trim($row->href), -4)) == '.rar'
134
+ || strtolower(substr($this->full_trim($row->href), -4)) == 'docx'
135
+ );
136
+ }
137
+
138
+ public function checkA_title($row)
139
+ {
140
+ return true;
141
+ }
142
+
143
+ public function checkA_dv($row)
144
+ {
145
+ return true;
146
+ }
147
+
148
+ public function checkA_dt($row)
149
+ {
150
+ return true;
151
+ }
152
+
153
+ public function checkA_dto($row)
154
+ {
155
+ return true;
156
+ }
157
+
158
+ public function checkA_dho($row)
159
+ {
160
+ return true;
161
+ }
162
+
163
+ public function checkA_dco($row)
164
+ {
165
+ return true;
166
+ }
167
+
168
+ public function checkA_dte($row)
169
+ {
170
+ return true;
171
+ }
172
+
173
+ public function searchForId($id, $array)
174
+ {
175
+ foreach ($array as $key => $val) {
176
+ if ($val['uid'] === $id) {
177
+ return $key;
178
+ }
179
+ }
180
+ return null;
181
+ }
182
+
183
+ public function ignoreNodes($dom)
184
+ {
185
+ $nodes_to_ignore = array(
186
+ array('<strong>','</strong>'),
187
+ array('<em>','</em>'),
188
+ array('<abbr>','</abbr>'),
189
+ array('<acronym>','</acronym>'),
190
+ array('<b>','</b>'),
191
+ array('<bdo>','</bdo>'),
192
+ array('<big>','</big>'),
193
+ array('<cite>','</cite>'),
194
+ array('<kbd>','</kbd>'),
195
+ array('<q>','</q>'),
196
+ array('<small>','</small>'),
197
+ array('<sub>','</sub>'),
198
+ array('<sup>','</sup>'),
199
+ );
200
+
201
+
202
+ foreach ($nodes_to_ignore as $ignore) {
203
+ $dom = str_replace($ignore[0], htmlentities($ignore[0]), $dom);
204
+ $dom = str_replace($ignore[1], htmlentities($ignore[1]), $dom);
205
+ }
206
+
207
+ return $dom;
208
+ }
209
+
210
+ public function translateDomFromTo($dom, $l_from, $l_to)
211
+ {
212
+ if (strlen($this->api_key) == 36) {
213
+ $dom = $this->ignoreNodes($dom);
214
+ }
215
+
216
+ $html = WeglotSDP\str_get_html($dom, true, true, WG_DEFAULT_TARGET_CHARSET, false, WG_DEFAULT_BR_TEXT, WG_DEFAULT_SPAN_TEXT);
217
+
218
+ $exceptions = explode(',', get_option('exclude_blocks'));
219
+ array_push($exceptions, '#wpadminbar');
220
+ foreach ($exceptions as $exception) {
221
+ foreach ($html->find($exception) as $k => $row) {
222
+ $attribute = 'data-wg-notranslate';
223
+ $row->$attribute = '';
224
+ }
225
+ }
226
+
227
+ $words = array();
228
+ $nodes = array();
229
+
230
+ $elements_to_check = array(
231
+
232
+ 'title'
233
+ => array(
234
+ array(
235
+ 'property' => 'innertext',
236
+ 't' => 4,
237
+ 'type' => 'text',
238
+ ),
239
+ ),
240
+
241
+
242
+ 'meta[name="description"],meta[property="og:title"],meta[property="og:description"],meta[property="og:site_name"],meta[name="twitter:title"],meta[name="twitter:description"]'
243
+ => array(
244
+ array(
245
+ 'property' => 'content',
246
+ 't' => 4,
247
+ 'type' => 'meta_desc',
248
+ ),
249
+ ),
250
+
251
+ 'text'
252
+ => array(
253
+ array(
254
+ 'property' => 'outertext',
255
+ 't' => 1,
256
+ 'type' => 'text',
257
+ ),
258
+ ),
259
+
260
+
261
+ "input[type='submit'],input[type='button'],button"
262
+ => array(
263
+ array(
264
+ 'property' => 'value',
265
+ 't' => 2,
266
+ 'type' => 'button',
267
+ ),
268
+ array(
269
+ 'property' => 'data-value',
270
+ 't' => 1,
271
+ 'type' => 'input_dv',
272
+ ),
273
+ array(
274
+ 'property' => 'data-order_button_text',
275
+ 't' => 1,
276
+ 'type' => 'input_dobt',
277
+ ),
278
+ ),
279
+
280
+ "input[type='radio']"
281
+ => array(
282
+ array(
283
+ 'property' => 'data-order_button_text',
284
+ 't' => 2,
285
+ 'type' => 'rad_obt',
286
+ ),
287
+ ),
288
+
289
+
290
+ "td"
291
+ => array(
292
+ array(
293
+ 'property' => 'data-title',
294
+ 't' => 2,
295
+ 'type' => 'td_dt',
296
+ ),
297
+ ),
298
+
299
+ "input[type=\'text\'],input[type=\'password\'],input[type=\'search\'],input[type=\'email\'],input:not([type]),textarea"
300
+ => array(
301
+ array(
302
+ 'property' => 'placeholder',
303
+ 't' => 3,
304
+ 'type' => 'placeholder',
305
+ ),
306
+ ),
307
+
308
+ 'iframe'
309
+ => array(
310
+ array(
311
+ 'property' => 'src',
312
+ 't' => 5,
313
+ 'type' => 'iframe_src',
314
+ ),
315
+ ),
316
+
317
+ 'img'
318
+ => array(
319
+ array(
320
+ 'property' => 'src',
321
+ 't' => 6,
322
+ 'type' => 'img_src',
323
+ ),
324
+ array(
325
+ 'property' => 'alt',
326
+ 't' => 7,
327
+ 'type' => 'img_alt',
328
+ ),
329
+ ),
330
+
331
+ 'source'
332
+ => array(
333
+ array(
334
+ 'property' => 'src',
335
+ 't' => 5,
336
+ 'type' => 'source_src',
337
+ ),
338
+ ),
339
+
340
+ 'a'
341
+ => array(
342
+ array(
343
+ 'property' => 'href',
344
+ 't' => 8,
345
+ 'type' => 'a_pdf',
346
+ ),
347
+ array(
348
+ 'property' => 'title',
349
+ 't' => 1,
350
+ 'type' => 'a_title',
351
+ ),
352
+ array(
353
+ 'property' => 'data-value',
354
+ 't' => 1,
355
+ 'type' => 'a_dv',
356
+ ),
357
+ array(
358
+ 'property' => 'data-title',
359
+ 't' => 1,
360
+ 'type' => 'a_dt',
361
+ ),
362
+ array(
363
+ 'property' => 'data-tooltip',
364
+ 't' => 1,
365
+ 'type' => 'a_dto',
366
+ ),
367
+ array(
368
+ 'property' => 'data-hover',
369
+ 't' => 1,
370
+ 'type' => 'a_dho',
371
+ ),
372
+ array(
373
+ 'property' => 'data-content',
374
+ 't' => 1,
375
+ 'type' => 'a_dco',
376
+ ),
377
+ array(
378
+ 'property' => 'data-text',
379
+ 't' => 1,
380
+ 'type' => 'a_dte',
381
+ ),
382
+ array(
383
+ 'property' => 'data-avia-tooltip',
384
+ 't' => 1,
385
+ 'type' => 'a_dat'
386
+ )
387
+ ),
388
+ );
389
+
390
+ $elements_to_check = apply_filters("weglot_elements_to_check" , $elements_to_check);
391
+
392
+ foreach ($elements_to_check as $key => $elem) {
393
+ foreach ($html->find($key) as $k => $row) {
394
+ foreach ($elem as $element) {
395
+ $property = $element['property'];
396
+ $t = $element['t'];
397
+ $type = $element['type'];
398
+ $functionName = 'check' . ucfirst($type);
399
+
400
+ if ($this->full_trim($row->$property) != '' && ! $this->hasAncestorAttribute($row, 'data-wg-notranslate')
401
+ && $this->$functionName($row)
402
+ ) {
403
+ array_push(
404
+ $words,
405
+ array(
406
+ 't' => $t,
407
+ 'w' => $row->$property,
408
+ )
409
+ );
410
+ array_push(
411
+ $nodes,
412
+ array(
413
+ 'node' => $row,
414
+ 'type' => $type,
415
+ 'property' => $property,
416
+ )
417
+ );
418
+ }
419
+ }
420
+ }
421
+ }
422
+
423
+
424
+
425
+ $microData = array("description");
426
+ $jsons = array();
427
+ $nbJsonStrings = 0;
428
+ foreach ($html->find('script[type="application/ld+json"]') as $k => $row) {
429
+ $mustAddjson = false;
430
+ $json = json_decode($row->innertext, true);
431
+ if (json_last_error() === JSON_ERROR_NONE) {
432
+ foreach ($microData as $key) {
433
+ $path = explode(">", $key);
434
+ $value = $this->getValue($json, $path);
435
+
436
+ if (isset($value)) {
437
+ $mustAddjson = true;
438
+ $this->addValues($value, $words, $nbJsonStrings);
439
+ }
440
+ }
441
+
442
+ if ($mustAddjson) {
443
+ array_push($jsons, array('node' => $row, 'json' => $json));
444
+ }
445
+ }
446
+ }
447
+
448
+ $countWC18n = 0;
449
+ if (isset($this->thirds["woocommerce"])) {
450
+ $countWC18n = $this->thirds["woocommerce"]->translate($dom, $words); // TODO : Improve countWC18n
451
+ }
452
+
453
+ $title = 'Empty title';
454
+ foreach ($html->find('title') as $k => $row) {
455
+ if ($row->innertext != '') {
456
+ $title = $row->innertext;
457
+ }
458
+ }
459
+
460
+
461
+ $absolute_url = $this->full_url($_SERVER);
462
+ if (strpos($absolute_url, 'admin-ajax.php') !== false) {
463
+ if (isset($_SERVER['HTTP_REFERER'])) {
464
+ $absolute_url = sanitize_text_field(wp_unslash($_SERVER['HTTP_REFERER']));
465
+ }
466
+ $title = 'Ajax data';
467
+ }
468
+
469
+ $bot = $this->bot_detected();
470
+ $parameters = array(
471
+ 'l_from' => $l_from,
472
+ 'l_to' => $l_to,
473
+ 'title' => $title,
474
+ 'request_url' => $absolute_url,
475
+ 'bot' => $bot,
476
+ 'words' => $words,
477
+ );
478
+ $results = $this->doRequest(self::API_BASE . '/translate?api_key=' . $this->api_key, $parameters);
479
+
480
+ $json = json_decode($results, true);
481
+ if (json_last_error() == JSON_ERROR_NONE) {
482
+ $answer = $json;
483
+ if (isset($answer['to_words'])) {
484
+ $translated_words = $answer['to_words'];
485
+ $from_words = $answer['from_words'];
486
+
487
+ if ((count($nodes) + $nbJsonStrings + $countWC18n) == count($translated_words)) {
488
+ for ($i = 0;$i < count($nodes);$i++) {
489
+ $property = $nodes[$i]['property'];
490
+ $type = $nodes[$i]['type'];
491
+
492
+ if ($type == "meta_desc") {
493
+ $nodes[$i]['node']->$property = htmlspecialchars($translated_words[$i]);
494
+ } else {
495
+ $nodes[$i]['node']->$property = $translated_words[$i];
496
+ }
497
+
498
+
499
+ if ($nodes[$i]['type'] == 'img_src') {
500
+ $nodes[$i]['node']->src = $translated_words[$i];
501
+ if ($nodes[$i]['node']->hasAttribute('srcset') && $nodes[$i]['node']->srcset != '' && htmlspecialchars_decode($translated_words[$i]) != htmlspecialchars_decode($words[$i]['w'])) {
502
+ $nodes[$i]['node']->srcset = '';
503
+ }
504
+ }
505
+ }
506
+ $index = count($nodes);
507
+ for ($j = 0;$j < count($jsons);$j++) {
508
+ $jsonArray = $jsons[$j]['json'];
509
+ $node = $jsons[$j]['node'];
510
+ foreach ($microData as $key) {
511
+ $path = explode(">", $key);
512
+ $hasV = $this->getValue($jsonArray, $path);
513
+
514
+ if (isset($hasV)) {
515
+ $this->setValues($jsonArray, $path, $translated_words, $index);
516
+ }
517
+ }
518
+ $node->innertext = json_encode($jsonArray, JSON_PRETTY_PRINT);
519
+ }
520
+
521
+ $dom = $html->save();
522
+
523
+ for ($k = 0; $k < $countWC18n; $k++) {
524
+ $dom = str_replace('\"'.$this->unformatFromApi($from_words[$k + $index + $nbJsonStrings]).'\"', '\"'.$this->unformatFromApi($translated_words[$k + $index + $nbJsonStrings]).'\"', $dom);
525
+ }
526
+
527
+ return $dom;
528
+ } else {
529
+ throw new WeglotException('Unknown error with Weglot Api (0006)');
530
+ }
531
+ } else {
532
+ throw new WeglotException('Unknown error with Weglot Api (0005) Error is: ' . serialize($results));
533
+ }
534
+ } else {
535
+ throw new WeglotException('Error with Weglot Api (0001) : ' . json_last_error() . ' Error is: ' . serialize($results));
536
+ }
537
+ }
538
+
539
+ public function getUserInfo()
540
+ {
541
+ $results = $this->doRequest(self::API_BASE_OLD . 'user-info?api_key=' . $this->api_key, null);
542
+ $json = json_decode($results, true);
543
+ if (json_last_error() == JSON_ERROR_NONE) {
544
+ if (isset($json['succeeded']) && ($json['succeeded'] == 0 || $json['succeeded'] == 1)) {
545
+ if ($json['succeeded'] == 1) {
546
+ if (isset($json['answer'])) {
547
+ $answer = $json['answer'];
548
+ return $answer;
549
+ } else {
550
+ throw new WeglotException('Unknown error with Weglot Api (0004)');
551
+ }
552
+ } else {
553
+ $error = isset($json['error']) ? $json['error'] : 'Unknown error with Weglot Api (0003)';
554
+ throw new WeglotException($error);
555
+ }
556
+ } else {
557
+ throw new WeglotException('Unknown error with Weglot Api (0002) : ' . $json);
558
+ }
559
+ } else {
560
+ throw new WeglotException('Unknown error with Weglot Api (0001) : ' . json_last_error());
561
+ }
562
+ }
563
+
564
+ public function doRequest($url, $parameters)
565
+ {
566
+ if ($parameters) {
567
+ $payload = json_encode($parameters);
568
+ if (json_last_error() == JSON_ERROR_NONE) {
569
+ $response = wp_remote_post(
570
+ $url,
571
+ array(
572
+ 'method' => 'POST',
573
+ 'timeout' => 45,
574
+ 'redirection' => 5,
575
+ 'blocking' => true,
576
+ 'headers' => array(
577
+ 'Content-type' => 'application/json',
578
+ ),
579
+ 'body' => $payload,
580
+ 'cookies' => array(),
581
+ 'sslverify' => false,
582
+ )
583
+ );
584
+ } else {
585
+ throw new WeglotException('Cannot json encode parameters: ' . json_last_error());
586
+ }
587
+ } else {
588
+ $response = wp_remote_get(
589
+ $url,
590
+ array(
591
+ 'method' => 'GET',
592
+ 'timeout' => 45,
593
+ 'redirection' => 5,
594
+ 'blocking' => true,
595
+ 'headers' => array(
596
+ 'Content-type' => 'application/json',
597
+ ),
598
+ 'body' => null,
599
+ 'cookies' => array(),
600
+ 'sslverify' => false,
601
+ )
602
+ );
603
+ }
604
+
605
+ if (is_wp_error($response)) {
606
+ $error_message = $response->get_error_message();
607
+ throw new WeglotException('Error doing the external request to ' . $url . ': ' . $error_message);
608
+ } else {
609
+ return $response['body'];
610
+ }
611
+ }
612
+
613
+
614
+
615
+ public function bot_detected()
616
+ {
617
+ if (isset($_SERVER['HTTP_USER_AGENT'])) {
618
+ $ua = sanitize_text_field(wp_unslash($_SERVER['HTTP_USER_AGENT']));
619
+ }
620
+ if (isset($ua)) {
621
+ if (preg_match('/bot|favicon|crawl|facebook|slurp|spider/i', $ua)) {
622
+ if (strpos($ua, 'Google') !== false || strpos($ua, 'facebook') !== false || strpos($ua, 'wprocketbot') !== false || strpos($ua, 'SemrushBot') !== false) {
623
+ return 2;
624
+ } elseif (strpos($ua, 'bing') !== false) {
625
+ return 3;
626
+ } elseif (strpos($ua, 'yahoo') !== false) {
627
+ return 4;
628
+ } elseif (strpos($ua, 'Baidu') !== false) {
629
+ return 5;
630
+ } elseif (strpos($ua, 'Yandex') !== false) {
631
+ return 6;
632
+ } else {
633
+ return 1;
634
+ }
635
+ } else {
636
+ return 0;
637
+ }
638
+ } else {
639
+ return 1;
640
+ }
641
+ }
642
+
643
+
644
+ public function addValues($value, &$words, &$nbJsonStrings)
645
+ {
646
+ if (is_array($value)) {
647
+ foreach ($value as $key => $val) {
648
+ $this->addValues($val, $words, $nbJsonStrings);
649
+ }
650
+ } else {
651
+ array_push(
652
+ $words,
653
+ array(
654
+ 't' => 1,
655
+ 'w' => $value,
656
+ )
657
+ );
658
+ $nbJsonStrings++;
659
+ }
660
+ }
661
+
662
+ public function setValues(&$data, $path, $translatedwords, &$index)
663
+ {
664
+ $temp = &$data;
665
+ foreach ($path as $key) {
666
+ if (array_key_exists($key, $temp)) {
667
+ $temp = &$temp[$key];
668
+ } else {
669
+ return null;
670
+ }
671
+ }
672
+
673
+ if (is_array($temp)) {
674
+ foreach ($temp as $key => &$val) {
675
+ $this->setValues($val, null, $translatedwords, $index) ;
676
+ }
677
+ } else {
678
+ $temp = $translatedwords[$index];
679
+ $index++;
680
+ }
681
+ }
682
+
683
+ public function getValue($data, $path)
684
+ {
685
+ $temp = $data;
686
+ foreach ($path as $key) {
687
+ if (array_key_exists($key, $temp)) {
688
+ $temp = $temp[$key];
689
+ } else {
690
+ return null;
691
+ }
692
+ }
693
+ return $temp ;
694
+ }
695
+
696
+ public function formatForApi($string)
697
+ {
698
+ $string = '"'.$string.'"';
699
+ return json_decode(str_replace('\\/', '/', str_replace('\\\\', '\\', $string)));
700
+ }
701
+
702
+ public function unformatFromApi($string)
703
+ {
704
+ $string = str_replace('"', '', str_replace('/', '\\\\/', str_replace('\\u', '\\\\u', json_encode($string))));
705
+ return $string;
706
+ }
707
+
708
+ public function url_origin($s, $use_forwarded_host = false)
709
+ {
710
+ $ssl = (! empty($s['HTTPS']) && $s['HTTPS'] == 'on') ? true : false;
711
+ $sp = strtolower($s['SERVER_PROTOCOL']);
712
+ $protocol = substr($sp, 0, strpos($sp, '/')) . (($ssl) ? 's' : '');
713
+ $port = $s['SERVER_PORT'];
714
+ $port = ((! $ssl && $port == '80') || ($ssl && $port == '443')) ? '' : ':' . $port;
715
+ $host = ($use_forwarded_host && isset($s['HTTP_X_FORWARDED_HOST'])) ? $s['HTTP_X_FORWARDED_HOST'] : (isset($s['HTTP_HOST']) ? $s['HTTP_HOST'] : null);
716
+ $host = isset($host) ? $host : $s['SERVER_NAME'] . $port;
717
+ return $protocol . '://' . $host;
718
+ }
719
+ public function full_url($s, $use_forwarded_host = false)
720
+ {
721
+ return $this->url_origin($s, $use_forwarded_host) . $s['REQUEST_URI'];
722
+ }
723
+ public function full_trim($word)
724
+ {
725
+ return trim($word, " \t\n\r\0\x0B\xA0�");
726
+ }
727
+ }
src/Exceptions/WeglotException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Weglot\Exceptions;
4
+
5
+ class WeglotException extends \Exception
6
+ {
7
+ }
src/Helpers/WeglotLang.php ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Weglot\Helpers;
4
+
5
+ abstract class WeglotLang
6
+ {
7
+ public static function getCodeLangs()
8
+ {
9
+ return array(
10
+ 'af',
11
+ 'hw',
12
+ 'sq',
13
+ 'am',
14
+ 'ar',
15
+ 'hy',
16
+ 'az',
17
+ 'ba',
18
+ 'eu',
19
+ 'be',
20
+ 'bn',
21
+ 'bs',
22
+ 'bg',
23
+ 'my',
24
+ 'ca',
25
+ 'ny',
26
+ 'zh',
27
+ 'tw',
28
+ 'co',
29
+ 'hr',
30
+ 'cs',
31
+ 'da',
32
+ 'nl',
33
+ 'en',
34
+ 'eo',
35
+ 'et',
36
+ 'fj',
37
+ 'fi',
38
+ 'fr',
39
+ 'fl',
40
+ 'gl',
41
+ 'ka',
42
+ 'de',
43
+ 'el',
44
+ 'gu',
45
+ 'ht',
46
+ 'ha',
47
+ 'he',
48
+ 'hi',
49
+ 'hu',
50
+ 'is',
51
+ 'ig',
52
+ 'id',
53
+ 'ga',
54
+ 'it',
55
+ 'ja',
56
+ 'jv',
57
+ 'kn',
58
+ 'kk',
59
+ 'km',
60
+ 'ko',
61
+ 'ku',
62
+ 'ky',
63
+ 'lo',
64
+ 'la',
65
+ 'lv',
66
+ 'lt',
67
+ 'lb',
68
+ 'mk',
69
+ 'mg',
70
+ 'ms',
71
+ 'ml',
72
+ 'mt',
73
+ 'mi',
74
+ 'mr',
75
+ 'mn',
76
+ 'ne',
77
+ 'no',
78
+ 'ps',
79
+ 'fa',
80
+ 'pl',
81
+ 'pt',
82
+ 'pa',
83
+ 'ro',
84
+ 'ru',
85
+ 'sm',
86
+ 'gd',
87
+ 'sr',
88
+ 'sn',
89
+ 'sd',
90
+ 'si',
91
+ 'sk',
92
+ 'sl',
93
+ 'so',
94
+ 'st',
95
+ 'es',
96
+ 'su',
97
+ 'sw',
98
+ 'sv',
99
+ 'tl',
100
+ 'ty',
101
+ 'tg',
102
+ 'ta',
103
+ 'tt',
104
+ 'te',
105
+ 'th',
106
+ 'to',
107
+ 'tr',
108
+ 'uk',
109
+ 'ur',
110
+ 'uz',
111
+ 'vi',
112
+ 'cy',
113
+ 'fy',
114
+ 'xh',
115
+ 'yi',
116
+ 'yo',
117
+ 'zu',
118
+ );
119
+ }
120
+
121
+ public static function getStrLangs()
122
+ {
123
+ return array(
124
+ 'af' => __('Afrikaans', 'weglot'),
125
+ 'sq' => __('Albanian', 'weglot'),
126
+ 'am' => __('Amharic', 'weglot'),
127
+ 'ar' => __('Arabic', 'weglot'),
128
+ 'hy' => __('Armenian', 'weglot'),
129
+ 'az' => __('Azerbaijani', 'weglot'),
130
+ 'ba' => __('Bashkir', 'weglot'),
131
+ 'eu' => __('Basque', 'weglot'),
132
+ 'be' => __('Belarusian', 'weglot'),
133
+ 'bn' => __('Bengali', 'weglot'),
134
+ 'bs' => __('Bosnian', 'weglot'),
135
+ 'bg' => __('Bulgarian', 'weglot'),
136
+ 'my' => __('Burmese', 'weglot'),
137
+ 'ca' => __('Catalan', 'weglot'),
138
+ 'ny' => __('Chichewa', 'weglot'),
139
+ 'zh' => __('Chinese', 'weglot'),
140
+ 'tw' => __('Chinese', 'weglot'),
141
+ 'co' => __('Corsican', 'weglot'),
142
+ 'hr' => __('Croatian', 'weglot'),
143
+ 'cs' => __('Czech', 'weglot'),
144
+ 'da' => __('Danish', 'weglot'),
145
+ 'nl' => __('Dutch', 'weglot'),
146
+ 'en' => __('English', 'weglot'),
147
+ 'eo' => __('Esperanto', 'weglot'),
148
+ 'et' => __('Estonian', 'weglot'),
149
+ 'fj' => __('Fijian', 'weglot'),
150
+ 'fi' => __('Finnish', 'weglot'),
151
+ 'fl' => __('Filipino', 'weglot'),
152
+ 'fr' => __('French', 'weglot'),
153
+ 'gl' => __('Galician', 'weglot'),
154
+ 'ka' => __('Georgian', 'weglot'),
155
+ 'de' => __('German', 'weglot'),
156
+ 'el' => __('Greek', 'weglot'),
157
+ 'gu' => __('Gujarati', 'weglot'),
158
+ 'ht' => __('Haitian', 'weglot'),
159
+ 'ha' => __('Hausa', 'weglot'),
160
+ 'hw' => __('Hawaiann', 'weglot'),
161
+ 'he' => __('Hebrew', 'weglot'),
162
+ 'hi' => __('Hindi', 'weglot'),
163
+ 'hu' => __('Hungarian', 'weglot'),
164
+ 'is' => __('Icelandic', 'weglot'),
165
+ 'ig' => __('Igbo', 'weglot'),
166
+ 'id' => __('Indonesian', 'weglot'),
167
+ 'ga' => __('Irish', 'weglot'),
168
+ 'it' => __('Italian', 'weglot'),
169
+ 'ja' => __('Japanese', 'weglot'),
170
+ 'jv' => __('Javanese', 'weglot'),
171
+ 'kn' => __('Kannada', 'weglot'),
172
+ 'kk' => __('Kazakh', 'weglot'),
173
+ 'km' => __('Khmer', 'weglot'),
174
+ 'ko' => __('Korean', 'weglot'),
175
+ 'ku' => __('Kurdish', 'weglot'),
176
+ 'ky' => __('Kyrgyz', 'weglot'),
177
+ 'lo' => __('Lao', 'weglot'),
178
+ 'la' => __('Latin', 'weglot'),
179
+ 'lv' => __('Latvian', 'weglot'),
180
+ 'lt' => __('Lithuanian', 'weglot'),
181
+ 'lb' => __('Luxembourgish', 'weglot'),
182
+ 'mk' => __('Macedonian', 'weglot'),
183
+ 'mg' => __('Malagasy', 'weglot'),
184
+ 'ms' => __('Malay', 'weglot'),
185
+ 'ml' => __('Malayalam', 'weglot'),
186
+ 'mt' => __('Maltese', 'weglot'),
187
+ 'mi' => __('Māori', 'weglot'),
188
+ 'mr' => __('Marathi', 'weglot'),
189
+ 'mn' => __('Mongolian', 'weglot'),
190
+ 'ne' => __('Nepali', 'weglot'),
191
+ 'no' => __('Norwegian', 'weglot'),
192
+ 'ps' => __('Pashto', 'weglot'),
193
+ 'fa' => __('Persian', 'weglot'),
194
+ 'pl' => __('Polish', 'weglot'),
195
+ 'pt' => __('Portuguese', 'weglot'),
196
+ 'pa' => __('Punjabi', 'weglot'),
197
+ 'ro' => __('Romanian', 'weglot'),
198
+ 'ru' => __('Russian', 'weglot'),
199
+ 'sm' => __('Samoan', 'weglot'),
200
+ 'gd' => __('Gaelic', 'weglot'),
201
+ 'sr' => __('Serbian', 'weglot'),
202
+ 'sn' => __('Shona', 'weglot'),
203
+ 'sd' => __('Sindhi', 'weglot'),
204
+ 'si' => __('Sinhalese', 'weglot'),
205
+ 'sk' => __('Slovak', 'weglot'),
206
+ 'sl' => __('Slovenian', 'weglot'),
207
+ 'so' => __('Somali', 'weglot'),
208
+ 'st' => __('Sotho', 'weglot'),
209
+ 'es' => __('Spanish', 'weglot'),
210
+ 'su' => __('Sundanese', 'weglot'),
211
+ 'sw' => __('Swahili', 'weglot'),
212
+ 'sv' => __('Swedish', 'weglot'),
213
+ 'tl' => __('Tagalog', 'weglot'),
214
+ 'ty' => __('Tahitian', 'weglot'),
215
+ 'tg' => __('Tajik', 'weglot'),
216
+ 'ta' => __('Tamil', 'weglot'),
217
+ 'tt' => __('Tatar', 'weglot'),
218
+ 'te' => __('Telugu', 'weglot'),
219
+ 'th' => __('Thai', 'weglot'),
220
+ 'to' => __('Tongan', 'weglot'),
221
+ 'tr' => __('Turkish', 'weglot'),
222
+ 'uk' => __('Ukrainian', 'weglot'),
223
+ 'ur' => __('Urdu', 'weglot'),
224
+ 'uz' => __('Uzbek', 'weglot'),
225
+ 'vi' => __('Vietnamese', 'weglot'),
226
+ 'cy' => __('Welsh', 'weglot'),
227
+ 'fy' => __('Frisian', 'weglot'),
228
+ 'xh' => __('Xhosa', 'weglot'),
229
+ 'yi' => __('Yiddish', 'weglot'),
230
+ 'yo' => __('Yoruba', 'weglot'),
231
+ 'zu' => __('Zulu', 'weglot'),
232
+ );
233
+ }
234
+
235
+ public static function getStrLangByCode($code)
236
+ {
237
+ $langs = self::getStrLangs();
238
+ return (array_key_exists($code, $langs)) ? $langs[$code] : "";
239
+ }
240
+ }
src/Helpers/WeglotUrl.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Weglot\Helpers;
4
+
5
+ abstract class WeglotUrl {
6
+ public static function isEligibleURL($url) // Change this in another helper and remove static
7
+
8
+ {
9
+ $url = urldecode(self::URLToRelative($url));
10
+ //Format exclude URL
11
+ $excludeURL = get_option('exclude_url'); // Too dependecy WP
12
+
13
+ if (!empty($excludeURL)) {
14
+ $excludeURL = preg_replace('#\s+#', ',', trim($excludeURL));
15
+
16
+ $excludedUrls = explode(',', $excludeURL);
17
+ foreach ($excludedUrls as &$ex_url) {
18
+ $ex_url = self::URLToRelative($ex_url);
19
+ }
20
+ $excludeURL = implode(',', $excludedUrls);
21
+ }
22
+
23
+ $exclusions = preg_replace('#\s+#', ',', $excludeURL);
24
+
25
+ $listRegex = explode(',', $exclusions);
26
+
27
+ $excludeAmp = apply_filters("weglot_exclude_amp", true); // Too dependecy WP
28
+
29
+ if ($excludeAmp) {
30
+ $listRegex[] = apply_filters('weglot_regex_amp', '([&,\?,/])?amp(/)?');
31
+ }
32
+
33
+ if (empty($exclusions)) {
34
+ return true;
35
+ }
36
+
37
+ foreach ($listRegex as $regex) {
38
+ $str = self::escapeSlash($regex);
39
+ $prepareRegex = sprintf('/%s/', $str);
40
+ if (preg_match($prepareRegex, $url) === 1) {
41
+ return false;
42
+ }
43
+ }
44
+
45
+ return true;
46
+ }
47
+
48
+ public static function escapeSlash($str) // Change this in another helper and remove static
49
+
50
+ {
51
+ return str_replace('/', '\/', $str);
52
+ }
53
+
54
+ public static function URLToRelative($url) // Change this in another helper and remove static
55
+ {
56
+ if ((substr($url, 0, 7) == 'http://') || (substr($url, 0, 8) == 'https://')) {
57
+ // the current link is an "absolute" URL - parse it to get just the path
58
+ $parsed = parse_url($url);
59
+ $path = isset($parsed['path']) ? $parsed['path'] : '';
60
+ $query = isset($parsed['query']) ? '?' . $parsed['query'] : '';
61
+ $fragment = isset($parsed['fragment']) ? '#' . $parsed['fragment'] : '';
62
+
63
+ if (self::getHomeDirectory()) {
64
+ $relative = str_replace(self::getHomeDirectory(), '', $path);
65
+
66
+ return ($relative == '') ? '/' : $relative;
67
+ } else {
68
+ return $path . $query . $fragment;
69
+ }
70
+ }
71
+ return $url;
72
+ }
73
+
74
+ /** Returns the subdirectories where WP is installed
75
+ *
76
+ * returns /directories if there is one
77
+ * return empty string otherwise
78
+ *
79
+ */
80
+ public static function getHomeDirectory()
81
+ {
82
+ if(isset(self::$home_dir)){
83
+ return self::$home_dir;
84
+ }
85
+
86
+ $opt_siteurl = trim(get_option('siteurl'), '/');
87
+ $opt_home = trim(get_option('home'), '/');
88
+ if ($opt_siteurl != '' && $opt_home != '') {
89
+ if ((substr($opt_home, 0, 7) == 'http://' && strpos(substr($opt_home, 7), '/') !== false) || (substr($opt_home, 0, 8) == 'https://' && strpos(substr($opt_home, 8), '/') !== false)) {
90
+ $parsed_url = parse_url($opt_home);
91
+ $path = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
92
+ self::$home_dir = $path;
93
+ return $path;
94
+ }
95
+ }
96
+ return null;
97
+ }
98
+
99
+ }
WGUtils.php → src/Helpers/WeglotUtils.php RENAMED
@@ -1,9 +1,12 @@
1
  <?php
2
 
3
- class WGUtils {
4
 
5
- public static function getLangNameFromCode( $code, $english ) {
6
- switch ( $code ) {
 
 
 
7
  case "af":
8
  return $english ? "Afrikaans" : "Afrikaans";
9
  case "sq":
@@ -58,6 +61,8 @@ class WGUtils {
58
  return $english ? "Estonian" : "Eesti";
59
  case "fj":
60
  return $english ? "Fijian" : "Fidžin";
 
 
61
  case "fi":
62
  return $english ? "Finnish" : "Suomi";
63
  case "fr":
@@ -76,6 +81,8 @@ class WGUtils {
76
  return $english ? "Haitian" : "Kreyòl ayisyen";
77
  case "ha":
78
  return $english ? "Hausa" : "Hausa";
 
 
79
  case "he":
80
  return $english ? "Hebrew" : "עברית";
81
  case "hi":
@@ -216,76 +223,85 @@ class WGUtils {
216
  return $english ? "Yoruba" : "Yorùbá";
217
  case "zu":
218
  return $english ? "Zulu" : "isiZulu";
219
- }
220
- }
221
 
222
- public static function str_lreplace( $search, $replace, $subject ) {
223
- $pos = strrpos( $subject, $search );
 
224
 
225
- if ( $pos !== false ) {
226
- $subject = substr_replace( $subject, $replace, $pos, strlen( $search ) );
227
- }
228
- return $subject;
229
- }
230
 
231
- public static function is_HTML( $string ) {
232
- return ((preg_match( '/<head/',$string,$m ) != 0) && ! (preg_match( '/<xsl/',$string,$m ) != 0));
233
- }
 
234
 
235
- public static function is_AJAX_HTML( $string ) {
236
- $r = preg_match_all( '/<(a|div|span|p|i|aside|input|textarea|select|h1|h2|h3|h4|meta|button|form|li|strong|ul)/',$string,$m,PREG_PATTERN_ORDER );
237
- if ( $string[0] != '{' && $r && $r >= 2 ) {
238
- return true;
239
- } else {
240
- return false;
241
- }
242
- }
 
 
243
 
244
- public static function endsWith( $haystack, $needle ) {
245
- // search forward starting from end minus needle length characters
246
- return $needle === '' || (($temp = strlen( $haystack ) - strlen( $needle )) >= 0 && strpos( $haystack, $needle, $temp ) !== false);
247
- }
 
 
248
 
249
- public static function isLanguageRTL( $code ) {
250
- $rtls = array( 'ar', 'he', 'fa' );
251
- if ( in_array( $code,$rtls ) ) {
252
- return true;
253
- }
254
- return false;
255
- }
 
 
256
 
257
- public static function hasLanguageRTL( $arrayOfCode ) {
258
- foreach ( $arrayOfCode as $code ) {
259
- if ( WGUtils::isLanguageRTL( $code ) ) {
260
- return true;
261
- }
262
- }
263
- return false;
264
- }
265
 
266
- public static function hasLanguageLTR( $arrayOfCode ) {
267
- foreach ( $arrayOfCode as $code ) {
268
- if ( ! WGUtils::isLanguageRTL( $code ) ) {
269
- return true;
270
- }
271
- }
272
- return false;
273
- }
 
274
 
275
 
276
- public static function is_bot() {
277
- $ua = array_key_exists( 'HTTP_USER_AGENT',$_SERVER ) ? sanitize_text_field(
278
- wp_unslash( $_SERVER['HTTP_USER_AGENT'] )
279
- ) : 'Unknown';
280
- if ( isset( $ua ) ) {
281
- if ( preg_match( '/bot|favicon|crawl|facebook|Face|slurp|spider/i', $ua ) ) {
282
- return true;
283
-
284
- } else {
285
- return false;
286
- }
287
- } else {
288
- return true;
289
- }
290
- }
291
  }
1
  <?php
2
 
3
+ namespace Weglot\Helpers;
4
 
5
+ class WeglotUtils
6
+ {
7
+ public static function getLangNameFromCode($code, $english)
8
+ {
9
+ switch ($code) {
10
  case "af":
11
  return $english ? "Afrikaans" : "Afrikaans";
12
  case "sq":
61
  return $english ? "Estonian" : "Eesti";
62
  case "fj":
63
  return $english ? "Fijian" : "Fidžin";
64
+ case "fl":
65
+ return $english ? "Filipino" : "Filipino";
66
  case "fi":
67
  return $english ? "Finnish" : "Suomi";
68
  case "fr":
81
  return $english ? "Haitian" : "Kreyòl ayisyen";
82
  case "ha":
83
  return $english ? "Hausa" : "Hausa";
84
+ case "hw":
85
+ return $english ? "Hawaiann" : "Hawaiann";
86
  case "he":
87
  return $english ? "Hebrew" : "עברית";
88
  case "hi":
223
  return $english ? "Yoruba" : "Yorùbá";
224
  case "zu":
225
  return $english ? "Zulu" : "isiZulu";
226
+ }
227
+ }
228
 
229
+ public static function str_lreplace($search, $replace, $subject)
230
+ {
231
+ $pos = strrpos($subject, $search);
232
 
233
+ if ($pos !== false) {
234
+ $subject = substr_replace($subject, $replace, $pos, strlen($search));
235
+ }
236
+ return $subject;
237
+ }
238
 
239
+ public static function is_HTML($string)
240
+ {
241
+ return ((preg_match('/<head/', $string, $m) != 0) && !(preg_match('/<xsl/', $string, $m) != 0));
242
+ }
243
 
244
+ public static function is_AJAX_HTML($string)
245
+ {
246
+ $r = preg_match_all('/<(a|div|span|p|i|aside|input|textarea|select|h1|h2|h3|h4|meta|button|form|li|strong|ul)/',
247
+ $string, $m, PREG_PATTERN_ORDER);
248
+ if (isset($string[0]) && $string[0] != '{' && $r && $r >= 2) {
249
+ return true;
250
+ } else {
251
+ return false;
252
+ }
253
+ }
254
 
255
+ public static function endsWith($haystack, $needle)
256
+ {
257
+ // search forward starting from end minus needle length characters
258
+ return $needle === '' || (($temp = strlen($haystack) - strlen($needle)) >= 0 && strpos($haystack, $needle,
259
+ $temp) !== false);
260
+ }
261
 
262
+ public static function hasLanguageRTL($arrayOfCode)
263
+ {
264
+ foreach ($arrayOfCode as $code) {
265
+ if (self::isLanguageRTL($code)) {
266
+ return true;
267
+ }
268
+ }
269
+ return false;
270
+ }
271
 
272
+ public static function isLanguageRTL($code)
273
+ {
274
+ $rtls = array('ar', 'he', 'fa');
275
+ if (in_array($code, $rtls)) {
276
+ return true;
277
+ }
278
+ return false;
279
+ }
280
 
281
+ public static function hasLanguageLTR($arrayOfCode)
282
+ {
283
+ foreach ($arrayOfCode as $code) {
284
+ if (!self::isLanguageRTL($code)) {
285
+ return true;
286
+ }
287
+ }
288
+ return false;
289
+ }
290
 
291
 
292
+ public static function is_bot()
293
+ {
294
+ $ua = array_key_exists('HTTP_USER_AGENT', $_SERVER) ? sanitize_text_field(
295
+ wp_unslash($_SERVER['HTTP_USER_AGENT'])
296
+ ) : 'Unknown';
297
+ if (isset($ua)) {
298
+ if (preg_match('/bot|favicon|crawl|facebook|Face|slurp|spider/i', $ua)) {
299
+ return true;
300
+ } else {
301
+ return false;
302
+ }
303
+ } else {
304
+ return true;
305
+ }
306
+ }
307
  }
src/Models/TranslateInterface.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Weglot\Models;
4
+
5
+ interface TranslateInterface
6
+ {
7
+ public function translate($html, &$words);
8
+ }
src/Notices/AdminNotices.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Weglot\Notices;
4
+
5
+ class AdminNotices
6
+ {
7
+ public function wgExceededFreeLimit()
8
+ {
9
+ add_action('admin_notices', array($this, 'wgExceededFreeLimitNotice'), 0);
10
+ }
11
+
12
+ /**
13
+ * @see wgExceededFreeLimit
14
+ */
15
+ protected function wgExceededFreeLimitNotice()
16
+ {
17
+ ?>
18
+ <div class="updated settings-error notice is-dismissible">
19
+ <p><?php echo sprintf(esc_html__('Weglot Translate is not active because you have exceeded the free limit. Please %1$supgrade your plan%2$s if you want to keep the service running.', 'weglot'), '<a target="_blank" href="https://weglot.com/change-plan">', '</a>'); ?></p>
20
+ </div>
21
+ <?php
22
+ }
23
+
24
+ public function wgRequireRewriteModule()
25
+ {
26
+ add_action('admin_notices', array($this, 'wgRequireRewriteModuleNotice'), 0);
27
+ }
28
+
29
+ /**
30
+ * @see wgRequireRewriteModule
31
+ */
32
+ protected function wgRequireRewriteModuleNotice()
33
+ {
34
+ ?>
35
+ <div class="error settings-error notice is-dismissible">
36
+ <p><?php echo sprintf(esc_html__('Weglot Translate: You need to activate the mod_rewrite module. You can find more information here : %1$sUsing Permalinks%2$s. If you need help, just ask us directly at support@weglot.com.', 'weglot'), '<a target="_blank" href="https://codex.wordpress.org/Using_Permalinks">', '</a>'); ?></p>
37
+ </div>
38
+ <?php
39
+ }
40
+
41
+ public function wgNeedConfiguration()
42
+ {
43
+ add_action('admin_notices', array($this, 'wgNeedConfigurationNotice'), 0);
44
+ }
45
+
46
+ /**
47
+ * @see wgNeedConfiguration
48
+ */
49
+ public function wgNeedConfigurationNotice()
50
+ {
51
+ ?>
52
+ <div class="error settings-error notice is-dismissible">
53
+ <p><?php echo sprintf(esc_html__('Weglot Translate is installed but not yet configured, you need to configure Weglot here : %1$sWeglot configuration page%2$s. The configuration takes only 1 minute! ', 'weglot'), '<a href="'.admin_url().'admin.php?page=Weglot">', '</a>'); ?></p>
54
+ </div>
55
+ <?php
56
+ }
57
+
58
+ public function thirdNotices()
59
+ {
60
+ add_action('admin_notices', array($this, 'wgGtranslateNotice'), 0);
61
+ }
62
+
63
+ public function hasGTranslatePlugin() // Not single responsability
64
+ {
65
+ return is_plugin_active('gtranslate/gtranslate.php');
66
+ }
67
+
68
+
69
+ public function wgGtranslateNotice()
70
+ {
71
+ if (!$this->hasGTranslatePlugin()) {
72
+ return;
73
+ }
74
+
75
+
76
+ $screen = get_current_screen();
77
+
78
+ if ($screen->id === "toplevel_page_Weglot") {
79
+ return;
80
+ }
81
+
82
+ $pluginFile = 'gtranslate/gtranslate.php';
83
+ $deactivateLink = wp_nonce_url('plugins.php?action=deactivate&amp;plugin='.urlencode($pluginFile).'&amp;plugin_status=all&amp;paged=1&amp;s=', 'deactivate-plugin_' . $pluginFile)
84
+
85
+ ?>
86
+ <div class="error settings-error notice is-dismissible">
87
+ <p><?php echo sprintf(esc_html__('Please %1$sdeactivate GTranslate%2$s. This plugin causes conflicts with Weglot.', 'weglot'), '<a href="'.$deactivateLink.'">', '</a>'); ?></p>
88
+ </div>
89
+ <?php
90
+ }
91
+ }
src/Third/WooCommerce/WeglotTranslateWoo.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Weglot\Third\WooCommerce;
4
+
5
+ use Weglot\Models\TranslateInterface;
6
+
7
+ class WeglotTranslateWoo implements TranslateInterface
8
+ {
9
+ public function translate($html, &$words)
10
+ {
11
+ $countTranslate = 0;
12
+ $countTranslate += $this->addWCLabels($html, $words);
13
+
14
+ return $countTranslate;
15
+ }
16
+
17
+ public function addWCLabels($html, &$words)
18
+ {
19
+ $count = 0;
20
+
21
+ preg_match('#wc_address_i18n_params(.*?);#', $html, $match);
22
+ if (!isset($match[1])) {
23
+ return $count;
24
+ }
25
+
26
+ preg_match_all('#(label|placeholder)\\\":\\\"(.*?)\\\"#', $match[1], $all);
27
+
28
+ $allWords = $all[2];
29
+
30
+ foreach ($allWords as $value) {
31
+ $value = $this->formatForApi($value);
32
+ array_push(
33
+ $words,
34
+ array(
35
+ 't' => 1,
36
+ 'w' => $value,
37
+ )
38
+ );
39
+ $count++;
40
+ }
41
+
42
+ return $count;
43
+ }
44
+
45
+ public function formatForApi($string) // TODO : Refactoring in a service
46
+ {
47
+ $string = '"'.$string.'"';
48
+ return json_decode(str_replace('\\/', '/', str_replace('\\\\', '\\', $string)));
49
+ }
50
+ }
src/Third/Yoast/RedirectHandler.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Weglot\Third\Yoast;
4
+
5
+ use Weglot\Helpers\WeglotLang;
6
+ use Weglot\Helpers\WeglotUrl;
7
+
8
+ /**
9
+ * Override Yoast Premium
10
+ */
11
+ class RedirectHandler extends \WPSEO_Redirect_Handler{
12
+
13
+ /**
14
+ * The options where the URL redirects are stored.
15
+ *
16
+ * @var string
17
+ */
18
+ private $normal_option_name = 'wpseo-premium-redirects-export-plain';
19
+
20
+ /**
21
+ * The option name where the regex redirects are stored.
22
+ *
23
+ * @var string
24
+ */
25
+ private $regex_option_name = 'wpseo-premium-redirects-export-regex';
26
+
27
+ /**
28
+ * The URL that is called at the moment.
29
+ *
30
+ * @var string
31
+ */
32
+ protected $request_url = '';
33
+
34
+ public function load() {
35
+
36
+ // Only handle the redirect when the option for php redirects is enabled.
37
+ if ( ! $this->load_php_redirects() ) {
38
+ return;
39
+ }
40
+
41
+ // Set the requested URL.
42
+ $this->set_request_url();
43
+
44
+ // Check the normal redirects.
45
+ $this->handle_normal_redirects( $this->request_url );
46
+
47
+ do_action("weglot_another_redirect_override", $this->request_url);
48
+ }
49
+
50
+ protected function set_request_url() {
51
+ $this->request_url = $this->get_request_uri();
52
+ }
53
+
54
+ /**
55
+ * Checks if the current URL matches a normal redirect.
56
+ *
57
+ * @param string $request_url The request url to look for.
58
+ *
59
+ * @return void
60
+ */
61
+ protected function handle_normal_redirects( $request_url ) {
62
+ // Setting the redirects.
63
+ $redirects = $this->get_redirects( $this->normal_option_name );
64
+ $this->redirects = $this->normalize_redirects( $redirects );
65
+
66
+ // Trim the slashes, to match the variants of a request URL (Like: url, /url, /url/, url/).
67
+ if ( $request_url !== '/' ) {
68
+ $request_url = trim( $request_url, '/' );
69
+ }
70
+
71
+ $redirect_url = "";
72
+
73
+ if(isset($request_url[2]) && $request_url[2] === "/"){
74
+ $codeLanguage = explode("/", $request_url);
75
+
76
+ $langs = WeglotLang::getCodeLangs();
77
+ if(!in_array($codeLanguage[0], $langs)){ // Default behavior Yoast
78
+ $redirect_url = $this->find_url( $request_url );
79
+ }
80
+ else{
81
+ $redirect_url = str_replace($codeLanguage[0] . "/", "", $request_url);
82
+ $redirect_url = $this->find_url( $redirect_url );
83
+
84
+ if(!empty($redirect_url)){ // If find URL redirect on Yoast
85
+
86
+ // Prepare Eligible URL from Yoast
87
+ $eligibleUrl = $redirect_url["url"];
88
+ if($eligibleUrl[0] !== "/"){
89
+ $eligibleUrl = "/" . $eligibleUrl;
90
+ }
91
+ if(substr($eligibleUrl, -1) !== "/"){
92
+ $eligibleUrl .= "/";
93
+ }
94
+
95
+ if(WeglotUrl::isEligibleURL($eligibleUrl)){
96
+ $redirect_url["url"] = sprintf("%s/%s", $codeLanguage[0], $redirect_url["url"]);
97
+ }
98
+
99
+ }
100
+ }
101
+ }
102
+
103
+ // Get the URL and doing the redirect.
104
+ if ( ! empty( $redirect_url ) ) {
105
+ $this->is_redirected = true;
106
+ $this->do_redirect( $redirect_url['url'], $redirect_url['type'] );
107
+ }
108
+ }
109
+
110
+ }
vendor/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit22b676e0f36abfbf19cdf3636d910ced::getLoader();
vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,445 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
17
+ *
18
+ * $loader = new \Composer\Autoload\ClassLoader();
19
+ *
20
+ * // register classes with namespaces
21
+ * $loader->add('Symfony\Component', __DIR__.'/component');
22
+ * $loader->add('Symfony', __DIR__.'/framework');
23
+ *
24
+ * // activate the autoloader
25
+ * $loader->register();
26
+ *
27
+ * // to enable searching the include path (eg. for PEAR packages)
28
+ * $loader->setUseIncludePath(true);
29
+ *
30
+ * In this example, if you try to use a class in the Symfony\Component
31
+ * namespace or one of its children (Symfony\Component\Console for instance),
32
+ * the autoloader will first look for the class under the component/
33
+ * directory, and it will then fallback to the framework/ directory if not
34
+ * found before giving up.
35
+ *
36
+ * This class is loosely based on the Symfony UniversalClassLoader.
37
+ *
38
+ * @author Fabien Potencier <fabien@symfony.com>
39
+ * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see http://www.php-fig.org/psr/psr-0/
41
+ * @see http://www.php-fig.org/psr/psr-4/
42
+ */
43
+ class ClassLoader
44
+ {
45
+ // PSR-4
46
+ private $prefixLengthsPsr4 = array();
47
+ private $prefixDirsPsr4 = array();
48
+ private $fallbackDirsPsr4 = array();
49
+
50
+ // PSR-0
51
+ private $prefixesPsr0 = array();
52
+ private $fallbackDirsPsr0 = array();
53
+
54
+ private $useIncludePath = false;
55
+ private $classMap = array();
56
+ private $classMapAuthoritative = false;
57
+ private $missingClasses = array();
58
+ private $apcuPrefix;
59
+
60
+ public function getPrefixes()
61
+ {
62
+ if (!empty($this->prefixesPsr0)) {
63
+ return call_user_func_array('array_merge', $this->prefixesPsr0);
64
+ }
65
+
66
+ return array();
67
+ }
68
+
69
+ public function getPrefixesPsr4()
70
+ {
71
+ return $this->prefixDirsPsr4;
72
+ }
73
+
74
+ public function getFallbackDirs()
75
+ {
76
+ return $this->fallbackDirsPsr0;
77
+ }
78
+
79
+ public function getFallbackDirsPsr4()
80
+ {
81
+ return $this->fallbackDirsPsr4;
82
+ }
83
+
84
+ public function getClassMap()
85
+ {
86
+ return $this->classMap;
87
+ }
88
+
89
+ /**
90
+ * @param array $classMap Class to filename map
91
+ */
92
+ public function addClassMap(array $classMap)
93
+ {
94
+ if ($this->classMap) {
95
+ $this->classMap = array_merge($this->classMap, $classMap);
96
+ } else {
97
+ $this->classMap = $classMap;
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Registers a set of PSR-0 directories for a given prefix, either
103
+ * appending or prepending to the ones previously set for this prefix.
104
+ *
105
+ * @param string $prefix The prefix
106
+ * @param array|string $paths The PSR-0 root directories
107
+ * @param bool $prepend Whether to prepend the directories
108
+ */
109
+ public function add($prefix, $paths, $prepend = false)
110
+ {
111
+ if (!$prefix) {
112
+ if ($prepend) {
113
+ $this->fallbackDirsPsr0 = array_merge(
114
+ (array) $paths,
115
+ $this->fallbackDirsPsr0
116
+ );
117
+ } else {
118
+ $this->fallbackDirsPsr0 = array_merge(
119
+ $this->fallbackDirsPsr0,
120
+ (array) $paths
121
+ );
122
+ }
123
+
124
+ return;
125
+ }
126
+
127
+ $first = $prefix[0];
128
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
129
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
130
+
131
+ return;
132
+ }
133
+ if ($prepend) {
134
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
135
+ (array) $paths,
136
+ $this->prefixesPsr0[$first][$prefix]
137
+ );
138
+ } else {
139
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
140
+ $this->prefixesPsr0[$first][$prefix],
141
+ (array) $paths
142
+ );
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Registers a set of PSR-4 directories for a given namespace, either
148
+ * appending or prepending to the ones previously set for this namespace.
149
+ *
150
+ * @param string $prefix The prefix/namespace, with trailing '\\'
151
+ * @param array|string $paths The PSR-4 base directories
152
+ * @param bool $prepend Whether to prepend the directories
153
+ *
154
+ * @throws \InvalidArgumentException
155
+ */
156
+ public function addPsr4($prefix, $paths, $prepend = false)
157
+ {
158
+ if (!$prefix) {
159
+ // Register directories for the root namespace.
160
+ if ($prepend) {
161
+ $this->fallbackDirsPsr4 = array_merge(
162
+ (array) $paths,
163
+ $this->fallbackDirsPsr4
164
+ );
165
+ } else {
166
+ $this->fallbackDirsPsr4 = array_merge(
167
+ $this->fallbackDirsPsr4,
168
+ (array) $paths
169
+ );
170
+ }
171
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
172
+ // Register directories for a new namespace.
173
+ $length = strlen($prefix);
174
+ if ('\\' !== $prefix[$length - 1]) {
175
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
176
+ }
177
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
178
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
179
+ } elseif ($prepend) {
180
+ // Prepend directories for an already registered namespace.
181
+ $this->prefixDirsPsr4[$prefix] = array_merge(
182
+ (array) $paths,
183
+ $this->prefixDirsPsr4[$prefix]
184
+ );
185
+ } else {
186
+ // Append directories for an already registered namespace.
187
+ $this->prefixDirsPsr4[$prefix] = array_merge(
188
+ $this->prefixDirsPsr4[$prefix],
189
+ (array) $paths
190
+ );
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Registers a set of PSR-0 directories for a given prefix,
196
+ * replacing any others previously set for this prefix.
197
+ *
198
+ * @param string $prefix The prefix
199
+ * @param array|string $paths The PSR-0 base directories
200
+ */
201
+ public function set($prefix, $paths)
202
+ {
203
+ if (!$prefix) {
204
+ $this->fallbackDirsPsr0 = (array) $paths;
205
+ } else {
206
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
207
+ }
208
+ }
209
+
210
+ /**
211
+ * Registers a set of PSR-4 directories for a given namespace,
212
+ * replacing any others previously set for this namespace.
213
+ *
214
+ * @param string $prefix The prefix/namespace, with trailing '\\'
215
+ * @param array|string $paths The PSR-4 base directories
216
+ *
217
+ * @throws \InvalidArgumentException
218
+ */
219
+ public function setPsr4($prefix, $paths)
220
+ {
221
+ if (!$prefix) {
222
+ $this->fallbackDirsPsr4 = (array) $paths;
223
+ } else {
224
+ $length = strlen($prefix);
225
+ if ('\\' !== $prefix[$length - 1]) {
226
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
227
+ }
228
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
229
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
230
+ }
231
+ }
232
+
233
+ /**
234
+ * Turns on searching the include path for class files.
235
+ *
236
+ * @param bool $useIncludePath
237
+ */
238
+ public function setUseIncludePath($useIncludePath)
239
+ {
240
+ $this->useIncludePath = $useIncludePath;
241
+ }
242
+
243
+ /**
244
+ * Can be used to check if the autoloader uses the include path to check
245
+ * for classes.
246
+ *
247
+ * @return bool
248
+ */
249
+ public function getUseIncludePath()
250
+ {
251
+ return $this->useIncludePath;
252
+ }
253
+
254
+ /**
255
+ * Turns off searching the prefix and fallback directories for classes
256
+ * that have not been registered with the class map.
257
+ *
258
+ * @param bool $classMapAuthoritative
259
+ */
260
+ public function setClassMapAuthoritative($classMapAuthoritative)
261
+ {
262
+ $this->classMapAuthoritative = $classMapAuthoritative;
263
+ }
264
+
265
+ /**
266
+ * Should class lookup fail if not found in the current class map?
267
+ *
268
+ * @return bool
269
+ */
270
+ public function isClassMapAuthoritative()
271
+ {
272
+ return $this->classMapAuthoritative;
273
+ }
274
+
275
+ /**
276
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
277
+ *
278
+ * @param string|null $apcuPrefix
279
+ */
280
+ public function setApcuPrefix($apcuPrefix)
281
+ {
282
+ $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
283
+ }
284
+
285
+ /**
286
+ * The APCu prefix in use, or null if APCu caching is not enabled.
287
+ *
288
+ * @return string|null
289
+ */
290
+ public function getApcuPrefix()
291
+ {
292
+ return $this->apcuPrefix;
293
+ }
294
+
295
+ /**
296
+ * Registers this instance as an autoloader.
297
+ *
298
+ * @param bool $prepend Whether to prepend the autoloader or not
299
+ */
300
+ public function register($prepend = false)
301
+ {
302
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
303
+ }
304
+
305
+ /**
306
+ * Unregisters this instance as an autoloader.
307
+ */
308
+ public function unregister()
309
+ {
310
+ spl_autoload_unregister(array($this, 'loadClass'));
311
+ }
312
+
313
+ /**
314
+ * Loads the given class or interface.
315
+ *
316
+ * @param string $class The name of the class
317
+ * @return bool|null True if loaded, null otherwise
318
+ */
319
+ public function loadClass($class)
320
+ {
321
+ if ($file = $this->findFile($class)) {
322
+ includeFile($file);
323
+
324
+ return true;
325
+ }
326
+ }
327
+
328
+ /**
329
+ * Finds the path to the file where the class is defined.
330
+ *
331
+ * @param string $class The name of the class
332
+ *
333
+ * @return string|false The path if found, false otherwise
334
+ */
335
+ public function findFile($class)
336
+ {
337
+ // class map lookup
338
+ if (isset($this->classMap[$class])) {
339
+ return $this->classMap[$class];
340
+ }
341
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
342
+ return false;
343
+ }
344
+ if (null !== $this->apcuPrefix) {
345
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
346
+ if ($hit) {
347
+ return $file;
348
+ }
349
+ }
350
+
351
+ $file = $this->findFileWithExtension($class, '.php');
352
+
353
+ // Search for Hack files if we are running on HHVM
354
+ if (false === $file && defined('HHVM_VERSION')) {
355
+ $file = $this->findFileWithExtension($class, '.hh');
356
+ }
357
+
358
+ if (null !== $this->apcuPrefix) {
359
+ apcu_add($this->apcuPrefix.$class, $file);
360
+ }
361
+
362
+ if (false === $file) {
363
+ // Remember that this class does not exist.
364
+ $this->missingClasses[$class] = true;
365
+ }
366
+
367
+ return $file;
368
+ }
369
+
370
+ private function findFileWithExtension($class, $ext)
371
+ {
372
+ // PSR-4 lookup
373
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
374
+
375
+ $first = $class[0];
376
+ if (isset($this->prefixLengthsPsr4[$first])) {
377
+ $subPath = $class;
378
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
379
+ $subPath = substr($subPath, 0, $lastPos);
380
+ $search = $subPath.'\\';
381
+ if (isset($this->prefixDirsPsr4[$search])) {
382
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
383
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
384
+ if (file_exists($file = $dir . $pathEnd)) {
385
+ return $file;
386
+ }
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ // PSR-4 fallback dirs
393
+ foreach ($this->fallbackDirsPsr4 as $dir) {
394
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
395
+ return $file;
396
+ }
397
+ }
398
+
399
+ // PSR-0 lookup
400
+ if (false !== $pos = strrpos($class, '\\')) {
401
+ // namespaced class name
402
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
403
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
404
+ } else {
405
+ // PEAR-like class name
406
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
407
+ }
408
+
409
+ if (isset($this->prefixesPsr0[$first])) {
410
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
411
+ if (0 === strpos($class, $prefix)) {
412
+ foreach ($dirs as $dir) {
413
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
414
+ return $file;
415
+ }
416
+ }
417
+ }
418
+ }
419
+ }
420
+
421
+ // PSR-0 fallback dirs
422
+ foreach ($this->fallbackDirsPsr0 as $dir) {
423
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
424
+ return $file;
425
+ }
426
+ }
427
+
428
+ // PSR-0 include paths.
429
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
430
+ return $file;
431
+ }
432
+
433
+ return false;
434
+ }
435
+ }
436
+
437
+ /**
438
+ * Scope isolated include.
439
+ *
440
+ * Prevents access to $this/self from included files.
441
+ */
442
+ function includeFile($file)
443
+ {
444
+ include $file;
445
+ }
vendor/composer/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copyright (c) Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'Weglot\\' => array($baseDir . '/src'),
10
+ );
vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit22b676e0f36abfbf19cdf3636d910ced
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ public static function getLoader()
17
+ {
18
+ if (null !== self::$loader) {
19
+ return self::$loader;
20
+ }
21
+
22
+ spl_autoload_register(array('ComposerAutoloaderInit22b676e0f36abfbf19cdf3636d910ced', 'loadClassLoader'), true, true);
23
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit22b676e0f36abfbf19cdf3636d910ced', 'loadClassLoader'));
25
+
26
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
27
+ if ($useStaticLoader) {
28
+ require_once __DIR__ . '/autoload_static.php';
29
+
30
+ call_user_func(\Composer\Autoload\ComposerStaticInit22b676e0f36abfbf19cdf3636d910ced::getInitializer($loader));
31
+ } else {
32
+ $map = require __DIR__ . '/autoload_namespaces.php';
33
+ foreach ($map as $namespace => $path) {
34
+ $loader->set($namespace, $path);
35
+ }
36
+
37
+ $map = require __DIR__ . '/autoload_psr4.php';
38
+ foreach ($map as $namespace => $path) {
39
+ $loader->setPsr4($namespace, $path);
40
+ }
41
+
42
+ $classMap = require __DIR__ . '/autoload_classmap.php';
43
+ if ($classMap) {
44
+ $loader->addClassMap($classMap);
45
+ }
46
+ }
47
+
48
+ $loader->register(true);
49
+
50
+ return $loader;
51
+ }
52
+ }
vendor/composer/autoload_static.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInit22b676e0f36abfbf19cdf3636d910ced
8
+ {
9
+ public static $prefixLengthsPsr4 = array (
10
+ 'W' =>
11
+ array (
12
+ 'Weglot\\' => 7,
13
+ ),
14
+ );
15
+
16
+ public static $prefixDirsPsr4 = array (
17
+ 'Weglot\\' =>
18
+ array (
19
+ 0 => __DIR__ . '/../..' . '/src',
20
+ ),
21
+ );
22
+
23
+ public static function getInitializer(ClassLoader $loader)
24
+ {
25
+ return \Closure::bind(function () use ($loader) {
26
+ $loader->prefixLengthsPsr4 = ComposerStaticInit22b676e0f36abfbf19cdf3636d910ced::$prefixLengthsPsr4;
27
+ $loader->prefixDirsPsr4 = ComposerStaticInit22b676e0f36abfbf19cdf3636d910ced::$prefixDirsPsr4;
28
+
29
+ }, null, ClassLoader::class);
30
+ }
31
+ }
vendor/composer/installed.json ADDED
@@ -0,0 +1 @@
 
1
+ []
weglot.php CHANGED
@@ -1,7 +1,7 @@
1
  <?php
2
  /**
3
  * @package Weglot
4
- * @version 1.10
5
  */
6
 
7
  /*
@@ -12,7 +12,7 @@ Author: Weglot Translate team
12
  Author URI: https://weglot.com/
13
  Text Domain: weglot
14
  Domain Path: /languages/
15
- Version: 1.10
16
  */
17
 
18
  /*
@@ -36,35 +36,53 @@ Version: 1.10
36
  * Exit if absolute path
37
  */
38
 
39
- if ( ! defined( 'ABSPATH' ) ) {
40
  exit;
41
  }
42
 
43
 
 
 
 
 
 
 
44
 
 
 
 
45
 
 
 
 
 
46
 
 
 
 
 
47
 
48
- define( 'WEGLOT_VERSION', '1.10' );
49
- define( 'WEGLOT_DIR', dirname( __FILE__ ) );
50
- define( 'WEGLOT_BNAME', plugin_basename( __FILE__ ) );
51
- define( 'WEGLOT_DIRURL', plugin_dir_url( __FILE__ ) );
52
- define( 'WEGLOT_INC', WEGLOT_DIR . '/includes' );
53
- define( 'WEGLOT_RESURL', WEGLOT_DIRURL . 'resources/' );
 
 
54
 
 
 
 
 
 
 
55
 
56
- /**
57
- * Load our files. Could do an autoloader here but for now, there is only 4 files.
58
- */
59
- require WEGLOT_DIR . '/WeglotPHPClient/weglot.php';
60
- require WEGLOT_DIR . '/simple_html_dom.php';
61
- require WEGLOT_DIR . '/WGUtils.php';
62
- require WEGLOT_DIR . '/WeglotWidget.php';
63
 
64
  /**
65
  * Singleton class Weglot */
66
- class Weglot {
67
-
68
  private $original_l;
69
  private $destination_l;
70
 
@@ -81,245 +99,236 @@ class Weglot {
81
  *
82
  * @since 0.1
83
  */
84
- private function __construct() {
 
 
 
 
85
 
86
- if ( version_compare( phpversion(), '5.3.0', '<' ) ) {
87
- add_action( 'admin_notices', array( &$this, 'wg_admin_notice2' ),0 );
88
  return;
89
  }
90
 
91
- if ( function_exists( 'apache_get_modules' ) && ! in_array( 'mod_rewrite', apache_get_modules() ) ) {
92
- add_action( 'admin_notices', array( &$this, 'wg_admin_notice3' ),0 );
93
- return;
94
- }
95
 
96
- add_action( 'plugins_loaded', array( &$this, 'wg_load_textdomain' ) );
97
- add_action( 'init', array( &$this, 'init_function' ),11 );
98
- add_action( 'wp', array( &$this, 'rr_404_my_event' ) );
99
- add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( &$this, 'wg_plugin_action_links' ) );
100
 
101
- $this->original_l = get_option( 'original_l' );
102
- $this->destination_l = get_option( 'destination_l' );
103
 
104
- $this->home_dir = $this->getHomeDirectory();
105
- $this->request_uri = $this->getRequestUri( $this->home_dir );
106
  $this->network_paths = $this->getListOfNetworkPath();
107
 
108
  $this->noredirect = false;
109
- if ( strpos( $this->request_uri, '?no_lredirect=true' ) !== false ) {
110
  $this->noredirect = true;
111
- if ( isset( $_SERVER['REQUEST_URI'] ) ) {
112
  $_SERVER['REQUEST_URI'] = str_replace(
113
- '?no_lredirect=true','',
 
114
  $_SERVER['REQUEST_URI']
115
  );
116
  }
117
  }
118
- $this->request_uri = str_replace( '?no_lredirect=true','',$this->request_uri );
119
- $curr = $this->getLangFromUrl( $this->request_uri );
120
- $this->currentlang = $curr ? $curr : $this->original_l;
121
- $this->request_uri_no_language = ($this->currentlang != $this->original_l) ? substr( $this->request_uri,3 ) : $this->request_uri;
122
 
123
- if ( $this->currentlang != $this->original_l ) {
 
 
 
 
 
124
  $_SERVER['REQUEST_URI'] = str_replace(
125
  '/' . $this->currentlang .
126
- '/','/', $_SERVER['REQUEST_URI']
 
 
127
  );
128
  }
129
 
130
- if ( WGUtils::isLanguageRTL( $this->currentlang ) ) {
131
  $GLOBALS['text_direction'] = 'rtl';
132
  } else {
133
  $GLOBALS['text_direction'] = 'ltr';
134
  }
135
 
136
- add_filter( 'woocommerce_get_cart_url' , array( &$this,'filter_woocommerce_get_cart_url'));
137
- add_filter( 'woocommerce_get_checkout_url' , array( &$this,'filter_woocommerce_get_cart_url'));
138
- add_filter( 'woocommerce_get_checkout_order_received_url', array( &$this,'filter_woocommerce_get_checkout_order_received_url'));
 
 
 
 
 
 
139
 
140
- add_filter('woocommerce_login_redirect', array( &$this,'wg_log_redirect'));
141
- add_filter( 'login_redirect', array( &$this,'wg_log_redirect') );
142
- add_filter( 'logout_redirect', array( &$this,'wg_log_redirect') );
 
143
 
144
- //add_filter( 'wp_mail' , array( &$this, 'translate_emails'), 10,1);
 
145
 
146
- $apikey = get_option( 'project_key' );
147
- $this->translator = $apikey ? new \Weglot\Client( $apikey ) : null;
148
- $this->allowed = $apikey ? get_option( 'wg_allowed' ) : true;
149
 
150
- if ( is_admin() ) {
151
- if ( strpos( $this->request_uri, 'page=Weglot' ) !== false ) {
152
- if ( $this->translator ) {
153
  try {
154
  $this->userInfo = $this->translator->getUserInfo();
155
- if ( $this->userInfo ) {
156
  $this->allowed = $this->userInfo['allowed'];
157
- update_option( 'wg_allowed',$this->allowed ? 1 : 0 );
158
  }
159
- } catch ( \Exception $e ) {
160
  // If an exception occurs, do nothing, keep wg_allowed.
161
  ;
162
  }
163
  }
164
- } elseif ( $this->allowed == 0 ) {
165
- add_action( 'admin_notices', array( &$this, 'wg_admin_notice1' ),0 );
166
- } elseif ( !$apikey ) {
167
- add_action( 'admin_notices', array( &$this, 'wg_admin_notice4' ),0 );
168
  }
169
  }
170
 
171
 
172
- $isURLOK = $this->isEligibleURL( $this->request_uri_no_language );
173
- if ( $isURLOK ) {
174
- add_action( 'wp_head',array( &$this, 'add_alternate' ) );
175
- add_action( 'widgets_init', array( &$this, 'addWidget' ) );
176
- add_shortcode( 'weglot_switcher', array( &$this, 'wg_switcher_creation' ) );
177
- if ( get_option( 'is_menu' ) == 'on' ) {
178
- add_filter( 'wp_nav_menu_items', 'your_custom_menu_item', 10, 2 );
179
- function your_custom_menu_item( $items, $args ) {
 
180
  $button = Weglot::Instance()->returnWidgetCode();
181
  $items .= $button;
182
 
183
  return $items;
184
  }
185
  }
 
 
186
  }
187
- else {
188
- add_shortcode( 'weglot_switcher', array( &$this, 'wg_switcher_creation_empty' ) );
 
 
 
 
 
 
 
189
  }
 
 
 
 
 
 
190
  }
191
 
192
  // Get our only instance of Weglot class
193
- public static function Instance() {
 
194
  static $inst = null;
195
- if ( $inst == null ) {
196
  $inst = new Weglot();
197
  }
198
  return $inst;
199
  }
200
 
201
- public static function plugin_activate() {
202
- if ( version_compare( phpversion(), '5.3.0', '<' ) ) {
203
- wp_die(
204
- '<p>' . esc_html__( 'Thank you for downloading <strong>Weglot Translate</strong>!', 'weglot' ) . '</p><p>' . sprintf( esc_html__( 'In order to activate Weglot, you need PHP version <strong>5.3</strong> or greater. Your current version of PHP is %s.', 'weglot' ), esc_html__( phpversion() ) ) . '</p><p>' . esc_html__( 'Please upgrade your PHP version. You can ask your host provider to do this by sending them an email.', 'weglot' ) . '</p>',
205
- esc_html__( 'Plugin Activation Error', 'weglot' ),
206
- array(
207
- 'response' => 200,
208
- 'back_link' => true,
209
- )
210
- );
211
- }
212
-
213
- add_option( 'with_flags','on' );
214
- add_option( 'with_name','on' );
215
- add_option( 'is_dropdown','on' );
216
- add_option( 'is_fullname','off' );
217
- add_option( 'override_css','' );
218
- add_option( 'is_menu','off' );
219
- update_option( 'wg_allowed',1 );
220
- if ( get_option( 'permalink_structure' ) == '' ) {
221
- add_option( 'wg_old_permalink_structure_empty','on' );
222
- update_option( 'permalink_structure','/%year%/%monthnum%/%day%/%postname%/' );
223
  }
224
  }
225
 
226
- public static function plugin_deactivate() {
 
227
  flush_rewrite_rules();
228
- if ( get_option( 'wg_old_permalink_structure_empty' ) == 'on' ) {
229
- delete_option( 'wg_old_permalink_structure_empty' );
230
- update_option( 'permalink_structure','' );
231
  }
232
  }
233
 
234
- public static function plugin_uninstall() {
 
235
  flush_rewrite_rules();
236
- delete_option( 'project_key' );
237
- delete_option( 'original_l' );
238
- delete_option( 'destination_l' );
239
- delete_option( 'show_box' );
240
  }
241
 
242
- public function wg_load_textdomain() {
243
- load_plugin_textdomain( 'weglot', false, dirname( WEGLOT_BNAME ) . '/languages/' );
 
244
  }
245
 
246
- public function wg_plugin_action_links( $links ) {
247
- $links[] = '<a href="' . esc_url( get_admin_url( null, 'admin.php?page=Weglot' ) ) . '">' . __( 'Settings','weglot' ) . '</a>';
 
248
  return $links;
249
  }
250
 
251
- public function wg_admin_notice1() {
252
- ?>
253
- <div class="updated settings-error notice is-dismissible">
254
- <p><?php echo sprintf( esc_html__( 'Weglot Translate is not active because you have exceeded the free limit. Please %1$supgrade your plan%2$s if you want to keep the service running.', 'weglot' ), '<a target="_blank" href="https://weglot.com/change-plan">', '</a>' ); ?></p>
255
- </div>
256
- <?php
257
- }
258
-
259
- public function wg_admin_notice2() {
260
- ?>
261
- <div class="error settings-error notice is-dismissible">
262
- <p><?php echo sprintf( esc_html__( 'Weglot Translate plugin requires at least PHP 5.3 and you have PHP %s. Please upgrade your PHP version (you can contact your host and they will do it for you).', 'weglot' ), esc_html__( phpversion() ) ); ?></p>
263
- </div>
264
- <?php
265
- }
266
-
267
- public function wg_admin_notice3() {
268
- ?>
269
- <div class="error settings-error notice is-dismissible">
270
- <p><?php echo sprintf( esc_html__( 'Weglot Translate: You need to activate the mod_rewrite module. You can find more information here : %1$sUsing Permalinks%2$s. If you need help, just ask us directly at support@weglot.com.', 'weglot' ), '<a target="_blank" href="https://codex.wordpress.org/Using_Permalinks">', '</a>' ); ?></p>
271
- </div>
272
- <?php
273
- }
274
-
275
- public function wg_admin_notice4() {
276
- ?>
277
- <div class="error settings-error notice is-dismissible">
278
- <p><?php echo sprintf( esc_html__( 'Weglot Translate is installed but not yet configured, you need to configure Weglot here : %1$sWeglot configuration page%2$s. The configuration takes only 1 minute! ', 'weglot' ), '<a href="'.admin_url().'admin.php?page=Weglot">', '</a>'); ?></p>
279
- </div>
280
- <?php
281
- }
282
-
283
- public function filter_woocommerce_get_cart_url( $wc_get_page_permalink ) {
284
- if($this->currentlang != $this->original_l) {
285
  return $this->replaceUrl($wc_get_page_permalink, $this->currentlang);
286
- }
287
- else {
288
  return $wc_get_page_permalink;
289
  }
290
  }
291
 
292
- public function filter_woocommerce_get_checkout_order_received_url( $order_received_url ) {
293
-
294
- if($this->currentlang != $this->original_l) {
295
- if(substr(get_option( 'permalink_structure' ),-1) == '/')
296
- return str_replace('?key','/?key',$this->replaceUrl($order_received_url, $this->currentlang));
297
- else
298
- return $this->replaceUrl($order_received_url, $this->currentlang);
299
- }
300
- else {
301
- if(isset($_SERVER['HTTP_REFERER'])) {
302
- $l = $this->getLangFromUrl($this->URLToRelative( $_SERVER['HTTP_REFERER']));
303
- if($l && $l != $this->original_l) {
304
- if(substr(get_option( 'permalink_structure' ),-1) == '/')
305
- return str_replace('?key','/?key',$this->replaceUrl($order_received_url, $l));
306
- else
307
- return $this->replaceUrl($order_received_url, $l);
308
- }
309
- }
310
- return $order_received_url;
311
- }
312
- }
313
-
314
- public function wg_log_redirect( $redirect_to ) {
315
-
316
- if($this->currentlang != $this->original_l) {
 
317
  return $this->replaceUrl($redirect_to, $this->currentlang);
318
- }
319
- else {
320
- if(isset($_SERVER['HTTP_REFERER'])) {
321
- $l = $this->getLangFromUrl($this->URLToRelative( $_SERVER['HTTP_REFERER']));
322
- if($l && $l != $this->original_l) {
323
  return $this->replaceUrl($redirect_to, $l);
324
  }
325
  }
@@ -327,62 +336,62 @@ class Weglot {
327
  }
328
  }
329
 
330
- public function translate_emails($args){
331
-
332
  $messageAndSubject = "<p>".$args['subject']."</p>".$args['message'];
333
 
334
- if($this->currentlang != $this->original_l) {
335
- $messageAndSubjectTranslated = $this->translateEmail($messageAndSubject,$this->currentlang);
336
- }
337
- elseif(isset($_SERVER['HTTP_REFERER'])) {
338
- $l = $this->getLangFromUrl($this->URLToRelative( $_SERVER['HTTP_REFERER']));
339
- if($l && $l != $this->original_l) { //If language in referer
340
- $messageAndSubjectTranslated = $this->translateEmail($messageAndSubject,$l);
341
- }
342
- elseif(strpos($_SERVER['HTTP_REFERER'], 'wg_language=') !== false) { //If language in parameter
343
- $pos = strpos($_SERVER['HTTP_REFERER'], 'wg_language=');
344
  $start = $pos + strlen('wg_language=');
345
- $l = substr($_SERVER['HTTP_REFERER'],$start,2);
346
- if($l && $l != $this->original_l) {
347
- $messageAndSubjectTranslated = $this->translateEmail($messageAndSubject,$l);
348
  }
349
  }
350
  }
351
 
352
  if (strpos($messageAndSubjectTranslated, '</p>') !== false) {
353
- $pos = strpos($messageAndSubjectTranslated, '</p>')+4;
354
- $args['subject'] = substr($messageAndSubjectTranslated,3,$pos-7);
355
- $args['message'] = substr($messageAndSubjectTranslated,$pos);
356
-
357
  }
358
  return $args;
359
  }
360
 
361
- public function wg_switcher_creation() {
 
362
  $button = Weglot::Instance()->returnWidgetCode();
363
- echo wp_kses( $button, $this->getAllowedTags());
364
  }
365
 
366
- public function wg_switcher_creation_empty() {
367
- echo wp_kses( "", $this->getAllowedTags());
 
368
  }
369
 
370
 
371
 
372
- public function init_function() {
 
 
 
373
 
374
- add_action( 'admin_menu', array( &$this, 'plugin_menu' ) );
375
- add_action( 'admin_init', array( &$this, 'plugin_settings' ) );
376
 
377
- $dest = explode( ',',$this->destination_l );
378
 
379
- if ( $this->request_uri == '/' && ! $this->noredirect && ! WGUtils::is_bot() ) { // front_page
380
- if ( get_option( 'wg_auto_switch' ) == 'on' && isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) {
381
  /* Redirects to browser L */
382
- $lang = substr( $_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2 );
383
  // exit(print_r($dest));
384
- if ( in_array( $lang,$dest ) ) {
385
- wp_safe_redirect( $this->home_dir . "/$lang/" );
386
  exit();
387
  }
388
  }
@@ -390,265 +399,284 @@ class Weglot {
390
 
391
  /* prevent homepage redirect in canonical.php in case of show */
392
  $request_uri = $this->request_uri;
393
- foreach ( $dest as $d ) {
394
- if ( $request_uri == '/' . $d . '/' ) {
395
  $thisL = $d;
396
  }
397
  }
398
- $url = (isset( $thisL ) && $thisL != '') ? substr( $request_uri,3 ) : $request_uri;
399
 
400
- if ( $url == '/' && (isset( $thisL ) && $thisL != '') && 'page' == get_option( 'show_on_front' ) ) {
401
- add_action( 'template_redirect',array( &$this, 'kill_canonical_wg_92103' ),1 );
402
  }
403
 
404
- if ( ! is_admin() || (is_admin() && strpos( $this->request_uri, 'page=Weglot' ) !== false) ) {
405
  // Add JS
406
- wp_register_script( 'wp-weglot-js', WEGLOT_RESURL . 'wp-weglot-js.js', false,WEGLOT_VERSION, false );
407
- wp_enqueue_script( 'wp-weglot-js' );
408
 
409
  // Add CSS
410
- wp_register_style( 'wp-weglot-css', WEGLOT_RESURL . 'wp-weglot-css.css', false,WEGLOT_VERSION, false );
411
- wp_enqueue_style( 'wp-weglot-css' );
412
-
413
- wp_add_inline_style( 'wp-weglot-css', $this->getInlineCSS() );
414
 
415
- if ( is_admin() ) {
 
 
416
  // Add Admin JS
417
- wp_register_script( 'wp-weglot-admin-js', WEGLOT_RESURL . 'wp-weglot-admin-js.js', array( 'jquery' ),WEGLOT_VERSION, true );
418
- wp_enqueue_script( 'wp-weglot-admin-js' );
419
 
420
  // Add Admin CSS
421
- wp_register_style( 'wp-weglot-admin-css', WEGLOT_RESURL . 'wp-weglot-admin-css.css', false,WEGLOT_VERSION, false );
422
- wp_enqueue_style( 'wp-weglot-admin-css' );
423
 
424
  // Add Selectize JS
425
- wp_enqueue_script( 'jquery-ui', WEGLOT_RESURL . 'selectize/js/jquery-ui.min.js', array( 'jquery' ), WEGLOT_VERSION, true );
426
- wp_enqueue_script( 'jquery-selectize', WEGLOT_RESURL . 'selectize/js/selectize.min.js', array( 'jquery' ), WEGLOT_VERSION, true );
427
  // wp_enqueue_style( 'selectize-css', WEGLOT_RESURL . 'selectize/css/selectize.css', array(), $ver );
428
- wp_enqueue_style( 'selectize-defaut-css', WEGLOT_RESURL . 'selectize/css/selectize.default.css', array(), WEGLOT_VERSION );
429
 
 
 
 
 
 
 
 
 
 
 
 
 
 
430
  }
431
  }
432
 
433
  /* Putting it in init makes that buffer deeper than caching ob */
434
- ob_start( array( &$this, 'treatPage' ) );
435
  }
436
 
437
- public function add_alternate() {
438
-
439
- if ( $this->destination_l != '' ) {
440
 
441
  // $thisL = $this->currentlang;
442
- $dest = explode( ',',$this->destination_l );
443
 
444
- $full_url = ($this->currentlang != $this->original_l) ? str_replace( '/' . $this->currentlang . '/','/',$this->full_url( $_SERVER ) ) : $this->full_url( $_SERVER );
445
- $output = '<link rel="alternate" hreflang="' . $this->original_l . '" href="' . $full_url . '" />' . "\n";
446
- foreach ( $dest as $d ) {
447
- $output .= '<link rel="alternate" hreflang="' . $d . '" href="' . $this->replaceUrl( $full_url,$d ) . '" />' . "\n";
448
  }
449
 
450
  echo wp_kses($output, array(
451
  'link' => array(
452
  'rel' => array(),
453
- 'hreflang'=>array(),
454
- 'href'=>array())
455
  ));
456
  }
457
  }
458
 
459
- public function getCurrentLang() {
 
460
  return $this->currentlang;
461
  }
462
 
463
- public function rr_404_my_event() {
 
464
 
465
  // regex logic here
466
- $isURLOK = $this->isEligibleURL( $this->request_uri_no_language );
467
- if ( ! $isURLOK && $this->currentlang != $this->original_l ) {
468
  global $wp_query;
469
  $wp_query->set_404();
470
- status_header( 404 );
471
  }
472
  }
473
 
474
- public function kill_canonical_wg_92103() {
475
- add_action( 'redirect_canonical','__return_false' );
 
476
  }
477
 
478
- public function plugin_menu() {
479
- $hook = add_menu_page( 'Weglot', 'Weglot', 'administrator', 'Weglot', array( &$this, 'plugin_settings_page' ), WEGLOT_DIRURL . '/images/weglot_fav_bw.png' );
 
480
 
481
- // add_action('load-'.$hook,array(&$this, 'updateRewriteRule'));
482
- if ( isset( $this->request_uri_no_language )
483
  // && isset( $_POST['settings-updated-nonce'] )
484
- && $this->request_uri_no_language
485
- && strpos( $this->request_uri_no_language, 'page=Weglot' ) !== false
486
- && strpos( $this->request_uri_no_language, 'settings-updated=true' ) !==
487
  false) {
488
-
489
- $d = explode( ',',preg_replace( '/\s+/', '', trim( $this->destination_l,',' ) ) );
490
- $accepted = array( 'af','sq','am','ar','hy','az','ba','eu','be','bn','bs','bg','my','ca','km','ny','co','hr','cs','da','nl','en','eo','et','fj','fi','fr','gl','ka','de','el','gu','ht','ha','he','hi','hu','is','ig','id','ga','it','ja','jv','kn','kk','ko','ku','ky','lo','la','lv','lt','lb','mk','mg','ms','ml','mt','mi','mr','mn','ne','no','ps','fa','pl','pt','pa','ro','ru','sm','gd','sr','sn','zh','sd','si','sk','sl','so','st','es','su','sw','sv','tl','ty','tg','ta','tt','te','th','to','tw','tr','uk','ur','uz','vi','cy','fy','xh','yi','yo','zu' );
491
- foreach ( $d as $k => $l ) {
492
- if ( ! in_array( $l,$accepted ) || $l == $this->original_l ) {
493
- unset( $d[ $k ] );
494
  }
495
  }
496
- update_option( 'destination_l',implode( ',',$d ) );
497
- $this->destination_l = implode( ',',$d );
498
 
499
  /* Display Box */
500
- if ( ! get_option( 'show_box' ) ) {
501
- add_option( 'show_box','on' );
502
  }
503
 
504
- if ( $this->userInfo['plan'] <= 0 || in_array( $this->userInfo['plan'],array( 18, 19, 1001, 1002 ) ) ) {
505
- $d = explode( ',',preg_replace( '/\s+/', '', trim( $this->destination_l,',' ) ) );
506
  $this->destination_l = $d[0];
507
- update_option( 'destination_l',$this->destination_l );
508
  }
509
  }
510
  }
511
 
512
- public function plugin_settings() {
513
- register_setting( 'my-plugin-settings-group', 'project_key' );
514
- register_setting( 'my-plugin-settings-group', 'original_l' );
515
- register_setting( 'my-plugin-settings-group', 'destination_l' );
516
- register_setting( 'my-plugin-settings-group', 'wg_auto_switch' );
517
- register_setting( 'my-plugin-settings-group', 'override_css' );
518
- register_setting( 'my-plugin-settings-group', 'flag_css' );
519
- register_setting( 'my-plugin-settings-group', 'with_flags' );
520
- register_setting( 'my-plugin-settings-group', 'type_flags' );
521
- register_setting( 'my-plugin-settings-group', 'with_name' );
522
- register_setting( 'my-plugin-settings-group', 'is_dropdown' );
523
- register_setting( 'my-plugin-settings-group', 'is_fullname' );
524
- register_setting( 'my-plugin-settings-group', 'is_menu' );
525
- register_setting( 'my-plugin-settings-group', 'exclude_url' );
526
- register_setting( 'my-plugin-settings-group', 'exclude_blocks' );
527
- register_setting( 'my-plugin-settings-group', 'rtl_ltr_style' );
 
528
  }
529
 
530
- public function plugin_settings_page() {
531
- include( WEGLOT_DIR . '/includes/wg-settings-page.php' );
 
532
  }
533
 
534
- public function addWidget() {
535
- return register_widget( 'WeglotWidget' );
 
536
  }
537
 
538
- public function translateEmail($body,$l) {
539
- $translatedEmail = $this->translator->translateDomFromTo( $body,$this->original_l,$l );
 
540
  return $translatedEmail;
541
  }
542
- public function treatPage( $final ) {
543
-
544
  $request_uri = $this->request_uri;
545
- if ( ! is_admin() && strpos( $request_uri,'jax' ) === false && $this->original_l != '' && $this->destination_l != '' ) {
546
 
547
  // $final = file_get_contents(__DIR__.'/content.html'); //Testing purpose.
548
  // Get the original request
549
  $url = $this->request_uri_no_language;
550
-
551
- if ( $this->isEligibleURL( $url ) && WGUtils::is_HTML( $final ) ) {
552
 
553
  // If a language is set, we translate the page & links.
554
- if ( $this->currentlang != $this->original_l ) {
555
  try {
556
- $l = $this->currentlang;
557
- $final = $this->translatePageTo( $final,$l );
558
- } catch ( \Weglot\WeglotException $e ) {
559
  $final .= '<!--Weglot error : ' . $e->getMessage() . '-->';
560
- if ( strpos( $e->getMessage(), 'NMC' ) !== false ) {
561
- update_option( 'wg_allowed',0 );
562
  }
563
- } catch ( \Exception $e ) {
564
  $final .= '<!--Weglot error : ' . $e->getMessage() . '-->';
565
  }
566
  }
567
 
568
  // Place the button if we see short code
569
- if ( strpos( $final,'<div id="weglot_here"></div>' ) !== false ) {
570
-
571
  $button = $this->returnWidgetCode();
572
- $final = str_replace( '<div id="weglot_here"></div>',$button,$final );
573
  }
574
  // Place the button if we see short code
575
- if ( strpos( $final,'<div class="weglot_here"></div>' ) !== false ) {
576
-
577
  $button = $this->returnWidgetCode();
578
- $final = str_replace( '<div class="weglot_here"></div>',$button,
579
- $final );
 
 
 
580
  }
581
 
582
  // Place the button if not in the page
583
- if ( strpos( $final,'class="wgcurrent' ) === false ) {
584
-
585
- $button = $this->returnWidgetCode( true );
586
- $button = WGUtils::str_lreplace( '<aside data-wg-notranslate class="','<aside data-wg-notranslate class="wg-default ',$button );
587
- $final = (strpos( $final, '</body>' ) !== false) ? WGUtils::str_lreplace( '</body>',$button . ' </body>',$final ) : WGUtils::str_lreplace( '</footer>',$button . ' </footer>',$final );
588
  }
589
- return $final;
590
- }
591
- elseif($this->isEligibleURL( $url ) && $final[0] == '{' || ($final[0] == '[' && $final[1] == '{') ) {
 
592
  $thisL = $this->getLangFromUrl(
593
  $this->URLToRelative(
594
  $_SERVER['HTTP_REFERER']
595
  )
596
  );
597
- if ( isset( $thisL ) && $thisL != '' ) {
598
  try {
599
- if ( $final[0] == '{' || ($final[0] == '[' && $final[1] == '{') ) {
600
- $json = json_decode( $final,true );
601
- if ( json_last_error() == JSON_ERROR_NONE ) {
602
- $jsonT = $this->translateArray( $json,$thisL );
603
- return wp_json_encode( $jsonT );
604
  } else {
605
  return $final;
606
  }
607
- } elseif ( WGUtils::is_AJAX_HTML( $final ) ) {
608
- return $this->translatePageTo( $final,$thisL );
609
  } else {
610
  return $final;
611
  }
612
- } catch ( \Weglot\WeglotException $e ) {
613
  return $final;
614
- } catch ( \Exception $e ) {
615
  return $final;
616
  }
617
  } else {
618
  return $final;
619
  }
620
- }
621
- else {
622
  return $final;
623
  }
624
- } elseif ( (strpos( $request_uri,'jax' ) !== false ) &&
625
  $this->destination_l != '' && $this->original_l != '' && isset(
626
  $_SERVER['HTTP_REFERER']
627
- ) && strpos( $_SERVER['HTTP_REFERER'] ,'admin' ) === false ) {
628
-
629
  $thisL = $this->getLangFromUrl(
630
  $this->URLToRelative(
631
  $_SERVER['HTTP_REFERER']
632
  )
633
  );
634
- if ( isset( $thisL ) && $thisL != '' ) {
635
  try {
636
- if ( $final[0] == '{' || ($final[0] == '[' && $final[1] == '{') ) {
637
- $json = json_decode( $final,true );
638
- if ( json_last_error() == JSON_ERROR_NONE ) {
639
- $jsonT = $this->translateArray( $json,$thisL );
640
- return wp_json_encode( $jsonT );
641
  } else {
642
  return $final;
643
  }
644
- } elseif ( WGUtils::is_AJAX_HTML( $final ) ) {
645
- return $this->translatePageTo( $final,$thisL );
646
  } else {
647
  return $final;
648
  }
649
- } catch ( \Weglot\WeglotException $e ) {
650
  return $final;
651
- } catch ( \Exception $e ) {
652
  return $final;
653
  }
654
  } else {
@@ -660,156 +688,218 @@ class Weglot {
660
  }
661
 
662
  /* translation of the page */
663
- function translateArray( $array, $to ) {
664
- foreach ( $array as $key => $val ) {
665
- if ( is_array( $val ) ) {
666
- $array[ $key ] = $this->translateArray( $val,$to );
 
667
  } else {
668
- if ( WGUtils::is_AJAX_HTML( $val ) ) {
669
- $array[ $key ] = $this->translatePageTo( $val,$to );
670
- }
671
- elseif(in_array($key,'redirecturl','url')) {
672
- $array[ $key] = $this->replaceUrl($val,$to);
673
  }
674
  }
675
  }
676
  return $array;
677
  }
678
 
679
- function translatePageTo( $final, $l ) {
680
-
681
- if ( $this->allowed == 0 ) {
682
  return $final . '<!--Not allowed-->';
683
  }
684
- $translatedPage = $this->translator->translateDomFromTo( $final,$this->original_l,$l ); // $page is your html page
685
-
686
- $this->modifyLink('/<a([^\>]+?)?href=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/',$translatedPage,$l,'A');
687
- $this->modifyLink('/<([^\>]+?)?data-link=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/',$translatedPage,$l,'DATALINK');
688
- $this->modifyLink('/<([^\>]+?)?data-url=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/',$translatedPage,$l,'DATAURL');
689
- $this->modifyLink('/<([^\>]+?)?data-cart-url=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/',$translatedPage,$l,'DATACART');
690
- $this->modifyLink('/<form([^\>]+?)?action=(\"|\')([^\s\>]+?)(\"|\')/',$translatedPage,$l,'FORM');
691
- $this->modifyLink('/<option (.*?)?(\"|\')([^\s\>]+?)(\"|\')(.*?)?>/',
692
- $translatedPage,$l,'OPTION');
693
- $this->modifyLink('/<link rel="canonical"(.*?)?href=(\"|\')([^\s\>]+?)(\"|\')/',$translatedPage,$l,'LINK');
694
- $this->modifyLink('/<meta property="og:url"(.*?)?content=(\"|\')([^\s\>]+?)(\"|\')/',$translatedPage,$l,'META');
 
 
 
 
 
695
 
696
 
697
 
698
 
699
- $translatedPage = preg_replace( '/<html (.*?)?lang=(\"|\')(\S*)(\"|\')/','<html $1lang=$2' . $l . '$4',$translatedPage );
700
- $translatedPage = preg_replace( '/property="og:locale" content=(\"|\')(\S*)(\"|\')/','property="og:locale" content=$1' . $l . '$3',$translatedPage );
701
  return $translatedPage;
702
  }
703
 
704
- public function modifyLink($pattern,&$translatedPage,$l,$type) {
 
705
  $admin_url = admin_url();
706
- preg_match_all($pattern ,$translatedPage,$out, PREG_PATTERN_ORDER );
707
- for ( $i = 0;$i < count( $out[0] );$i++ ) {
708
-
709
- $sometags = $out[1][ $i ];
710
- $quote1 = $out[2][ $i ];
711
- $current_url = $out[3][ $i ];
712
- $quote2 = $out[4][ $i ];
713
- $sometags2 = $out[5][ $i ];
714
-
 
 
 
715
 
716
- if ( $this->checkLink($current_url,$admin_url,$sometags,$sometags2) )
717
- {
718
  $functionName = 'replace' .$type;
719
- $this->$functionName($translatedPage,$current_url,$l,$quote1,
720
- $quote2,$sometags,$sometags2);
 
 
 
 
 
 
 
721
  }
722
  }
723
  }
724
 
725
- public function checkLink($current_url,$admin_url,$sometags = null, $sometags2 =
726
- null) {
727
- $parsed_url = parse_url( $current_url );
 
728
 
729
  return (
730
  (($current_url[0] == 'h' && $parsed_url['host'] == $_SERVER['HTTP_HOST'])
731
  || ($current_url[0] == '/' && $current_url[1] != '/'))
732
- && strpos( $current_url,$admin_url ) === false
733
- && strpos( $current_url,'wp-login' ) === false
734
  && !$this->isLinkAFile($current_url)
735
- && $this->isEligibleURL( $current_url )
736
- && strpos( $sometags,'data-wg-notranslate' ) === false
737
- && strpos( $sometags2,'data-wg-notranslate' ) === false
738
  );
739
  }
740
 
741
- public function replaceA(&$translatedPage,$current_url,$l,$quote1,
742
- $quote2,$sometags = null, $sometags2 = null) {
743
- $translatedPage = preg_replace( '/<a' . preg_quote( $sometags,'/' ) . 'href=' .
744
- preg_quote( $quote1 . $current_url . $quote2,'/' ) . '/'
745
- ,'<a' . $sometags . 'href=' . $quote1 . $this->replaceUrl(
746
- $current_url,$l ) . $quote2
747
- ,$translatedPage );
748
-
 
 
 
 
 
 
 
749
  }
750
 
751
- public function replaceDATALINK(&$translatedPage,$current_url,$l,$quote1,
752
- $quote2,$sometags = null, $sometags2 = null) {
753
- $translatedPage = preg_replace( '/<' . preg_quote( $sometags,'/' ) . 'data-link=' . preg_quote( $quote1 . $current_url . $quote2,'/' ) . '/'
754
- ,'<' . $sometags . 'data-link=' . $quote1 . $this->replaceUrl(
755
- $current_url,$l ) . $quote2,$translatedPage );
756
-
757
  }
758
 
759
- public function replaceDATAURL(&$translatedPage,$current_url,$l,$quote1,
760
- $quote2,$sometags = null, $sometags2 = null) {
761
- $translatedPage = preg_replace( '/<' . preg_quote( $sometags,'/' ) . 'data-url=' . preg_quote( $quote1 . $current_url . $quote2,'/' ) . '/'
762
- ,'<' . $sometags . 'data-url=' . $quote1 . $this->replaceUrl(
763
- $current_url,$l ) . $quote2,$translatedPage );
764
-
765
  }
766
 
767
- public function replaceDATACART(&$translatedPage,$current_url,$l,$quote1,
768
- $quote2,$sometags = null, $sometags2 = null) {
769
-
770
- $translatedPage = preg_replace( '/<' . preg_quote( $sometags,'/' ) . 'data-cart-url=' . preg_quote( $quote1 . $current_url . $quote2,'/' ) . '/'
771
- ,'<' . $sometags . 'data-cart-url=' . $quote1 . $this->replaceUrl(
772
- $current_url,$l ) . $quote2,$translatedPage );
 
 
 
 
 
 
 
773
  }
774
 
775
- public function replaceFORM(&$translatedPage,$current_url,$l,$quote1,
776
- $quote2,$sometags = null, $sometags2 = null) {
777
-
778
- $translatedPage = preg_replace( '/<form' . preg_quote( $sometags,'/' ) . 'action=' . preg_quote( $quote1 . $current_url . $quote2,'/' ) . '/','<form ' . $sometags . 'action=' . $quote1 . $this->replaceUrl( $current_url,$l ) . $quote2,$translatedPage );
779
-
 
 
 
 
 
780
  }
781
 
782
- public function replaceOPTION(&$translatedPage,$current_url,$l,$quote1,
783
- $quote2,$sometags = null, $sometags2 = null) {
784
-
785
- $translatedPage = preg_replace( '/<option ' . preg_quote(
786
- $sometags,'/' ) . preg_quote( $quote1 . $current_url . $quote2,'/'
787
- ) . '(.*?)?>/','<option ' . $sometags . $quote1 . $this->replaceUrl(
788
- $current_url,$l ) . $quote2 . '$2>',$translatedPage );
 
 
 
 
 
 
 
 
 
 
 
 
789
  }
790
 
791
- public function replaceLINK(&$translatedPage,$current_url,$l,$quote1,
792
- $quote2,$sometags = null, $sometags2 = null) {
793
-
794
- $translatedPage = preg_replace( '/<link rel="canonical"' . preg_quote(
795
- $sometags,'/' ) . 'href=' . preg_quote( $quote1 . $current_url .
796
- $quote2,'/' ) . '/','<link rel="canonical"' . $sometags . 'href=' . $quote1 . $this->replaceUrl( $current_url,$l ) . $quote2,$translatedPage );
797
-
 
 
 
 
 
 
 
798
  }
799
 
800
- public function replaceMETA(&$translatedPage,$current_url,$l,$quote1,
801
- $quote2,$sometags = null, $sometags2 = null) {
802
- $translatedPage = preg_replace( '/<meta property="og:url"' . preg_quote(
803
- $sometags,'/' ) . 'content=' . preg_quote( $quote1 . $current_url
804
- . $quote2,'/' ) . '/','<meta property="og:url"' . $sometags . 'content=' . $quote1 . $this->replaceUrl( $current_url,$l ) . $quote2,$translatedPage );
805
-
806
-
 
 
 
 
 
 
 
807
  }
808
 
809
- public function isLinkAFile($current_url) {
 
810
  $files = array('pdf','rar','doc','docx','jpg','jpeg','png','ppt','pptx','xls','zip','mp4','xlsx');
811
  foreach ($files as $file) {
812
- if ( WGUtils::endsWith( $current_url,'.'.$file )) {
813
  return true;
814
  }
815
  }
@@ -817,56 +907,60 @@ class Weglot {
817
  }
818
 
819
  /* Urls functions */
820
- public function replaceUrl( $url, $l ) {
 
821
  //$home_dir = $this->home_dir;
822
 
823
- $parsed_url = parse_url( $url );
824
- $scheme = isset( $parsed_url['scheme'] ) ? $parsed_url['scheme'] . '://' : '';
825
- $host = isset( $parsed_url['host'] ) ? $parsed_url['host'] : '';
826
- $port = isset( $parsed_url['port'] ) ? ':' . $parsed_url['port'] : '';
827
- $user = isset( $parsed_url['user'] ) ? $parsed_url['user'] : '';
828
- $pass = isset( $parsed_url['pass'] ) ? ':' . $parsed_url['pass'] : '';
829
- $pass = ($user || $pass) ? "$pass@" : '';
830
- $path = isset( $parsed_url['path'] ) ? $parsed_url['path'] : '/';
831
- $query = isset( $parsed_url['query'] ) ? '?' . $parsed_url['query'] : '';
832
- $fragment = isset( $parsed_url['fragment'] ) ? '#' . $parsed_url['fragment'] : '';
833
 
834
 
835
- if ( $l == '' ) {
836
  return $url;
837
  } else {
838
- $urlTranslated = (strlen( $path ) > 2 && substr( $path,0,4 ) ==
839
  "/$l/") ?
840
  "$scheme$user$pass$host$port$path$query$fragment" : "$scheme$user$pass$host$port/$l$path$query$fragment";
841
 
842
  foreach ($this->network_paths as $np) {
843
- if (strlen($np)>2 && strpos($urlTranslated, $np) !==
844
  false) {
845
- $urlTranslated = str_replace('/'.$l.$np,$np.$l.'/' ,
846
- $urlTranslated);
 
 
 
847
  }
848
  }
849
 
850
  return $urlTranslated;
851
  }
852
-
853
  }
854
- public function url_origin( $s, $use_forwarded_host = false ) {
855
- $ssl = ( ! empty( $s['HTTPS'] ) && $s['HTTPS'] == 'on') ? true : false;
856
- $sp = strtolower( $s['SERVER_PROTOCOL'] );
857
- $protocol = substr( $sp, 0, strpos( $sp, '/' ) ) . (($ssl) ? 's' : '');
858
- $port = $s['SERVER_PORT'];
859
- $port = (( ! $ssl && $port == '80') || ($ssl && $port == '443')) ? '' : ':' . $port;
860
- $host = ($use_forwarded_host && isset( $s['HTTP_X_FORWARDED_HOST'] )) ? $s['HTTP_X_FORWARDED_HOST'] : (isset( $s['HTTP_HOST'] ) ? $s['HTTP_HOST'] : null);
861
- $host = isset( $host ) ? $host : $s['SERVER_NAME'] . $port;
 
862
  return $protocol . '://' . $host;
863
  }
864
 
865
- public function getListOfNetworkPath() {
866
-
867
  $paths = array();
868
 
869
- if(is_multisite()) {
870
  $sites = get_sites();
871
  foreach ($sites as $site) {
872
  $path = $site->path;
@@ -879,51 +973,67 @@ class Weglot {
879
  return $paths;
880
  }
881
 
882
- public function full_url( $s, $use_forwarded_host = false ) {
883
- return $this->url_origin( $s, $use_forwarded_host ) . $s['REQUEST_URI'];
 
884
  }
885
- public function isEligibleURL( $url ) {
886
- $url = $this->URLToRelative( $url );
887
-
888
-
889
  //Format exclude URL
890
  $excludeURL = get_option('exclude_url');
891
- if(!empty($excludeURL)) {
892
- $excludeURL = preg_replace('#\s+#',',',trim($excludeURL));
893
- $excluded_urls = explode(',',$excludeURL);
894
- foreach ($excluded_urls as &$ex_url) {
 
 
895
  $ex_url = $this->URLToRelative($ex_url);
896
  }
897
- $excludeURL = implode(',',$excluded_urls);
898
  }
899
 
900
 
901
- $exclusions = preg_replace( '#\s+#',',',$excludeURL );
902
- $exclusions = $exclusions == '' ? '/amp(/)?$' : $exclusions . ',/amp(/)?$';
903
- $regex = explode( ',',$exclusions );
904
 
905
- if ( $exclusions != '' ) {
906
- foreach ( $regex as $ex ) {
907
- if ( preg_match( '/' . str_replace( '/', '\/',$ex ) . '/',$url ) == 1 ) {
908
- return false;
909
- }
 
 
 
 
 
 
 
 
 
 
 
910
  }
911
- return true;
912
- } else {
913
- return true;
914
  }
 
 
915
  }
916
- public function URLToRelative( $url ) {
917
 
918
- if ( (substr( $url, 0, 7 ) == 'http://') || (substr( $url, 0, 8 ) == 'https://') ) {
 
 
 
 
 
 
 
919
  // the current link is an "absolute" URL - parse it to get just the path
920
- $parsed = parse_url( $url );
921
- $path = isset( $parsed['path'] ) ? $parsed['path'] : '';
922
- $query = isset( $parsed['query'] ) ? '?' . $parsed['query'] : '';
923
- $fragment = isset( $parsed['fragment'] ) ? '#' . $parsed['fragment'] : '';
924
 
925
- if ( $this->home_dir ) {
926
- $relative = str_replace( $this->home_dir,'',$path );
927
 
928
  return ($relative == '') ? '/' : $relative;
929
  } else {
@@ -932,18 +1042,20 @@ class Weglot {
932
  }
933
  return $url;
934
  }
935
- public function getRequestUri( $home_dir ) {
936
- if ( $home_dir ) {
937
- return str_replace( $home_dir,'', $_SERVER['REQUEST_URI'] );
 
938
  } else {
939
  return $_SERVER['REQUEST_URI'];
940
  }
941
  }
942
- public function getLangFromUrl( $request_uri ) {
943
- $l = null;
944
- $dest = explode( ',',$this->destination_l );
945
- foreach ( $dest as $d ) {
946
- if ( substr( $request_uri,0,4 ) == '/' . $d . '/' ) {
 
947
  $l = $d;
948
  }
949
  }
@@ -956,13 +1068,14 @@ class Weglot {
956
  * return empty string otherwise
957
  *
958
  */
959
- public function getHomeDirectory() {
960
- $opt_siteurl = trim( get_option( 'siteurl' ),'/' );
961
- $opt_home = trim( get_option( 'home' ),'/' );
962
- if ( $opt_siteurl != '' && $opt_home != '' ) {
963
- if ( (substr( $opt_home,0,7 ) == 'http://' && strpos( substr( $opt_home,7 ),'/' ) !== false) || (substr( $opt_home,0,8 ) == 'https://' && strpos( substr( $opt_home,8 ),'/' ) !== false) ) {
964
- $parsed_url = parse_url( $opt_home );
965
- $path = isset( $parsed_url['path'] ) ? $parsed_url['path'] : '/';
 
966
  return $path;
967
  }
968
  }
@@ -970,72 +1083,73 @@ class Weglot {
970
  }
971
 
972
  /* button function (code and CSS) */
973
- public function getInlineCSS() {
974
- $css = get_option( 'override_css' );
975
- if ( (WGUtils::isLanguageRTL( $this->original_l ) && ! WGUtils::isLanguageRTL( $this->currentlang )) ||
976
- ( ! WGUtils::isLanguageRTL( $this->original_l ) && WGUtils::isLanguageRTL( $this->currentlang )) ) {
977
- $css .= get_option( 'rtl_ltr_style' );
 
978
  }
979
- if ( ! is_admin() ) {
980
- $css .= get_option( 'flag_css' );
981
  }
982
  return $css;
983
  }
984
 
985
- public function getAllowedTags() {
 
986
  return array(
987
- 'a' => array( 'href' => array(), 'title' =>
988
  array(), 'onclick' => array(), 'target'
989
- => array(), 'data-wg-notranslate' => array() , 'class'=>array()),
990
- 'div' => array('class'=>array(), 'data-wg-notranslate' =>
991
  array()),
992
- 'aside' => array('onclick' => array(), 'class'=>array(), 'data-wg-notranslate' => array()),
993
- 'ul' => array('class'=>array(), 'data-wg-notranslate' => array
994
- ()),
995
- 'li' => array('class'=>array(), 'data-wg-notranslate' => array())
996
  );
997
  }
998
 
999
- public function returnWidgetCode( $forceNoMenu = false ) {
1000
-
1001
- $full = get_option( 'is_fullname' ) == 'on';
1002
- $withname = get_option( 'with_name' ) == 'on';
1003
- $is_dropdown = get_option( 'is_dropdown' ) == 'on';
1004
- $is_menu = $forceNoMenu ? false : get_option( 'is_menu' ) == 'on';
1005
- $flag_class = (get_option( 'with_flags' ) == 'on') ? 'wg-flags ' : '';
1006
 
1007
- $type_flags = get_option( 'type_flags' ) ? get_option( 'type_flags' ) : 0;
1008
  $flag_class .= $type_flags == 0 ? '' : 'flag-' . $type_flags . ' ';
1009
 
1010
  $current = $this->currentlang;
1011
- $list = $is_dropdown ? '<ul>' : '';
1012
- $destEx = explode( ',',$this->destination_l );
1013
- array_unshift( $destEx,$this->original_l );
1014
- foreach ( $destEx as $d ) {
1015
- if ( $d != $current ) {
1016
- $link = ($d != $this->original_l) ? $this->replaceUrl( $this->home_dir.$this->request_uri_no_language,$d ) : $this->home_dir.$this->request_uri_no_language;
1017
- if ( $link == $this->home_dir.'/' && get_option( 'wg_auto_switch' ) == 'on' ) {
1018
  $link = $link . '?no_lredirect=true';
1019
  }
1020
- $list .= '<li class="wg-li ' . $flag_class . $d . '"><a data-wg-notranslate href="' . $link . '">' . ($withname ? ($full ? WGUtils::getLangNameFromCode( $d,false ) : strtoupper( $d )) : '') . '</a></li>';
1021
  }
1022
  }
1023
  $list .= $is_dropdown ? '</ul>' : '';
1024
  $tag = $is_dropdown ? 'div' : 'li';
1025
 
1026
- $moreclass = (get_option( 'is_dropdown' ) == 'on') ? 'wg-drop ' : 'wg-list ';
1027
 
1028
  $aside1 = ($is_menu && ! $is_dropdown) ? '' : '<aside data-wg-notranslate class="' . $moreclass . 'country-selector closed" onclick="openClose(this);" >';
1029
  $aside2 = ($is_menu && ! $is_dropdown) ? '' : '</aside>';
1030
 
1031
- $button = '<!--Weglot ' . WEGLOT_VERSION . '-->' . $aside1 . '<' . $tag . ' data-wg-notranslate class="wgcurrent wg-li ' . $flag_class . $current . '"><a href="#" onclick="return false;" >' . ($withname ? ($full ? WGUtils::getLangNameFromCode( $current,false ) : strtoupper( $current )) : '') . '</a></' . $tag . '>' . $list . $aside2;
1032
 
1033
  return $button;
1034
  }
1035
  }
1036
 
1037
- register_activation_hook( __FILE__, array( 'Weglot', 'plugin_activate' ) );
1038
- register_deactivation_hook( __FILE__, array( 'Weglot', 'plugin_deactivate' ) );
1039
- register_uninstall_hook( __FILE__, array( 'Weglot', 'plugin_uninstall' ) );
1040
 
1041
- add_action( 'plugins_loaded', array( 'Weglot', 'Instance' ), 10 );
1
  <?php
2
  /**
3
  * @package Weglot
4
+ * @version 1.11
5
  */
6
 
7
  /*
12
  Author URI: https://weglot.com/
13
  Text Domain: weglot
14
  Domain Path: /languages/
15
+ Version: 1.11
16
  */
17
 
18
  /*
36
  * Exit if absolute path
37
  */
38
 
39
+ if (! defined('ABSPATH')) {
40
  exit;
41
  }
42
 
43
 
44
+ define('WEGLOT_VERSION', '1.11');
45
+ define('WEGLOT_DIR', dirname(__FILE__));
46
+ define('WEGLOT_BNAME', plugin_basename(__FILE__));
47
+ define('WEGLOT_DIRURL', plugin_dir_url(__FILE__));
48
+ define('WEGLOT_INC', WEGLOT_DIR . '/includes');
49
+ define('WEGLOT_RESURL', WEGLOT_DIRURL . 'resources/');
50
 
51
+ require_once WEGLOT_DIR . "/vendor/autoload.php";
52
+ require_once WEGLOT_DIR . '/simple_html_dom.php';
53
+ require_once WEGLOT_DIR . '/WeglotWidget.php';
54
 
55
+ use Weglot\Helpers\WeglotUtils;
56
+ use Weglot\Helpers\WeglotLang;
57
+ use Weglot\Notices\AdminNotices;
58
+ use Weglot\Third\Yoast\RedirectHandler;
59
 
60
+ $dirYoastPremum = plugin_dir_path(__DIR__) . "wordpress-seo-premium/premium/";
61
+ if(!function_exists('is_plugin_active')){
62
+ include_once(ABSPATH . 'wp-admin/includes/plugin.php');
63
+ }
64
 
65
+ // Override yoast redirect
66
+ if (
67
+ ! is_admin() &&
68
+ is_plugin_active("wordpress-seo-premium/wp-seo-premium.php") &&
69
+ file_exists($dirYoastPremum) &&
70
+ file_exists($dirYoastPremum . 'classes/redirect/redirect-handler.php') &&
71
+ file_exists($dirYoastPremum . 'classes/redirect/redirect-util.php')
72
+ ){
73
 
74
+ require_once $dirYoastPremum . 'classes/redirect/redirect-handler.php';
75
+ require_once $dirYoastPremum . 'classes/redirect/redirect-util.php';
76
+
77
+ $redirectHandler = new RedirectHandler();
78
+ $redirectHandler->load();
79
+ }
80
 
 
 
 
 
 
 
 
81
 
82
  /**
83
  * Singleton class Weglot */
84
+ class Weglot
85
+ {
86
  private $original_l;
87
  private $destination_l;
88
 
99
  *
100
  * @since 0.1
101
  */
102
+ private function __construct()
103
+ {
104
+ $this->services = array(
105
+ "AdminNotices" => new AdminNotices()
106
+ );
107
 
108
+ if (function_exists('apache_get_modules') && ! in_array('mod_rewrite', apache_get_modules())) {
109
+ $this->services["AdminNotices"]->wgRequireRewriteModule();
110
  return;
111
  }
112
 
113
+ $this->services["AdminNotices"]->thirdNotices();
114
+
 
 
115
 
116
+ add_action('plugins_loaded', array( $this, 'wg_load_textdomain' ));
117
+ add_action('init', array( $this, 'init_function' ), 11);
118
+ add_action('wp', array( $this, 'rr_404_my_event' ));
119
+ add_filter('plugin_action_links_' . plugin_basename(__FILE__), array( $this, 'wg_plugin_action_links' ));
120
 
121
+ $this->original_l = get_option('original_l');
122
+ $this->destination_l = get_option('destination_l');
123
 
124
+ $this->home_dir = $this->getHomeDirectory();
125
+ $this->request_uri = $this->getRequestUri($this->home_dir);
126
  $this->network_paths = $this->getListOfNetworkPath();
127
 
128
  $this->noredirect = false;
129
+ if (strpos($this->request_uri, '?no_lredirect=true') !== false) {
130
  $this->noredirect = true;
131
+ if (isset($_SERVER['REQUEST_URI'])) {
132
  $_SERVER['REQUEST_URI'] = str_replace(
133
+ '?no_lredirect=true',
134
+ '',
135
  $_SERVER['REQUEST_URI']
136
  );
137
  }
138
  }
 
 
 
 
139
 
140
+ $this->request_uri = str_replace('?no_lredirect=true', '', $this->request_uri);
141
+ $curr = $this->getLangFromUrl($this->request_uri);
142
+ $this->currentlang = $curr ? $curr : $this->original_l;
143
+ $this->request_uri_no_language = ($this->currentlang != $this->original_l) ? substr($this->request_uri, 3) : $this->request_uri;
144
+
145
+ if ($this->currentlang != $this->original_l) {
146
  $_SERVER['REQUEST_URI'] = str_replace(
147
  '/' . $this->currentlang .
148
+ '/',
149
+ '/',
150
+ $_SERVER['REQUEST_URI']
151
  );
152
  }
153
 
154
+ if (WeglotUtils::isLanguageRTL($this->currentlang)) {
155
  $GLOBALS['text_direction'] = 'rtl';
156
  } else {
157
  $GLOBALS['text_direction'] = 'ltr';
158
  }
159
 
160
+ add_filter('woocommerce_get_cart_url', array( $this,'filter_woocommerce_get_cart_url'));
161
+ add_filter('woocommerce_get_checkout_url', array( $this,'filter_woocommerce_get_cart_url'));
162
+ add_filter('woocommerce_get_checkout_order_received_url', array( $this, 'filter_woocommerce_get_checkout_order_received_url'));
163
+ add_action('woocommerce_reset_password_notification', array( $this, 'redirectUrlLostPassword'));
164
+
165
+ add_filter('woocommerce_login_redirect', array( $this,'wg_log_redirect'));
166
+ add_filter('woocommerce_registration_redirect', array( $this,'wg_log_redirect'));
167
+ add_filter('login_redirect', array( $this,'wg_log_redirect'));
168
+ add_filter('logout_redirect', array( $this,'wg_log_redirect'));
169
 
170
+ $activeTranslateEmail = apply_filters("weglot_active_translate_email", false);
171
+ if ($activeTranslateEmail) {
172
+ add_filter('wp_mail', array( $this, 'translate_emails'), 10, 1);
173
+ }
174
 
175
+ $apikey = get_option('project_key');
176
+ $this->translator = $apikey ? new \Weglot\Client\WeglotClient($apikey) : null;
177
 
178
+ $this->allowed = $apikey ? get_option('wg_allowed') : true;
 
 
179
 
180
+ if (is_admin()) {
181
+ if (strpos($this->request_uri, 'page=Weglot') !== false) {
182
+ if ($this->translator) {
183
  try {
184
  $this->userInfo = $this->translator->getUserInfo();
185
+ if ($this->userInfo) {
186
  $this->allowed = $this->userInfo['allowed'];
187
+ update_option('wg_allowed', $this->allowed ? 1 : 0);
188
  }
189
+ } catch (\Exception $e) {
190
  // If an exception occurs, do nothing, keep wg_allowed.
191
  ;
192
  }
193
  }
194
+ } elseif ($this->allowed == 0) {
195
+ $this->services["AdminNotices"]->wgExceededFreeLimit();
196
+ } elseif (!$apikey) {
197
+ $this->services["AdminNotices"]->wgNeedConfiguration();
198
  }
199
  }
200
 
201
 
202
+ $isURLOK = $this->isEligibleURL($this->request_uri_no_language);
203
+ if ($isURLOK) {
204
+ add_action('wp_head', array( $this, 'add_alternate' ));
205
+ add_action('widgets_init', array( $this, 'addWidget' ));
206
+ add_shortcode('weglot_switcher', array( $this, 'wg_switcher_creation' ));
207
+ if (get_option('is_menu') == 'on') {
208
+ add_filter('wp_nav_menu_items', 'your_custom_menu_item', 10, 2);
209
+ function your_custom_menu_item($items, $args)
210
+ {
211
  $button = Weglot::Instance()->returnWidgetCode();
212
  $items .= $button;
213
 
214
  return $items;
215
  }
216
  }
217
+ } else {
218
+ add_shortcode('weglot_switcher', array( $this, 'wg_switcher_creation_empty' ));
219
  }
220
+ }
221
+
222
+ /**
223
+ * Redirect URL Lost password for WooCommerce
224
+ */
225
+ public function redirectUrlLostPassword($url)
226
+ {
227
+ if ($this->currentlang === $this->original_l) {
228
+ return;
229
  }
230
+
231
+ $urlRedirect = add_query_arg('reset-link-sent', 'true', wc_get_account_endpoint_url('lost-password'));
232
+ $urlRedirect = $this->replaceUrl($urlRedirect, $this->currentlang);
233
+
234
+ wp_redirect($urlRedirect);
235
+ exit;
236
  }
237
 
238
  // Get our only instance of Weglot class
239
+ public static function Instance()
240
+ {
241
  static $inst = null;
242
+ if ($inst == null) {
243
  $inst = new Weglot();
244
  }
245
  return $inst;
246
  }
247
 
248
+ public static function plugin_activate()
249
+ {
250
+ add_option('with_flags', 'on');
251
+ add_option('with_name', 'on');
252
+ add_option('is_dropdown', 'on');
253
+ add_option('is_fullname', 'off');
254
+ add_option('override_css', '');
255
+ add_option('is_menu', 'off');
256
+ update_option('wg_allowed', 1);
257
+ if (get_option('permalink_structure') == '') {
258
+ add_option('wg_old_permalink_structure_empty', 'on');
259
+ update_option('permalink_structure', '/%year%/%monthnum%/%day%/%postname%/');
 
 
 
 
 
 
 
 
 
 
260
  }
261
  }
262
 
263
+ public static function plugin_deactivate()
264
+ {
265
  flush_rewrite_rules();
266
+ if (get_option('wg_old_permalink_structure_empty') == 'on') {
267
+ delete_option('wg_old_permalink_structure_empty');
268
+ update_option('permalink_structure', '');
269
  }
270
  }
271
 
272
+ public static function plugin_uninstall()
273
+ {
274
  flush_rewrite_rules();
275
+ delete_option('project_key');
276
+ delete_option('original_l');
277
+ delete_option('destination_l');
278
+ delete_option('show_box');
279
  }
280
 
281
+ public function wg_load_textdomain()
282
+ {
283
+ load_plugin_textdomain('weglot', false, dirname(WEGLOT_BNAME) . '/languages/');
284
  }
285
 
286
+ public function wg_plugin_action_links($links)
287
+ {
288
+ $links[] = '<a href="' . esc_url(get_admin_url(null, 'admin.php?page=Weglot')) . '">' . __('Settings', 'weglot') . '</a>';
289
  return $links;
290
  }
291
 
292
+ public function filter_woocommerce_get_cart_url($wc_get_page_permalink)
293
+ {
294
+ if ($this->currentlang != $this->original_l) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295
  return $this->replaceUrl($wc_get_page_permalink, $this->currentlang);
296
+ } else {
 
297
  return $wc_get_page_permalink;
298
  }
299
  }
300
 
301
+ public function filter_woocommerce_get_checkout_order_received_url($order_received_url)
302
+ {
303
+ if ($this->currentlang != $this->original_l) {
304
+ if (substr(get_option('permalink_structure'), -1) != '/') {
305
+ return str_replace('/?key', '?key', $this->replaceUrl($order_received_url, $this->currentlang));
306
+ } else {
307
+ return str_replace('//?key', '/?key', str_replace('?key', '/?key', $this->replaceUrl($order_received_url, $this->currentlang)));
308
+ }
309
+ } else {
310
+ if (isset($_SERVER['HTTP_REFERER'])) {
311
+ $l = $this->getLangFromUrl($this->URLToRelative($_SERVER['HTTP_REFERER']));
312
+ if ($l && $l != $this->original_l) {
313
+ if (substr(get_option('permalink_structure'), -1) != '/') {
314
+ return str_replace('/?key', '?key', $this->replaceUrl($order_received_url, $l));
315
+ } else {
316
+ return str_replace('//?key', '/?key', str_replace('?key', '/?key', $this->replaceUrl($order_received_url, $l)));
317
+ }
318
+ }
319
+ }
320
+ return $order_received_url;
321
+ }
322
+ }
323
+
324
+ public function wg_log_redirect($redirect_to)
325
+ {
326
+ if ($this->currentlang != $this->original_l) {
327
  return $this->replaceUrl($redirect_to, $this->currentlang);
328
+ } else {
329
+ if (isset($_SERVER['HTTP_REFERER'])) {
330
+ $l = $this->getLangFromUrl($this->URLToRelative($_SERVER['HTTP_REFERER']));
331
+ if ($l && $l != $this->original_l) {
 
332
  return $this->replaceUrl($redirect_to, $l);
333
  }
334
  }
336
  }
337
  }
338
 
339
+ public function translate_emails($args)
340
+ {
341
  $messageAndSubject = "<p>".$args['subject']."</p>".$args['message'];
342
 
343
+ if ($this->currentlang != $this->original_l) {
344
+ $messageAndSubjectTranslated = $this->translateEmail($messageAndSubject, $this->currentlang);
345
+ } elseif (isset($_SERVER['HTTP_REFERER'])) {
346
+ $l = $this->getLangFromUrl($this->URLToRelative($_SERVER['HTTP_REFERER']));
347
+ if ($l && $l != $this->original_l) { //If language in referer
348
+ $messageAndSubjectTranslated = $this->translateEmail($messageAndSubject, $l);
349
+ } elseif (strpos($_SERVER['HTTP_REFERER'], 'wg_language=') !== false) { //If language in parameter
350
+ $pos = strpos($_SERVER['HTTP_REFERER'], 'wg_language=');
 
 
351
  $start = $pos + strlen('wg_language=');
352
+ $l = substr($_SERVER['HTTP_REFERER'], $start, 2);
353
+ if ($l && $l != $this->original_l) {
354
+ $messageAndSubjectTranslated = $this->translateEmail($messageAndSubject, $l);
355
  }
356
  }
357
  }
358
 
359
  if (strpos($messageAndSubjectTranslated, '</p>') !== false) {
360
+ $pos = strpos($messageAndSubjectTranslated, '</p>') + 4;
361
+ $args['subject'] = substr($messageAndSubjectTranslated, 3, $pos - 7);
362
+ $args['message'] = substr($messageAndSubjectTranslated, $pos);
 
363
  }
364
  return $args;
365
  }
366
 
367
+ public function wg_switcher_creation()
368
+ {
369
  $button = Weglot::Instance()->returnWidgetCode();
370
+ echo wp_kses($button, $this->getAllowedTags());
371
  }
372
 
373
+ public function wg_switcher_creation_empty()
374
+ {
375
+ echo wp_kses("", $this->getAllowedTags());
376
  }
377
 
378
 
379
 
380
+ public function init_function()
381
+ {
382
+ add_action('admin_menu', array( $this, 'plugin_menu' ));
383
+ add_action('admin_init', array( $this, 'plugin_settings' ));
384
 
385
+ $dest = explode(',', $this->destination_l);
 
386
 
387
+ if ($this->request_uri == '/' && ! $this->noredirect && ! WeglotUtils::is_bot()) { // front_page
388
 
389
+ if (get_option('wg_auto_switch') == 'on' && isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
 
390
  /* Redirects to browser L */
391
+ $lang = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
392
  // exit(print_r($dest));
393
+ if (in_array($lang, $dest)) {
394
+ wp_safe_redirect($this->home_dir . "/$lang/");
395
  exit();
396
  }
397
  }
399
 
400
  /* prevent homepage redirect in canonical.php in case of show */
401
  $request_uri = $this->request_uri;
402
+ foreach ($dest as $d) {
403
+ if ($request_uri == '/' . $d . '/') {
404
  $thisL = $d;
405
  }
406
  }
407
+ $url = (isset($thisL) && $thisL != '') ? substr($request_uri, 3) : $request_uri;
408
 
409
+ if ($url == '/' && (isset($thisL) && $thisL != '') && 'page' == get_option('show_on_front')) {
410
+ add_action('template_redirect', array( $this, 'kill_canonical_wg_92103' ), 1);
411
  }
412
 
413
+ if (! is_admin() || (is_admin() && strpos($this->request_uri, 'page=Weglot') !== false)) {
414
  // Add JS
415
+ wp_register_script('wp-weglot-js', WEGLOT_RESURL . 'wp-weglot-js.js', false, WEGLOT_VERSION, false);
416
+ wp_enqueue_script('wp-weglot-js');
417
 
418
  // Add CSS
419
+ wp_register_style('wp-weglot-css', WEGLOT_RESURL . 'wp-weglot-css.css', false, WEGLOT_VERSION, false);
420
+ wp_enqueue_style('wp-weglot-css');
 
 
421
 
422
+ wp_add_inline_style('wp-weglot-css', $this->getInlineCSS());
423
+
424
+ if (is_admin()) {
425
  // Add Admin JS
426
+ wp_register_script('wp-weglot-admin-js', WEGLOT_RESURL . 'wp-weglot-admin-js.js', array( 'jquery' ), WEGLOT_VERSION, true);
427
+ wp_enqueue_script('wp-weglot-admin-js');
428
 
429
  // Add Admin CSS
430
+ wp_register_style('wp-weglot-admin-css', WEGLOT_RESURL . 'wp-weglot-admin-css.css', false, WEGLOT_VERSION, false);
431
+ wp_enqueue_style('wp-weglot-admin-css');
432
 
433
  // Add Selectize JS
434
+ wp_enqueue_script('jquery-ui', WEGLOT_RESURL . 'selectize/js/jquery-ui.min.js', array( 'jquery' ), WEGLOT_VERSION, true);
435
+ wp_enqueue_script('jquery-selectize', WEGLOT_RESURL . 'selectize/js/selectize.min.js', array( 'jquery' ), WEGLOT_VERSION, true);
436
  // wp_enqueue_style( 'selectize-css', WEGLOT_RESURL . 'selectize/css/selectize.css', array(), $ver );
437
+ wp_enqueue_style('selectize-defaut-css', WEGLOT_RESURL . 'selectize/css/selectize.default.css', array(), WEGLOT_VERSION);
438
 
439
+ if (! function_exists('is_plugin_active')) { // Need to refactor enqueue script
440
+ require_once(ABSPATH . '/wp-admin/includes/plugin.php');
441
+ }
442
+
443
+ if ($this->services["AdminNotices"]->hasGTranslatePlugin()) {
444
+ $customCss = "
445
+ .gt-admin-notice{
446
+ display:none !important;
447
+ }
448
+ ";
449
+
450
+ wp_add_inline_style('wp-weglot-css', $customCss);
451
+ }
452
  }
453
  }
454
 
455
  /* Putting it in init makes that buffer deeper than caching ob */
456
+ ob_start(array($this, 'treatPage' ));
457
  }
458
 
459
+ public function add_alternate()
460
+ {
461
+ if ($this->destination_l != '') {
462
 
463
  // $thisL = $this->currentlang;
464
+ $dest = explode(',', $this->destination_l);
465
 
466
+ $full_url = ($this->currentlang != $this->original_l) ? str_replace('/' . $this->currentlang . '/', '/', $this->full_url($_SERVER)) : $this->full_url($_SERVER);
467
+ $output = '<link rel="alternate" hreflang="' . $this->original_l . '" href="' . $full_url . '" />' . "\n";
468
+ foreach ($dest as $d) {
469
+ $output .= '<link rel="alternate" hreflang="' . $d . '" href="' . $this->replaceUrl($full_url, $d) . '" />' . "\n";
470
  }
471
 
472
  echo wp_kses($output, array(
473
  'link' => array(
474
  'rel' => array(),
475
+ 'hreflang' => array(),
476
+ 'href' => array())
477
  ));
478
  }
479
  }
480
 
481
+ public function getCurrentLang()
482
+ {
483
  return $this->currentlang;
484
  }
485
 
486
+ public function rr_404_my_event()
487
+ {
488
 
489
  // regex logic here
490
+ $isURLOK = $this->isEligibleURL($this->request_uri_no_language);
491
+ if (! $isURLOK && $this->currentlang != $this->original_l) {
492
  global $wp_query;
493
  $wp_query->set_404();
494
+ status_header(404);
495
  }
496
  }
497
 
498
+ public function kill_canonical_wg_92103()
499
+ {
500
+ add_action('redirect_canonical', '__return_false');
501
  }
502
 
503
+ public function plugin_menu()
504
+ {
505
+ $hook = add_menu_page('Weglot', 'Weglot', 'administrator', 'Weglot', array( $this, 'plugin_settings_page' ), WEGLOT_DIRURL . '/images/weglot_fav_bw.png');
506
 
507
+ // add_action('load-'.$hook,array($this, 'updateRewriteRule'));
508
+ if (isset($this->request_uri_no_language)
509
  // && isset( $_POST['settings-updated-nonce'] )
510
+ && $this->request_uri_no_language
511
+ && strpos($this->request_uri_no_language, 'page=Weglot') !== false
512
+ && strpos($this->request_uri_no_language, 'settings-updated=true') !==
513
  false) {
514
+ $d = explode(',', preg_replace('/\s+/', '', trim($this->destination_l, ',')));
515
+ $accepted = WeglotLang::getCodeLangs();
516
+ foreach ($d as $k => $l) {
517
+ if (! in_array($l, $accepted) || $l == $this->original_l) {
518
+ unset($d[ $k ]);
 
519
  }
520
  }
521
+ update_option('destination_l', implode(',', $d));
522
+ $this->destination_l = implode(',', $d);
523
 
524
  /* Display Box */
525
+ if (! get_option('show_box')) {
526
+ add_option('show_box', 'on');
527
  }
528
 
529
+ if ($this->userInfo['plan'] <= 0 || in_array($this->userInfo['plan'], array( 18, 19, 1001, 1002 ))) {
530
+ $d = explode(',', preg_replace('/\s+/', '', trim($this->destination_l, ',')));
531
  $this->destination_l = $d[0];
532
+ update_option('destination_l', $this->destination_l);
533
  }
534
  }
535
  }
536
 
537
+ public function plugin_settings()
538
+ {
539
+ register_setting('my-plugin-settings-group', 'project_key');
540
+ register_setting('my-plugin-settings-group', 'original_l');
541
+ register_setting('my-plugin-settings-group', 'destination_l');
542
+ register_setting('my-plugin-settings-group', 'wg_auto_switch');
543
+ register_setting('my-plugin-settings-group', 'override_css');
544
+ register_setting('my-plugin-settings-group', 'flag_css');
545
+ register_setting('my-plugin-settings-group', 'with_flags');
546
+ register_setting('my-plugin-settings-group', 'type_flags');
547
+ register_setting('my-plugin-settings-group', 'with_name');
548
+ register_setting('my-plugin-settings-group', 'is_dropdown');
549
+ register_setting('my-plugin-settings-group', 'is_fullname');
550
+ register_setting('my-plugin-settings-group', 'is_menu');
551
+ register_setting('my-plugin-settings-group', 'exclude_url');
552
+ register_setting('my-plugin-settings-group', 'exclude_blocks');
553
+ register_setting('my-plugin-settings-group', 'rtl_ltr_style');
554
  }
555
 
556
+ public function plugin_settings_page()
557
+ {
558
+ include(WEGLOT_DIR . '/includes/wg-settings-page.php');
559
  }
560
 
561
+ public function addWidget()
562
+ {
563
+ return register_widget('WeglotWidget');
564
  }
565
 
566
+ public function translateEmail($body, $l)
567
+ {
568
+ $translatedEmail = $this->translator->translateDomFromTo($body, $this->original_l, $l);
569
  return $translatedEmail;
570
  }
571
+ public function treatPage($final)
572
+ {
573
  $request_uri = $this->request_uri;
574
+ if (! is_admin() && strpos($request_uri, 'jax') === false && $this->original_l != '' && $this->destination_l != '') {
575
 
576
  // $final = file_get_contents(__DIR__.'/content.html'); //Testing purpose.
577
  // Get the original request
578
  $url = $this->request_uri_no_language;
579
+
580
+ if ($this->isEligibleURL($url) && WeglotUtils::is_HTML($final)) {
581
 
582
  // If a language is set, we translate the page & links.
583
+ if ($this->currentlang != $this->original_l) {
584
  try {
585
+ $l = $this->currentlang;
586
+ $final = $this->translatePageTo($final, $l);
587
+ } catch (\Weglot\Exceptions\WeglotException $e) {
588
  $final .= '<!--Weglot error : ' . $e->getMessage() . '-->';
589
+ if (strpos($e->getMessage(), 'NMC') !== false) {
590
+ update_option('wg_allowed', 0);
591
  }
592
+ } catch (\Exception $e) {
593
  $final .= '<!--Weglot error : ' . $e->getMessage() . '-->';
594
  }
595
  }
596
 
597
  // Place the button if we see short code
598
+ if (strpos($final, '<div id="weglot_here"></div>') !== false) {
 
599
  $button = $this->returnWidgetCode();
600
+ $final = str_replace('<div id="weglot_here"></div>', $button, $final);
601
  }
602
  // Place the button if we see short code
603
+ if (strpos($final, '<div class="weglot_here"></div>') !== false) {
 
604
  $button = $this->returnWidgetCode();
605
+ $final = str_replace(
606
+ '<div class="weglot_here"></div>',
607
+ $button,
608
+ $final
609
+ );
610
  }
611
 
612
  // Place the button if not in the page
613
+ if (strpos($final, 'class="wgcurrent') === false) {
614
+ $button = $this->returnWidgetCode(true);
615
+ $button = WeglotUtils::str_lreplace('<aside data-wg-notranslate class="', '<aside data-wg-notranslate class="wg-default ', $button);
616
+ $final = (strpos($final, '</body>') !== false) ? WeglotUtils::str_lreplace('</body>', $button . ' </body>', $final) : WeglotUtils::str_lreplace('</footer>', $button . ' </footer>', $final);
 
617
  }
618
+ {
619
+ return $final;
620
+ }
621
+ } elseif ($this->isEligibleURL($url) && isset($final[0]) && $final[0] == '{' || ($final[0] == '[' && (isset($final[1]) && $final[1] == '{'))) {
622
  $thisL = $this->getLangFromUrl(
623
  $this->URLToRelative(
624
  $_SERVER['HTTP_REFERER']
625
  )
626
  );
627
+ if (isset($thisL) && $thisL != '') {
628
  try {
629
+ if ($final[0] == '{' || ($final[0] == '[' && $final[1] == '{')) {
630
+ $json = json_decode($final, true);
631
+ if (json_last_error() == JSON_ERROR_NONE) {
632
+ $jsonT = $this->translateArray($json, $thisL);
633
+ return wp_json_encode($jsonT);
634
  } else {
635
  return $final;
636
  }
637
+ } elseif (WeglotUtils::is_AJAX_HTML($final)) {
638
+ return $this->translatePageTo($final, $thisL);
639
  } else {
640
  return $final;
641
  }
642
+ } catch (\Weglot\Exceptions\WeglotException $e) {
643
  return $final;
644
+ } catch (\Exception $e) {
645
  return $final;
646
  }
647
  } else {
648
  return $final;
649
  }
650
+ } else {
 
651
  return $final;
652
  }
653
+ } elseif ((strpos($request_uri, 'jax') !== false) &&
654
  $this->destination_l != '' && $this->original_l != '' && isset(
655
  $_SERVER['HTTP_REFERER']
656
+ ) && strpos($_SERVER['HTTP_REFERER'], 'admin') === false) {
 
657
  $thisL = $this->getLangFromUrl(
658
  $this->URLToRelative(
659
  $_SERVER['HTTP_REFERER']
660
  )
661
  );
662
+ if (isset($thisL) && $thisL != '') {
663
  try {
664
+ if ($final[0] == '{' || ($final[0] == '[' && $final[1] == '{')) {
665
+ $json = json_decode($final, true);
666
+ if (json_last_error() == JSON_ERROR_NONE) {
667
+ $jsonT = $this->translateArray($json, $thisL);
668
+ return wp_json_encode($jsonT);
669
  } else {
670
  return $final;
671
  }
672
+ } elseif (WeglotUtils::is_AJAX_HTML($final)) {
673
+ return $this->translatePageTo($final, $thisL);
674
  } else {
675
  return $final;
676
  }
677
+ } catch (\Weglot\Exceptions\WeglotException $e) {
678
  return $final;
679
+ } catch (\Exception $e) {
680
  return $final;
681
  }
682
  } else {
688
  }
689
 
690
  /* translation of the page */
691
+ public function translateArray($array, $to)
692
+ {
693
+ foreach ($array as $key => $val) {
694
+ if (is_array($val)) {
695
+ $array[ $key ] = $this->translateArray($val, $to);
696
  } else {
697
+ if (WeglotUtils::is_AJAX_HTML($val)) {
698
+ $array[ $key ] = $this->translatePageTo($val, $to);
699
+ } elseif (in_array($key, array('redirecturl', 'url'))) {
700
+ $array[ $key] = $this->replaceUrl($val, $to);
 
701
  }
702
  }
703
  }
704
  return $array;
705
  }
706
 
707
+ public function translatePageTo($final, $l)
708
+ {
709
+ if ($this->allowed == 0) {
710
  return $final . '<!--Not allowed-->';
711
  }
712
+
713
+ $translatedPage = $this->translator->translateDomFromTo($final, $this->original_l, $l); // $page is your html page
714
+
715
+ $this->modifyLink('/<a([^\>]+?)?href=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/', $translatedPage, $l, 'A');
716
+ $this->modifyLink('/<([^\>]+?)?data-link=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/', $translatedPage, $l, 'DATALINK');
717
+ $this->modifyLink('/<([^\>]+?)?data-url=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/', $translatedPage, $l, 'DATAURL');
718
+ $this->modifyLink('/<([^\>]+?)?data-cart-url=(\"|\')([^\s\>]+?)(\"|\')([^\>]+?)?>/', $translatedPage, $l, 'DATACART');
719
+ $this->modifyLink('/<form([^\>]+?)?action=(\"|\')([^\s\>]+?)(\"|\')/', $translatedPage, $l, 'FORM');
720
+ $this->modifyLink(
721
+ '/<option (.*?)?(\"|\')([^\s\>]+?)(\"|\')(.*?)?>/',
722
+ $translatedPage,
723
+ $l,
724
+ 'OPTION'
725
+ );
726
+ $this->modifyLink('/<link rel="canonical"(.*?)?href=(\"|\')([^\s\>]+?)(\"|\')/', $translatedPage, $l, 'LINK');
727
+ $this->modifyLink('/<meta property="og:url"(.*?)?content=(\"|\')([^\s\>]+?)(\"|\')/', $translatedPage, $l, 'META');
728
 
729
 
730
 
731
 
732
+ $translatedPage = preg_replace('/<html (.*?)?lang=(\"|\')(\S*)(\"|\')/', '<html $1lang=$2' . $l . '$4', $translatedPage);
733
+ $translatedPage = preg_replace('/property="og:locale" content=(\"|\')(\S*)(\"|\')/', 'property="og:locale" content=$1' . $l . '$3', $translatedPage);
734
  return $translatedPage;
735
  }
736
 
737
+ public function modifyLink($pattern, &$translatedPage, $l, $type)
738
+ {
739
  $admin_url = admin_url();
740
+ preg_match_all($pattern, $translatedPage, $out, PREG_PATTERN_ORDER);
741
+ for ($i = 0;$i < count($out[0]);$i++) {
742
+ $sometags = (isset($out[1])) ? $out[1][ $i ] : null;
743
+ $quote1 = (isset($out[2])) ? $out[2][ $i ] : null;
744
+ $current_url = (isset($out[3])) ? $out[3][ $i ] : null;
745
+ $quote2 = (isset($out[4])) ? $out[4][ $i ] : null;
746
+ $sometags2 = (isset($out[5])) ? $out[5][ $i ] : null;
747
+
748
+ $lengthLink = apply_filters("weglot_length_replace_a", 1500); // Prevent error on long URL (preg_match_all Compilation failed: regular expression is too large at offset)
749
+ if (strlen($current_url) >= $lengthLink) {
750
+ continue;
751
+ }
752
 
753
+ if ($this->checkLink($current_url, $admin_url, $sometags, $sometags2)) {
 
754
  $functionName = 'replace' .$type;
755
+ $this->$functionName(
756
+ $translatedPage,
757
+ $current_url,
758
+ $l,
759
+ $quote1,
760
+ $quote2,
761
+ $sometags,
762
+ $sometags2
763
+ );
764
  }
765
  }
766
  }
767
 
768
+ public function checkLink($current_url, $admin_url, $sometags = null, $sometags2 =
769
+ null)
770
+ {
771
+ $parsed_url = parse_url($current_url);
772
 
773
  return (
774
  (($current_url[0] == 'h' && $parsed_url['host'] == $_SERVER['HTTP_HOST'])
775
  || ($current_url[0] == '/' && $current_url[1] != '/'))
776
+ && strpos($current_url, $admin_url) === false
777
+ && strpos($current_url, 'wp-login') === false
778
  && !$this->isLinkAFile($current_url)
779
+ && $this->isEligibleURL($current_url)
780
+ && strpos($sometags, 'data-wg-notranslate') === false
781
+ && strpos($sometags2, 'data-wg-notranslate') === false
782
  );
783
  }
784
 
785
+ public function replaceA(
786
+ &$translatedPage,
787
+ $current_url,
788
+ $l,
789
+ $quote1,
790
+ $quote2,
791
+ $sometags = null,
792
+ $sometags2 = null
793
+ ) {
794
+
795
+ $translatedPage = preg_replace('/<a' . preg_quote($sometags, '/') . 'href=' .
796
+ preg_quote($quote1 . $current_url . $quote2, '/') . '/', '<a' . $sometags . 'href=' . $quote1 . $this->replaceUrl(
797
+ $current_url,
798
+ $l
799
+ ) . $quote2, $translatedPage);
800
  }
801
 
802
+ public function replaceDATALINK(&$translatedPage, $current_url, $l, $quote1, $quote2, $sometags = null, $sometags2 = null)
803
+ {
804
+ $translatedPage = preg_replace('/<' . preg_quote($sometags, '/') . 'data-link=' . preg_quote($quote1 . $current_url . $quote2, '/') . '/', '<' . $sometags . 'data-link=' . $quote1 . $this->replaceUrl(
805
+ $current_url,
806
+ $l
807
+ ) . $quote2, $translatedPage);
808
  }
809
 
810
+ public function replaceDATAURL(&$translatedPage, $current_url, $l, $quote1, $quote2, $sometags = null, $sometags2 = null)
811
+ {
812
+ $translatedPage = preg_replace('/<' . preg_quote($sometags, '/') . 'data-url=' . preg_quote($quote1 . $current_url . $quote2, '/') . '/', '<' . $sometags . 'data-url=' . $quote1 . $this->replaceUrl(
813
+ $current_url,
814
+ $l
815
+ ) . $quote2, $translatedPage);
816
  }
817
 
818
+ public function replaceDATACART(
819
+ &$translatedPage,
820
+ $current_url,
821
+ $l,
822
+ $quote1,
823
+ $quote2,
824
+ $sometags = null,
825
+ $sometags2 = null
826
+ ) {
827
+ $translatedPage = preg_replace('/<' . preg_quote($sometags, '/') . 'data-cart-url=' . preg_quote($quote1 . $current_url . $quote2, '/') . '/', '<' . $sometags . 'data-cart-url=' . $quote1 . $this->replaceUrl(
828
+ $current_url,
829
+ $l
830
+ ) . $quote2, $translatedPage);
831
  }
832
 
833
+ public function replaceFORM(
834
+ &$translatedPage,
835
+ $current_url,
836
+ $l,
837
+ $quote1,
838
+ $quote2,
839
+ $sometags = null,
840
+ $sometags2 = null
841
+ ) {
842
+ $translatedPage = preg_replace('/<form' . preg_quote($sometags, '/') . 'action=' . preg_quote($quote1 . $current_url . $quote2, '/') . '/', '<form ' . $sometags . 'action=' . $quote1 . $this->replaceUrl($current_url, $l) . $quote2, $translatedPage);
843
  }
844
 
845
+ public function replaceOPTION(
846
+ &$translatedPage,
847
+ $current_url,
848
+ $l,
849
+ $quote1,
850
+ $quote2,
851
+ $sometags = null,
852
+ $sometags2 = null
853
+ ) {
854
+ $translatedPage = preg_replace('/<option ' . preg_quote(
855
+ $sometags,
856
+ '/'
857
+ ) . preg_quote(
858
+ $quote1 . $current_url . $quote2,
859
+ '/'
860
+ ) . '(.*?)?>/', '<option ' . $sometags . $quote1 . $this->replaceUrl(
861
+ $current_url,
862
+ $l
863
+ ) . $quote2 . '$2>', $translatedPage);
864
  }
865
 
866
+ public function replaceLINK(
867
+ &$translatedPage,
868
+ $current_url,
869
+ $l,
870
+ $quote1,
871
+ $quote2,
872
+ $sometags = null,
873
+ $sometags2 = null
874
+ ) {
875
+ $translatedPage = preg_replace('/<link rel="canonical"' . preg_quote(
876
+ $sometags,
877
+ '/'
878
+ ) . 'href=' . preg_quote($quote1 . $current_url .
879
+ $quote2, '/') . '/', '<link rel="canonical"' . $sometags . 'href=' . $quote1 . $this->replaceUrl($current_url, $l) . $quote2, $translatedPage);
880
  }
881
 
882
+ public function replaceMETA(
883
+ &$translatedPage,
884
+ $current_url,
885
+ $l,
886
+ $quote1,
887
+ $quote2,
888
+ $sometags = null,
889
+ $sometags2 = null
890
+ ) {
891
+ $translatedPage = preg_replace('/<meta property="og:url"' . preg_quote(
892
+ $sometags,
893
+ '/'
894
+ ) . 'content=' . preg_quote($quote1 . $current_url
895
+ . $quote2, '/') . '/', '<meta property="og:url"' . $sometags . 'content=' . $quote1 . $this->replaceUrl($current_url, $l) . $quote2, $translatedPage);
896
  }
897
 
898
+ public function isLinkAFile($current_url)
899
+ {
900
  $files = array('pdf','rar','doc','docx','jpg','jpeg','png','ppt','pptx','xls','zip','mp4','xlsx');
901
  foreach ($files as $file) {
902
+ if (WeglotUtils::endsWith($current_url, '.'.$file)) {
903
  return true;
904
  }
905
  }
907
  }
908
 
909
  /* Urls functions */
910
+ public function replaceUrl($url, $l)
911
+ {
912
  //$home_dir = $this->home_dir;
913
 
914
+ $parsed_url = parse_url($url);
915
+ $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
916
+ $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
917
+ $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
918
+ $user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
919
+ $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
920
+ $pass = ($user || $pass) ? "$pass@" : '';
921
+ $path = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
922
+ $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
923
+ $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
924
 
925
 
926
+ if ($l == '') {
927
  return $url;
928
  } else {
929
+ $urlTranslated = (strlen($path) > 2 && substr($path, 0, 4) ==
930
  "/$l/") ?
931
  "$scheme$user$pass$host$port$path$query$fragment" : "$scheme$user$pass$host$port/$l$path$query$fragment";
932
 
933
  foreach ($this->network_paths as $np) {
934
+ if (strlen($np) > 2 && strpos($urlTranslated, $np) !==
935
  false) {
936
+ $urlTranslated = str_replace(
937
+ '/'.$l.$np,
938
+ $np.$l.'/',
939
+ $urlTranslated
940
+ );
941
  }
942
  }
943
 
944
  return $urlTranslated;
945
  }
 
946
  }
947
+ public function url_origin($s, $use_forwarded_host = false)
948
+ {
949
+ $ssl = (! empty($s['HTTPS']) && $s['HTTPS'] == 'on') ? true : false;
950
+ $sp = strtolower($s['SERVER_PROTOCOL']);
951
+ $protocol = substr($sp, 0, strpos($sp, '/')) . (($ssl) ? 's' : '');
952
+ $port = $s['SERVER_PORT'];
953
+ $port = ((! $ssl && $port == '80') || ($ssl && $port == '443')) ? '' : ':' . $port;
954
+ $host = ($use_forwarded_host && isset($s['HTTP_X_FORWARDED_HOST'])) ? $s['HTTP_X_FORWARDED_HOST'] : (isset($s['HTTP_HOST']) ? $s['HTTP_HOST'] : null);
955
+ $host = isset($host) ? $host : $s['SERVER_NAME'] . $port;
956
  return $protocol . '://' . $host;
957
  }
958
 
959
+ public function getListOfNetworkPath()
960
+ {
961
  $paths = array();
962
 
963
+ if (is_multisite()) {
964
  $sites = get_sites();
965
  foreach ($sites as $site) {
966
  $path = $site->path;
973
  return $paths;
974
  }
975
 
976
+ public function full_url($s, $use_forwarded_host = false)
977
+ {
978
+ return $this->url_origin($s, $use_forwarded_host) . $s['REQUEST_URI'];
979
  }
980
+ public function isEligibleURL($url)
981
+ {
982
+ $url = urldecode($this->URLToRelative($url));
 
983
  //Format exclude URL
984
  $excludeURL = get_option('exclude_url');
985
+
986
+ if (!empty($excludeURL)) {
987
+ $excludeURL = preg_replace('#\s+#', ',', trim($excludeURL));
988
+
989
+ $excludedUrls = explode(',', $excludeURL);
990
+ foreach ($excludedUrls as &$ex_url) {
991
  $ex_url = $this->URLToRelative($ex_url);
992
  }
993
+ $excludeURL = implode(',', $excludedUrls);
994
  }
995
 
996
 
997
+ $exclusions = preg_replace('#\s+#', ',', $excludeURL);
 
 
998
 
999
+ $listRegex = null;
1000
+ if(!empty($exclusions)) {
1001
+ $listRegex = explode(',', $exclusions);
1002
+ }
1003
+
1004
+
1005
+ $excludeAmp = apply_filters("weglot_exclude_amp", true);
1006
+ if ($excludeAmp) {
1007
+ $listRegex[] = apply_filters('weglot_regex_amp', '([&,\?,/])?amp(/)?');
1008
+ }
1009
+
1010
+ foreach ($listRegex as $regex) {
1011
+ $str = $this->escapeSlash($regex);
1012
+ $prepareRegex = sprintf('/%s/', $str);
1013
+ if (preg_match($prepareRegex, $url) === 1) {
1014
+ return false;
1015
  }
 
 
 
1016
  }
1017
+
1018
+ return true;
1019
  }
 
1020
 
1021
+ protected function escapeSlash($str)
1022
+ {
1023
+ return str_replace('/', '\/', $str);
1024
+ }
1025
+
1026
+ public function URLToRelative($url)
1027
+ {
1028
+ if ((substr($url, 0, 7) == 'http://') || (substr($url, 0, 8) == 'https://')) {
1029
  // the current link is an "absolute" URL - parse it to get just the path
1030
+ $parsed = parse_url($url);
1031
+ $path = isset($parsed['path']) ? $parsed['path'] : '';
1032
+ $query = isset($parsed['query']) ? '?' . $parsed['query'] : '';
1033
+ $fragment = isset($parsed['fragment']) ? '#' . $parsed['fragment'] : '';
1034
 
1035
+ if ($this->home_dir) {
1036
+ $relative = str_replace($this->home_dir, '', $path);
1037
 
1038
  return ($relative == '') ? '/' : $relative;
1039
  } else {
1042
  }
1043
  return $url;
1044
  }
1045
+ public function getRequestUri($home_dir)
1046
+ {
1047
+ if ($home_dir) {
1048
+ return str_replace($home_dir, '', $_SERVER['REQUEST_URI']);
1049
  } else {
1050
  return $_SERVER['REQUEST_URI'];
1051
  }
1052
  }
1053
+ public function getLangFromUrl($request_uri)
1054
+ {
1055
+ $l = null;
1056
+ $dest = explode(',', $this->destination_l);
1057
+ foreach ($dest as $d) {
1058
+ if (substr($request_uri, 0, 4) == '/' . $d . '/') {
1059
  $l = $d;
1060
  }
1061
  }
1068
  * return empty string otherwise
1069
  *
1070
  */
1071
+ public function getHomeDirectory()
1072
+ {
1073
+ $opt_siteurl = trim(get_option('siteurl'), '/');
1074
+ $opt_home = trim(get_option('home'), '/');
1075
+ if ($opt_siteurl != '' && $opt_home != '') {
1076
+ if ((substr($opt_home, 0, 7) == 'http://' && strpos(substr($opt_home, 7), '/') !== false) || (substr($opt_home, 0, 8) == 'https://' && strpos(substr($opt_home, 8), '/') !== false)) {
1077
+ $parsed_url = parse_url($opt_home);
1078
+ $path = isset($parsed_url['path']) ? $parsed_url['path'] : '/';
1079
  return $path;
1080
  }
1081
  }
1083
  }
1084
 
1085
  /* button function (code and CSS) */
1086
+ public function getInlineCSS()
1087
+ {
1088
+ $css = get_option('override_css');
1089
+ if ((WeglotUtils::isLanguageRTL($this->original_l) && ! WeglotUtils::isLanguageRTL($this->currentlang)) ||
1090
+ (! WeglotUtils::isLanguageRTL($this->original_l) && WeglotUtils::isLanguageRTL($this->currentlang))) {
1091
+ $css .= get_option('rtl_ltr_style');
1092
  }
1093
+ if (! is_admin()) {
1094
+ $css .= get_option('flag_css');
1095
  }
1096
  return $css;
1097
  }
1098
 
1099
+ public function getAllowedTags()
1100
+ {
1101
  return array(
1102
+ 'a' => array( 'href' => array(), 'title' =>
1103
  array(), 'onclick' => array(), 'target'
1104
+ => array(), 'data-wg-notranslate' => array() , 'class' => array()),
1105
+ 'div' => array('class' => array(), 'data-wg-notranslate' =>
1106
  array()),
1107
+ 'aside' => array('onclick' => array(), 'class' => array(), 'data-wg-notranslate' => array()),
1108
+ 'ul' => array('class' => array(), 'data-wg-notranslate' => array()),
1109
+ 'li' => array('class' => array(), 'data-wg-notranslate' => array())
 
1110
  );
1111
  }
1112
 
1113
+ public function returnWidgetCode($forceNoMenu = false)
1114
+ {
1115
+ $full = get_option('is_fullname') == 'on';
1116
+ $withname = get_option('with_name') == 'on';
1117
+ $is_dropdown = get_option('is_dropdown') == 'on';
1118
+ $is_menu = $forceNoMenu ? false : get_option('is_menu') == 'on';
1119
+ $flag_class = (get_option('with_flags') == 'on') ? 'wg-flags ' : '';
1120
 
1121
+ $type_flags = get_option('type_flags') ? get_option('type_flags') : 0;
1122
  $flag_class .= $type_flags == 0 ? '' : 'flag-' . $type_flags . ' ';
1123
 
1124
  $current = $this->currentlang;
1125
+ $list = $is_dropdown ? '<ul>' : '';
1126
+ $destEx = explode(',', $this->destination_l);
1127
+ array_unshift($destEx, $this->original_l);
1128
+ foreach ($destEx as $d) {
1129
+ if ($d != $current) {
1130
+ $link = ($d != $this->original_l) ? $this->replaceUrl($this->home_dir.$this->request_uri_no_language, $d) : $this->home_dir.$this->request_uri_no_language;
1131
+ if ($link == $this->home_dir.'/' && get_option('wg_auto_switch') == 'on') {
1132
  $link = $link . '?no_lredirect=true';
1133
  }
1134
+ $list .= '<li class="wg-li ' . $flag_class . $d . '"><a data-wg-notranslate href="' . $link . '">' . ($withname ? ($full ? WeglotUtils::getLangNameFromCode($d, false) : strtoupper($d)) : '') . '</a></li>';
1135
  }
1136
  }
1137
  $list .= $is_dropdown ? '</ul>' : '';
1138
  $tag = $is_dropdown ? 'div' : 'li';
1139
 
1140
+ $moreclass = (get_option('is_dropdown') == 'on') ? 'wg-drop ' : 'wg-list ';
1141
 
1142
  $aside1 = ($is_menu && ! $is_dropdown) ? '' : '<aside data-wg-notranslate class="' . $moreclass . 'country-selector closed" onclick="openClose(this);" >';
1143
  $aside2 = ($is_menu && ! $is_dropdown) ? '' : '</aside>';
1144
 
1145
+ $button = '<!--Weglot ' . WEGLOT_VERSION . '-->' . $aside1 . '<' . $tag . ' data-wg-notranslate class="wgcurrent wg-li ' . $flag_class . $current . '"><a href="#" onclick="return false;" >' . ($withname ? ($full ? WeglotUtils::getLangNameFromCode($current, false) : strtoupper($current)) : '') . '</a></' . $tag . '>' . $list . $aside2;
1146
 
1147
  return $button;
1148
  }
1149
  }
1150
 
1151
+ register_activation_hook(__FILE__, array( 'Weglot', 'plugin_activate' ));
1152
+ register_deactivation_hook(__FILE__, array( 'Weglot', 'plugin_deactivate' ));
1153
+ register_uninstall_hook(__FILE__, array( 'Weglot', 'plugin_uninstall' ));
1154
 
1155
+ add_action('plugins_loaded', array( 'Weglot', 'Instance' ), 10);