Cyr-To-Lat - Version 3.6.1

Version Description

(31.01.2019) = * Text domain corrected.

Download this release

Release Info

Developer mihdan
Plugin Icon 128x128 Cyr-To-Lat
Version 3.6.1
Comparing to
See all releases

Code changes from version 3.4 to 3.6.1

Files changed (123) hide show
  1. .editorconfig +22 -0
  2. css/cyr-to-lat-admin.css +61 -0
  3. cyr-to-lat.php +30 -285
  4. dist/js/settings/app.js +1 -0
  5. includes/class-cyr-to-lat-conversion-tables.php +166 -0
  6. includes/class-cyr-to-lat-main.php +215 -0
  7. includes/class-cyr-to-lat-settings.php +671 -0
  8. languages/cyr2lat-ru_RU.mo +0 -0
  9. languages/cyr2lat-ru_RU.po +84 -0
  10. languages/en_US.pot +81 -0
  11. readme.txt +17 -4
  12. vendor/autoload.php +7 -0
  13. vendor/autoload_52.php +7 -0
  14. vendor/composer/ClassLoader.php +445 -0
  15. vendor/composer/ClassLoader52.php +271 -0
  16. vendor/composer/LICENSE +56 -0
  17. vendor/composer/autoload_classmap.php +12 -0
  18. vendor/composer/autoload_namespaces.php +10 -0
  19. vendor/composer/autoload_psr4.php +10 -0
  20. vendor/composer/autoload_real.php +52 -0
  21. vendor/composer/autoload_real_52.php +44 -0
  22. vendor/composer/autoload_static.php +49 -0
  23. vendor/composer/installed.json +157 -0
  24. vendor/composer/installers/LICENSE +19 -0
  25. vendor/composer/installers/composer.json +105 -0
  26. vendor/composer/installers/src/Composer/Installers/AglInstaller.php +21 -0
  27. vendor/composer/installers/src/Composer/Installers/AimeosInstaller.php +9 -0
  28. vendor/composer/installers/src/Composer/Installers/AnnotateCmsInstaller.php +11 -0
  29. vendor/composer/installers/src/Composer/Installers/AsgardInstaller.php +49 -0
  30. vendor/composer/installers/src/Composer/Installers/AttogramInstaller.php +9 -0
  31. vendor/composer/installers/src/Composer/Installers/BaseInstaller.php +136 -0
  32. vendor/composer/installers/src/Composer/Installers/BitrixInstaller.php +126 -0
  33. vendor/composer/installers/src/Composer/Installers/BonefishInstaller.php +9 -0
  34. vendor/composer/installers/src/Composer/Installers/CakePHPInstaller.php +82 -0
  35. vendor/composer/installers/src/Composer/Installers/ChefInstaller.php +11 -0
  36. vendor/composer/installers/src/Composer/Installers/CiviCrmInstaller.php +9 -0
  37. vendor/composer/installers/src/Composer/Installers/ClanCatsFrameworkInstaller.php +10 -0
  38. vendor/composer/installers/src/Composer/Installers/CockpitInstaller.php +34 -0
  39. vendor/composer/installers/src/Composer/Installers/CodeIgniterInstaller.php +11 -0
  40. vendor/composer/installers/src/Composer/Installers/Concrete5Installer.php +13 -0
  41. vendor/composer/installers/src/Composer/Installers/CraftInstaller.php +35 -0
  42. vendor/composer/installers/src/Composer/Installers/CroogoInstaller.php +21 -0
  43. vendor/composer/installers/src/Composer/Installers/DecibelInstaller.php +10 -0
  44. vendor/composer/installers/src/Composer/Installers/DokuWikiInstaller.php +50 -0
  45. vendor/composer/installers/src/Composer/Installers/DolibarrInstaller.php +16 -0
  46. vendor/composer/installers/src/Composer/Installers/DrupalInstaller.php +16 -0
  47. vendor/composer/installers/src/Composer/Installers/ElggInstaller.php +9 -0
  48. vendor/composer/installers/src/Composer/Installers/EliasisInstaller.php +12 -0
  49. vendor/composer/installers/src/Composer/Installers/ExpressionEngineInstaller.php +29 -0
  50. vendor/composer/installers/src/Composer/Installers/EzPlatformInstaller.php +10 -0
  51. vendor/composer/installers/src/Composer/Installers/FuelInstaller.php +11 -0
  52. vendor/composer/installers/src/Composer/Installers/FuelphpInstaller.php +9 -0
  53. vendor/composer/installers/src/Composer/Installers/GravInstaller.php +30 -0
  54. vendor/composer/installers/src/Composer/Installers/HuradInstaller.php +25 -0
  55. vendor/composer/installers/src/Composer/Installers/ImageCMSInstaller.php +11 -0
  56. vendor/composer/installers/src/Composer/Installers/Installer.php +274 -0
  57. vendor/composer/installers/src/Composer/Installers/ItopInstaller.php +9 -0
  58. vendor/composer/installers/src/Composer/Installers/JoomlaInstaller.php +15 -0
  59. vendor/composer/installers/src/Composer/Installers/KanboardInstaller.php +18 -0
  60. vendor/composer/installers/src/Composer/Installers/KirbyInstaller.php +11 -0
  61. vendor/composer/installers/src/Composer/Installers/KodiCMSInstaller.php +10 -0
  62. vendor/composer/installers/src/Composer/Installers/KohanaInstaller.php +9 -0
  63. vendor/composer/installers/src/Composer/Installers/LanManagementSystemInstaller.php +27 -0
  64. vendor/composer/installers/src/Composer/Installers/LaravelInstaller.php +9 -0
  65. vendor/composer/installers/src/Composer/Installers/LavaLiteInstaller.php +10 -0
  66. vendor/composer/installers/src/Composer/Installers/LithiumInstaller.php +10 -0
  67. vendor/composer/installers/src/Composer/Installers/MODULEWorkInstaller.php +9 -0
  68. vendor/composer/installers/src/Composer/Installers/MODXEvoInstaller.php +16 -0
  69. vendor/composer/installers/src/Composer/Installers/MagentoInstaller.php +11 -0
  70. vendor/composer/installers/src/Composer/Installers/MajimaInstaller.php +37 -0
  71. vendor/composer/installers/src/Composer/Installers/MakoInstaller.php +9 -0
  72. vendor/composer/installers/src/Composer/Installers/MauticInstaller.php +25 -0
  73. vendor/composer/installers/src/Composer/Installers/MayaInstaller.php +33 -0
  74. vendor/composer/installers/src/Composer/Installers/MediaWikiInstaller.php +51 -0
  75. vendor/composer/installers/src/Composer/Installers/MicroweberInstaller.php +111 -0
  76. vendor/composer/installers/src/Composer/Installers/ModxInstaller.php +12 -0
  77. vendor/composer/installers/src/Composer/Installers/MoodleInstaller.php +57 -0
  78. vendor/composer/installers/src/Composer/Installers/OctoberInstaller.php +47 -0
  79. vendor/composer/installers/src/Composer/Installers/OntoWikiInstaller.php +24 -0
  80. vendor/composer/installers/src/Composer/Installers/OsclassInstaller.php +14 -0
  81. vendor/composer/installers/src/Composer/Installers/OxidInstaller.php +59 -0
  82. vendor/composer/installers/src/Composer/Installers/PPIInstaller.php +9 -0
  83. vendor/composer/installers/src/Composer/Installers/PhiftyInstaller.php +11 -0
  84. vendor/composer/installers/src/Composer/Installers/PhpBBInstaller.php +11 -0
  85. vendor/composer/installers/src/Composer/Installers/PimcoreInstaller.php +21 -0
  86. vendor/composer/installers/src/Composer/Installers/PiwikInstaller.php +32 -0
  87. vendor/composer/installers/src/Composer/Installers/PlentymarketsInstaller.php +29 -0
  88. vendor/composer/installers/src/Composer/Installers/Plugin.php +17 -0
  89. vendor/composer/installers/src/Composer/Installers/PortoInstaller.php +9 -0
  90. vendor/composer/installers/src/Composer/Installers/PrestashopInstaller.php +10 -0
  91. vendor/composer/installers/src/Composer/Installers/PuppetInstaller.php +11 -0
  92. vendor/composer/installers/src/Composer/Installers/PxcmsInstaller.php +63 -0
  93. vendor/composer/installers/src/Composer/Installers/RadPHPInstaller.php +24 -0
  94. vendor/composer/installers/src/Composer/Installers/ReIndexInstaller.php +10 -0
  95. vendor/composer/installers/src/Composer/Installers/RedaxoInstaller.php +10 -0
  96. vendor/composer/installers/src/Composer/Installers/RoundcubeInstaller.php +22 -0
  97. vendor/composer/installers/src/Composer/Installers/SMFInstaller.php +10 -0
  98. vendor/composer/installers/src/Composer/Installers/ShopwareInstaller.php +60 -0
  99. vendor/composer/installers/src/Composer/Installers/SilverStripeInstaller.php +35 -0
  100. vendor/composer/installers/src/Composer/Installers/SiteDirectInstaller.php +25 -0
  101. vendor/composer/installers/src/Composer/Installers/SyDESInstaller.php +49 -0
  102. vendor/composer/installers/src/Composer/Installers/Symfony1Installer.php +26 -0
  103. vendor/composer/installers/src/Composer/Installers/TYPO3CmsInstaller.php +16 -0
  104. vendor/composer/installers/src/Composer/Installers/TYPO3FlowInstaller.php +38 -0
  105. vendor/composer/installers/src/Composer/Installers/TheliaInstaller.php +12 -0
  106. vendor/composer/installers/src/Composer/Installers/TuskInstaller.php +14 -0
  107. vendor/composer/installers/src/Composer/Installers/UserFrostingInstaller.php +9 -0
  108. vendor/composer/installers/src/Composer/Installers/VanillaInstaller.php +10 -0
  109. vendor/composer/installers/src/Composer/Installers/VgmcpInstaller.php +49 -0
  110. vendor/composer/installers/src/Composer/Installers/WHMCSInstaller.php +10 -0
  111. vendor/composer/installers/src/Composer/Installers/WolfCMSInstaller.php +9 -0
  112. vendor/composer/installers/src/Composer/Installers/WordPressInstaller.php +12 -0
  113. vendor/composer/installers/src/Composer/Installers/YawikInstaller.php +32 -0
  114. vendor/composer/installers/src/Composer/Installers/ZendInstaller.php +11 -0
  115. vendor/composer/installers/src/Composer/Installers/ZikulaInstaller.php +10 -0
  116. vendor/composer/installers/src/bootstrap.php +13 -0
  117. vendor/xrstf/composer-php52/.gitignore +1 -0
  118. vendor/xrstf/composer-php52/LICENSE +19 -0
  119. vendor/xrstf/composer-php52/README.md +37 -0
  120. vendor/xrstf/composer-php52/composer.json +26 -0
  121. vendor/xrstf/composer-php52/lib/xrstf/Composer52/AutoloadGenerator.php +346 -0
  122. vendor/xrstf/composer-php52/lib/xrstf/Composer52/ClassLoader.php +271 -0
  123. vendor/xrstf/composer-php52/lib/xrstf/Composer52/Generator.php +39 -0
.editorconfig ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is for unifying the coding style for different editors and IDEs
2
+ # editorconfig.org
3
+
4
+ # WordPress Coding Standards
5
+ # https://make.wordpress.org/core/handbook/coding-standards/
6
+
7
+ root = true
8
+
9
+ [*]
10
+ charset = utf-8
11
+ end_of_line = lf
12
+ insert_final_newline = true
13
+ trim_trailing_whitespace = true
14
+ indent_style = tab
15
+ indent_size = 4
16
+
17
+ [{.jshintrc,*.json,*.yml}]
18
+ indent_style = space
19
+ indent_size = 2
20
+
21
+ [{*.txt,wp-config-sample.php}]
22
+ end_of_line = crlf
css/cyr-to-lat-admin.css ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .ctl-col {
2
+ float: left;
3
+ }
4
+
5
+ .ctl-col.left {
6
+ /* width: 70%; */
7
+ }
8
+
9
+ .ctl-col.right {
10
+ width: 30%;
11
+ }
12
+
13
+ #ctl-options .form-table:not(:nth-child(2)) th {
14
+ display: none;
15
+ }
16
+
17
+ .ctl-table {
18
+ display: none;
19
+ }
20
+
21
+ #ctl-options .nav-tab {
22
+ cursor: pointer;
23
+ margin-bottom: -1px;
24
+ }
25
+
26
+ #ctl-options .nav-tab-active {
27
+ border-bottom: 1px solid #f1f1f1;
28
+ background: #f1f1f1;
29
+ }
30
+
31
+ .ctl-table.active {
32
+ display: block;
33
+ }
34
+
35
+ .ctl-table-cell {
36
+ float: left;
37
+ }
38
+
39
+ .ctl-table-cell label {
40
+ width: 2.4em;
41
+ display: inline-block;
42
+ text-align: right;
43
+ margin-right: 0.2em;
44
+ }
45
+
46
+ .ctl-table-cell input {
47
+ width: 3em !important;
48
+ display: inline-block !important;
49
+ }
50
+
51
+ .ctl-col.right form input[name="submit"] {
52
+ cursor: pointer;
53
+ padding: 0;
54
+ margin: 0;
55
+ }
56
+
57
+ @media screen and (max-width: 767px) {
58
+ .ctl-col.left, .ctl-col.right {
59
+ width: 100%;
60
+ }
61
+ }
cyr-to-lat.php CHANGED
@@ -1,317 +1,62 @@
1
  <?php
2
  /**
 
 
3
  * Plugin Name: Cyr-To-Lat
4
- * Plugin URI: http://wordpress.org/extend/plugins/cyr2lat/
5
  * Description: Converts Cyrillic characters in post and term slugs to Latin characters. Useful for creating human-readable URLs. Based on the original plugin by Anton Skorobogatov.
6
  * Author: Sergey Biryukov, Mikhail Kobzarev
7
- * Author URI: http://ru.wordpress.org/
8
  * Requires at least: 2.3
9
  * Tested up to: 5.1
10
- * Version: 3.4
 
 
 
 
 
 
 
11
  */
12
 
13
  if ( ! defined( 'ABSPATH' ) ) {
14
- exit;
15
  }
16
 
17
  /**
18
- * Sanitize title
19
- *
20
- * @param string $title Post title.
21
- *
22
- * @return string
23
  */
24
- function ctl_sanitize_title( $title ) {
25
- global $wpdb;
26
-
27
- $pre = apply_filters( 'ctl_pre_sanitize_title', false, $title );
28
-
29
- if ( false !== $pre ) {
30
- return $pre;
31
- }
32
-
33
- $iso9_table = array(
34
- 'А' => 'A',
35
- 'Б' => 'B',
36
- 'В' => 'V',
37
- 'Г' => 'G',
38
- 'Ѓ' => 'G',
39
- 'Ґ' => 'G',
40
- 'Д' => 'D',
41
- 'Е' => 'E',
42
- 'Ё' => 'YO',
43
- 'Є' => 'YE',
44
- 'Ж' => 'ZH',
45
- 'З' => 'Z',
46
- 'Ѕ' => 'Z',
47
- 'И' => 'I',
48
- 'Й' => 'J',
49
- 'Ј' => 'J',
50
- 'І' => 'I',
51
- 'Ї' => 'YI',
52
- 'К' => 'K',
53
- 'Ќ' => 'K',
54
- 'Л' => 'L',
55
- 'Љ' => 'L',
56
- 'М' => 'M',
57
- 'Н' => 'N',
58
- 'Њ' => 'N',
59
- 'О' => 'O',
60
- 'П' => 'P',
61
- 'Р' => 'R',
62
- 'С' => 'S',
63
- 'Т' => 'T',
64
- 'У' => 'U',
65
- 'Ў' => 'U',
66
- 'Ф' => 'F',
67
- 'Х' => 'H',
68
- 'Ц' => 'TS',
69
- 'Ч' => 'CH',
70
- 'Џ' => 'DH',
71
- 'Ш' => 'SH',
72
- 'Щ' => 'SHH',
73
- 'Ъ' => '',
74
- 'Ы' => 'Y',
75
- 'Ь' => '',
76
- 'Э' => 'E',
77
- 'Ю' => 'YU',
78
- 'Я' => 'YA',
79
- 'а' => 'a',
80
- 'б' => 'b',
81
- 'в' => 'v',
82
- 'г' => 'g',
83
- 'ѓ' => 'g',
84
- 'ґ' => 'g',
85
- 'д' => 'd',
86
- 'е' => 'e',
87
- 'ё' => 'yo',
88
- 'є' => 'ye',
89
- 'ж' => 'zh',
90
- 'з' => 'z',
91
- 'ѕ' => 'z',
92
- 'и' => 'i',
93
- 'й' => 'j',
94
- 'ј' => 'j',
95
- 'і' => 'i',
96
- 'ї' => 'yi',
97
- 'к' => 'k',
98
- 'ќ' => 'k',
99
- 'л' => 'l',
100
- 'љ' => 'l',
101
- 'м' => 'm',
102
- 'н' => 'n',
103
- 'њ' => 'n',
104
- 'о' => 'o',
105
- 'п' => 'p',
106
- 'р' => 'r',
107
- 'с' => 's',
108
- 'т' => 't',
109
- 'у' => 'u',
110
- 'ў' => 'u',
111
- 'ф' => 'f',
112
- 'х' => 'h',
113
- 'ц' => 'ts',
114
- 'ч' => 'ch',
115
- 'џ' => 'dh',
116
- 'ш' => 'sh',
117
- 'щ' => 'shh',
118
- 'ъ' => '',
119
- 'ы' => 'y',
120
- 'ь' => '',
121
- 'э' => 'e',
122
- 'ю' => 'yu',
123
- 'я' => 'ya',
124
- );
125
-
126
- // Locales list - https://make.wordpress.org/polyglots/teams/
127
- $locale = get_locale();
128
- switch ( $locale ) {
129
- case 'bg_BG':
130
- $iso9_table['Щ'] = 'SHT';
131
- $iso9_table['щ'] = 'sht';
132
- $iso9_table['Ъ'] = 'A';
133
- $iso9_table['ъ'] = 'a';
134
- break;
135
- case 'uk':
136
- $iso9_table['И'] = 'Y';
137
- $iso9_table['и'] = 'y';
138
- break;
139
- case 'ka_GE':
140
- $iso9_table['ა'] = 'a';
141
- $iso9_table['ბ'] = 'b';
142
- $iso9_table['გ'] = 'g';
143
- $iso9_table['დ'] = 'd';
144
- $iso9_table['ე'] = 'e';
145
- $iso9_table['ვ'] = 'v';
146
- $iso9_table['ზ'] = 'z';
147
- $iso9_table['თ'] = 'th';
148
- $iso9_table['ი'] = 'i';
149
- $iso9_table['კ'] = 'k';
150
- $iso9_table['ლ'] = 'l';
151
- $iso9_table['მ'] = 'm';
152
- $iso9_table['ნ'] = 'n';
153
- $iso9_table['ო'] = 'o';
154
- $iso9_table['პ'] = 'p';
155
- $iso9_table['ჟ'] = 'zh';
156
- $iso9_table['რ'] = 'r';
157
- $iso9_table['ს'] = 's';
158
- $iso9_table['ტ'] = 't';
159
- $iso9_table['უ'] = 'u';
160
- $iso9_table['ფ'] = 'ph';
161
- $iso9_table['ქ'] = 'q';
162
- $iso9_table['ღ'] = 'gh';
163
- $iso9_table['ყ'] = 'qh';
164
- $iso9_table['შ'] = 'sh';
165
- $iso9_table['ჩ'] = 'ch';
166
- $iso9_table['ც'] = 'ts';
167
- $iso9_table['ძ'] = 'dz';
168
- $iso9_table['წ'] = 'ts';
169
- $iso9_table['ჭ'] = 'tch';
170
- $iso9_table['ხ'] = 'kh';
171
- $iso9_table['ჯ'] = 'j';
172
- $iso9_table['ჰ'] = 'h';
173
- break;
174
- }
175
-
176
- $is_term = false;
177
- // @codingStandardsIgnoreLine
178
- $backtrace = debug_backtrace();
179
- foreach ( $backtrace as $backtrace_entry ) {
180
- if ( 'wp_insert_term' === $backtrace_entry['function'] ) {
181
- $is_term = true;
182
- break;
183
- }
184
- }
185
-
186
- $term = $is_term ? $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE name = %s", $title ) ) : '';
187
-
188
- if ( ! empty( $term ) ) {
189
- $title = $term;
190
- } else {
191
- $title = strtr( $title, apply_filters( 'ctl_table', $iso9_table ) );
192
-
193
- if ( function_exists( 'iconv' ) ) {
194
- $title = iconv( 'UTF-8', 'UTF-8//TRANSLIT//IGNORE', $title );
195
- }
196
-
197
- $title = preg_replace( "/[^A-Za-z0-9'_\-\.]/", '-', $title );
198
- $title = preg_replace( '/\-+/', '-', $title );
199
- $title = trim( $title, '-' );
200
- }
201
-
202
- return $title;
203
- }
204
-
205
- add_filter( 'sanitize_title', 'ctl_sanitize_title', 9 );
206
- add_filter( 'sanitize_file_name', 'ctl_sanitize_title' );
207
 
208
  /**
209
- * Convert Existing Slugs
210
  */
211
- function ctl_convert_existing_slugs() {
212
- global $wpdb;
213
-
214
- $posts = $wpdb->get_results( "SELECT ID, post_name FROM $wpdb->posts WHERE post_name REGEXP('[^A-Za-z0-9\-]+') AND post_status IN ('publish', 'future', 'private')" );
215
-
216
- foreach ( (array) $posts as $post ) {
217
- $sanitized_name = ctl_sanitize_title( urldecode( $post->post_name ) );
218
-
219
- if ( $post->post_name !== $sanitized_name ) {
220
- add_post_meta( $post->ID, '_wp_old_slug', $post->post_name );
221
- $wpdb->update( $wpdb->posts, array( 'post_name' => $sanitized_name ), array( 'ID' => $post->ID ) );
222
- }
223
- }
224
-
225
- $terms = $wpdb->get_results( "SELECT term_id, slug FROM $wpdb->terms WHERE slug REGEXP('[^A-Za-z0-9\-]+') " );
226
-
227
- foreach ( (array) $terms as $term ) {
228
- $sanitized_slug = ctl_sanitize_title( urldecode( $term->slug ) );
229
-
230
- if ( $term->slug !== $sanitized_slug ) {
231
- $wpdb->update( $wpdb->terms, array( 'slug' => $sanitized_slug ), array( 'term_id' => $term->term_id ) );
232
- }
233
- }
234
- }
235
-
236
- function ctl_schedule_conversion() {
237
- add_action( 'shutdown', 'ctl_convert_existing_slugs' );
238
- }
239
-
240
- register_activation_hook( __FILE__, 'ctl_schedule_conversion' );
241
 
242
  /**
243
- * Check if Classic Editor plugin is active.
244
- *
245
- * @link https://kagg.eu/how-to-catch-gutenberg/
246
- *
247
- * @return bool
248
  */
249
- function ctl_is_classic_editor_plugin_active() {
250
- if ( ! function_exists( 'is_plugin_active' ) ) {
251
- include_once ABSPATH . 'wp-admin/includes/plugin.php';
252
- }
253
-
254
- if ( is_plugin_active( 'classic-editor/classic-editor.php' ) ) {
255
- return true;
256
- }
257
-
258
- return false;
259
- }
260
 
261
  /**
262
- * Check if Block Editor is active.
263
- * Must only be used after plugins_loaded action is fired.
264
- *
265
- * @link https://kagg.eu/how-to-catch-gutenberg/
266
- *
267
- * @return bool
268
  */
269
- function ctl_is_gutenberg_editor_active() {
270
-
271
- // Gutenberg plugin is installed and activated.
272
- $gutenberg = ! ( false === has_filter( 'replace_editor', 'gutenberg_init' ) );
273
-
274
- // Block editor since 5.0.
275
- $block_editor = version_compare( $GLOBALS['wp_version'], '5.0-beta', '>' );
276
-
277
- if ( ! $gutenberg && ! $block_editor ) {
278
- return false;
279
- }
280
-
281
- if ( ctl_is_classic_editor_plugin_active() ) {
282
- $editor_option = get_option( 'classic-editor-replace' );
283
- $block_editor_active = array( 'no-replace', 'block' );
284
-
285
- return in_array( $editor_option, $block_editor_active, true );
286
- }
287
-
288
- return true;
289
- }
290
 
291
  /**
292
- * Gutenberg support
293
- *
294
- * @param array $data An array of slashed post data.
295
- * @param array $postarr An array of sanitized, but otherwise unmodified post data.
296
- *
297
- * @return mixed
298
  */
299
- function ctl_sanitize_post_name( $data, $postarr ) {
300
 
301
- if ( ! ctl_is_gutenberg_editor_active() ) {
302
- return $data;
303
- }
304
 
305
- if (
306
- ! $data['post_name'] && $data['post_title'] &&
307
- ! in_array( $data['post_status'], array( 'auto-draft', 'revision' ), true )
308
- ) {
309
- $data['post_name'] = sanitize_title( $data['post_title'] );
310
  }
311
 
312
- return $data;
313
  }
314
 
315
- add_filter( 'wp_insert_post_data', 'ctl_sanitize_post_name', 10, 2 );
316
-
317
- // eof;
1
  <?php
2
  /**
3
+ * Cyr-To-Lat
4
+ *
5
  * Plugin Name: Cyr-To-Lat
6
+ * Plugin URI: https://wordpress.org/plugins/cyr2lat/
7
  * Description: Converts Cyrillic characters in post and term slugs to Latin characters. Useful for creating human-readable URLs. Based on the original plugin by Anton Skorobogatov.
8
  * Author: Sergey Biryukov, Mikhail Kobzarev
9
+ * Author URI: https://profiles.wordpress.org/sergeybiryukov/
10
  * Requires at least: 2.3
11
  * Tested up to: 5.1
12
+ * Version: 3.6.1
13
+ * Stable tag: 3.6.1
14
+ *
15
+ * Text Domain: cyr-to-lat
16
+ * Domain Path: /languages/
17
+ *
18
+ * @package cyr-to-lat
19
+ * @author Sergey Biryukov, Mikhail Kobzarev
20
  */
21
 
22
  if ( ! defined( 'ABSPATH' ) ) {
23
+ exit; // Exit if accessed directly.
24
  }
25
 
26
  /**
27
+ * Path to the plugin dir.
 
 
 
 
28
  */
29
+ define( 'CYR_TO_LAT_PATH', dirname( __FILE__ ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
 
31
  /**
32
+ * Plugin dir url.
33
  */
34
+ define( 'CYR_TO_LAT_URL', untrailingslashit( plugin_dir_url( __FILE__ ) ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  /**
37
+ * Main plugin file.
 
 
 
 
38
  */
39
+ define( 'CYR_TO_LAT_FILE', __FILE__ );
 
 
 
 
 
 
 
 
 
 
40
 
41
  /**
42
+ * Plugin version.
 
 
 
 
 
43
  */
44
+ define( 'CYR_TO_LAT_VERSION', '3.6.1' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  /**
47
+ * Init plugin class on plugin load.
 
 
 
 
 
48
  */
 
49
 
50
+ static $plugin;
 
 
51
 
52
+ if ( ! isset( $plugin ) ) {
53
+ if ( version_compare( PHP_VERSION, '5.3.0' ) >= 0 ) {
54
+ require_once CYR_TO_LAT_PATH . '/vendor/autoload.php';
55
+ } else {
56
+ require_once CYR_TO_LAT_PATH . '/vendor/autoload_52.php';
57
  }
58
 
59
+ $plugin = new Cyr_To_Lat_Main();
60
  }
61
 
62
+ // eof.
 
 
dist/js/settings/app.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:n})},r.r=function(t){Object.defineProperty(t,"__esModule",{value:!0})},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=3)}([function(t,e,r){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=function(){function t(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(e,r,n){return r&&t(e.prototype,r),n&&t(e,n),e}}();function o(t){if(Array.isArray(t)){for(var e=0,r=Array(t.length);e<t.length;e++)r[e]=t[e];return r}return Array.from(t)}var i=function(){function t(){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.hideTables(),this.bindEvents()}return n(t,[{key:"hideTables",value:function(){var t=[].concat(o(document.querySelectorAll("#ctl-options table")));t.shift(),t.map(function(t,e){if(t.classList.add("ctl-table"),0===e){t.classList.add("active");var r=document.createElement("ul");r.classList.add("nav-tab-wrapper"),t.parentNode.insertBefore(r,t)}});var e=[].concat(o(document.querySelectorAll("#ctl-options h2")));e.shift(),e.map(function(t,e){t.classList.add("nav-tab"),t.dataset.index=e,document.querySelector("#ctl-options ul").appendChild(t),0===e&&t.classList.add("nav-tab-active")})}},{key:"bindEvents",value:function(){[].concat(o(document.querySelectorAll("#ctl-options ul h2"))).map(function(t){t.onclick=function(t){t.preventDefault();var e=t.target.dataset.index;[].concat(o(document.querySelectorAll("#ctl-options ul h2"))).map(function(t){t.classList.remove("nav-tab-active")}),t.target.classList.add("nav-tab-active");var r=[].concat(o(document.querySelectorAll(".ctl-table")));return r.map(function(t){t.classList.remove("active")}),r[e].classList.add("active"),!1}})}}]),t}();e.default=i},function(t,e,r){"use strict";var n=function(t){return t&&t.__esModule?t:{default:t}}(r(0));document.addEventListener("DOMContentLoaded",function(){new n.default})},function(t,e){!function(t){"use strict";if(!t.fetch){var e={searchParams:"URLSearchParams"in t,iterable:"Symbol"in t&&"iterator"in Symbol,blob:"FileReader"in t&&"Blob"in t&&function(){try{return new Blob,!0}catch(t){return!1}}(),formData:"FormData"in t,arrayBuffer:"ArrayBuffer"in t};if(e.arrayBuffer)var r=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],n=function(t){return t&&DataView.prototype.isPrototypeOf(t)},o=ArrayBuffer.isView||function(t){return t&&r.indexOf(Object.prototype.toString.call(t))>-1};c.prototype.append=function(t,e){t=a(t),e=u(e);var r=this.map[t];this.map[t]=r?r+","+e:e},c.prototype.delete=function(t){delete this.map[a(t)]},c.prototype.get=function(t){return t=a(t),this.has(t)?this.map[t]:null},c.prototype.has=function(t){return this.map.hasOwnProperty(a(t))},c.prototype.set=function(t,e){this.map[a(t)]=u(e)},c.prototype.forEach=function(t,e){for(var r in this.map)this.map.hasOwnProperty(r)&&t.call(e,this.map[r],r,this)},c.prototype.keys=function(){var t=[];return this.forEach(function(e,r){t.push(r)}),f(t)},c.prototype.values=function(){var t=[];return this.forEach(function(e){t.push(e)}),f(t)},c.prototype.entries=function(){var t=[];return this.forEach(function(e,r){t.push([r,e])}),f(t)},e.iterable&&(c.prototype[Symbol.iterator]=c.prototype.entries);var i=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];b.prototype.clone=function(){return new b(this,{body:this._bodyInit})},p.call(b.prototype),p.call(v.prototype),v.prototype.clone=function(){return new v(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new c(this.headers),url:this.url})},v.error=function(){var t=new v(null,{status:0,statusText:""});return t.type="error",t};var s=[301,302,303,307,308];v.redirect=function(t,e){if(-1===s.indexOf(e))throw new RangeError("Invalid status code");return new v(null,{status:e,headers:{location:t}})},t.Headers=c,t.Request=b,t.Response=v,t.fetch=function(t,r){return new Promise(function(n,o){var i=new b(t,r),s=new XMLHttpRequest;s.onload=function(){var t={status:s.status,statusText:s.statusText,headers:function(t){var e=new c;return t.split(/\r?\n/).forEach(function(t){var r=t.split(":"),n=r.shift().trim();if(n){var o=r.join(":").trim();e.append(n,o)}}),e}(s.getAllResponseHeaders()||"")};t.url="responseURL"in s?s.responseURL:t.headers.get("X-Request-URL");var e="response"in s?s.response:s.responseText;n(new v(e,t))},s.onerror=function(){o(new TypeError("Network request failed"))},s.ontimeout=function(){o(new TypeError("Network request failed"))},s.open(i.method,i.url,!0),"include"===i.credentials&&(s.withCredentials=!0),"responseType"in s&&e.blob&&(s.responseType="blob"),i.headers.forEach(function(t,e){s.setRequestHeader(e,t)}),s.send(void 0===i._bodyInit?null:i._bodyInit)})},t.fetch.polyfill=!0}function a(t){if("string"!=typeof t&&(t=String(t)),/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(t))throw new TypeError("Invalid character in header field name");return t.toLowerCase()}function u(t){return"string"!=typeof t&&(t=String(t)),t}function f(t){var r={next:function(){var e=t.shift();return{done:void 0===e,value:e}}};return e.iterable&&(r[Symbol.iterator]=function(){return r}),r}function c(t){this.map={},t instanceof c?t.forEach(function(t,e){this.append(e,t)},this):Array.isArray(t)?t.forEach(function(t){this.append(t[0],t[1])},this):t&&Object.getOwnPropertyNames(t).forEach(function(e){this.append(e,t[e])},this)}function l(t){if(t.bodyUsed)return Promise.reject(new TypeError("Already read"));t.bodyUsed=!0}function d(t){return new Promise(function(e,r){t.onload=function(){e(t.result)},t.onerror=function(){r(t.error)}})}function h(t){var e=new FileReader,r=d(e);return e.readAsArrayBuffer(t),r}function y(t){if(t.slice)return t.slice(0);var e=new Uint8Array(t.byteLength);return e.set(new Uint8Array(t)),e.buffer}function p(){return this.bodyUsed=!1,this._initBody=function(t){if(this._bodyInit=t,t)if("string"==typeof t)this._bodyText=t;else if(e.blob&&Blob.prototype.isPrototypeOf(t))this._bodyBlob=t;else if(e.formData&&FormData.prototype.isPrototypeOf(t))this._bodyFormData=t;else if(e.searchParams&&URLSearchParams.prototype.isPrototypeOf(t))this._bodyText=t.toString();else if(e.arrayBuffer&&e.blob&&n(t))this._bodyArrayBuffer=y(t.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer]);else{if(!e.arrayBuffer||!ArrayBuffer.prototype.isPrototypeOf(t)&&!o(t))throw new Error("unsupported BodyInit type");this._bodyArrayBuffer=y(t)}else this._bodyText="";this.headers.get("content-type")||("string"==typeof t?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):e.searchParams&&URLSearchParams.prototype.isPrototypeOf(t)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},e.blob&&(this.blob=function(){var t=l(this);if(t)return t;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this._bodyArrayBuffer?l(this)||Promise.resolve(this._bodyArrayBuffer):this.blob().then(h)}),this.text=function(){var t=l(this);if(t)return t;if(this._bodyBlob)return function(t){var e=new FileReader,r=d(e);return e.readAsText(t),r}(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(function(t){for(var e=new Uint8Array(t),r=new Array(e.length),n=0;n<e.length;n++)r[n]=String.fromCharCode(e[n]);return r.join("")}(this._bodyArrayBuffer));if(this._bodyFormData)throw new Error("could not read FormData body as text");return Promise.resolve(this._bodyText)},e.formData&&(this.formData=function(){return this.text().then(m)}),this.json=function(){return this.text().then(JSON.parse)},this}function b(t,e){var r=(e=e||{}).body;if(t instanceof b){if(t.bodyUsed)throw new TypeError("Already read");this.url=t.url,this.credentials=t.credentials,e.headers||(this.headers=new c(t.headers)),this.method=t.method,this.mode=t.mode,r||null==t._bodyInit||(r=t._bodyInit,t.bodyUsed=!0)}else this.url=String(t);if(this.credentials=e.credentials||this.credentials||"omit",!e.headers&&this.headers||(this.headers=new c(e.headers)),this.method=function(t){var e=t.toUpperCase();return i.indexOf(e)>-1?e:t}(e.method||this.method||"GET"),this.mode=e.mode||this.mode||null,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&r)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(r)}function m(t){var e=new FormData;return t.trim().split("&").forEach(function(t){if(t){var r=t.split("="),n=r.shift().replace(/\+/g," "),o=r.join("=").replace(/\+/g," ");e.append(decodeURIComponent(n),decodeURIComponent(o))}}),e}function v(t,e){e||(e={}),this.type="default",this.status="status"in e?e.status:200,this.ok=this.status>=200&&this.status<300,this.statusText="statusText"in e?e.statusText:"OK",this.headers=new c(e.headers),this.url=e.url||"",this._initBody(t)}}("undefined"!=typeof self?self:this)},function(t,e,r){r(2),t.exports=r(1)}]);
includes/class-cyr-to-lat-conversion-tables.php ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Conversion tables.
4
+ *
5
+ * @package cyr-to-lat
6
+ */
7
+
8
+ /**
9
+ * Class Cyr_To_Lat_Conversion_Tables
10
+ *
11
+ * @class Cyr_To_Lat_Conversion_Tables
12
+ */
13
+ class Cyr_To_Lat_Conversion_Tables {
14
+
15
+ /**
16
+ * Get conversion table by locale.
17
+ *
18
+ * @param string $locale WordPress locale.
19
+ *
20
+ * @return array
21
+ */
22
+ public static function get( $locale = '' ) {
23
+ $table = array(
24
+ 'А' => 'A',
25
+ 'Б' => 'B',
26
+ 'В' => 'V',
27
+ 'Г' => 'G',
28
+ 'Ѓ' => 'G',
29
+ 'Ґ' => 'G',
30
+ 'Д' => 'D',
31
+ 'Е' => 'E',
32
+ 'Ё' => 'YO',
33
+ 'Є' => 'YE',
34
+ 'Ж' => 'ZH',
35
+ 'З' => 'Z',
36
+ 'Ѕ' => 'Z',
37
+ 'И' => 'I',
38
+ 'Й' => 'J',
39
+ 'Ј' => 'J',
40
+ 'І' => 'I',
41
+ 'Ї' => 'YI',
42
+ 'К' => 'K',
43
+ 'Ќ' => 'K',
44
+ 'Л' => 'L',
45
+ 'Љ' => 'L',
46
+ 'М' => 'M',
47
+ 'Н' => 'N',
48
+ 'Њ' => 'N',
49
+ 'О' => 'O',
50
+ 'П' => 'P',
51
+ 'Р' => 'R',
52
+ 'С' => 'S',
53
+ 'Т' => 'T',
54
+ 'У' => 'U',
55
+ 'Ў' => 'U',
56
+ 'Ф' => 'F',
57
+ 'Х' => 'H',
58
+ 'Ц' => 'TS',
59
+ 'Ч' => 'CH',
60
+ 'Џ' => 'DH',
61
+ 'Ш' => 'SH',
62
+ 'Щ' => 'SHH',
63
+ 'Ъ' => '',
64
+ 'Ы' => 'Y',
65
+ 'Ь' => '',
66
+ 'Э' => 'E',
67
+ 'Ю' => 'YU',
68
+ 'Я' => 'YA',
69
+ 'а' => 'a',
70
+ 'б' => 'b',
71
+ 'в' => 'v',
72
+ 'г' => 'g',
73
+ 'ѓ' => 'g',
74
+ 'ґ' => 'g',
75
+ 'д' => 'd',
76
+ 'е' => 'e',
77
+ 'ё' => 'yo',
78
+ 'є' => 'ye',
79
+ 'ж' => 'zh',
80
+ 'з' => 'z',
81
+ 'ѕ' => 'z',
82
+ 'и' => 'i',
83
+ 'й' => 'j',
84
+ 'ј' => 'j',
85
+ 'і' => 'i',
86
+ 'ї' => 'yi',
87
+ 'к' => 'k',
88
+ 'ќ' => 'k',
89
+ 'л' => 'l',
90
+ 'љ' => 'l',
91
+ 'м' => 'm',
92
+ 'н' => 'n',
93
+ 'њ' => 'n',
94
+ 'о' => 'o',
95
+ 'п' => 'p',
96
+ 'р' => 'r',
97
+ 'с' => 's',
98
+ 'т' => 't',
99
+ 'у' => 'u',
100
+ 'ў' => 'u',
101
+ 'ф' => 'f',
102
+ 'х' => 'h',
103
+ 'ц' => 'ts',
104
+ 'ч' => 'ch',
105
+ 'џ' => 'dh',
106
+ 'ш' => 'sh',
107
+ 'щ' => 'shh',
108
+ 'ъ' => '',
109
+ 'ы' => 'y',
110
+ 'ь' => '',
111
+ 'э' => 'e',
112
+ 'ю' => 'yu',
113
+ 'я' => 'ya',
114
+ );
115
+ switch ( $locale ) {
116
+ case 'bg_BG':
117
+ $table['Щ'] = 'SHT';
118
+ $table['щ'] = 'sht';
119
+ $table['Ъ'] = 'A';
120
+ $table['ъ'] = 'a';
121
+ break;
122
+ case 'uk':
123
+ $table['И'] = 'Y';
124
+ $table['и'] = 'y';
125
+ break;
126
+ case 'ka_GE':
127
+ $table['ა'] = 'a';
128
+ $table['ბ'] = 'b';
129
+ $table['გ'] = 'g';
130
+ $table['დ'] = 'd';
131
+ $table['ე'] = 'e';
132
+ $table['ვ'] = 'v';
133
+ $table['ზ'] = 'z';
134
+ $table['თ'] = 'th';
135
+ $table['ი'] = 'i';
136
+ $table['კ'] = 'k';
137
+ $table['ლ'] = 'l';
138
+ $table['მ'] = 'm';
139
+ $table['ნ'] = 'n';
140
+ $table['ო'] = 'o';
141
+ $table['პ'] = 'p';
142
+ $table['ჟ'] = 'zh';
143
+ $table['რ'] = 'r';
144
+ $table['ს'] = 's';
145
+ $table['ტ'] = 't';
146
+ $table['უ'] = 'u';
147
+ $table['ფ'] = 'ph';
148
+ $table['ქ'] = 'q';
149
+ $table['ღ'] = 'gh';
150
+ $table['ყ'] = 'qh';
151
+ $table['შ'] = 'sh';
152
+ $table['ჩ'] = 'ch';
153
+ $table['ც'] = 'ts';
154
+ $table['ძ'] = 'dz';
155
+ $table['წ'] = 'ts';
156
+ $table['ჭ'] = 'tch';
157
+ $table['ხ'] = 'kh';
158
+ $table['ჯ'] = 'j';
159
+ $table['ჰ'] = 'h';
160
+ break;
161
+ default:
162
+ }
163
+
164
+ return $table;
165
+ }
166
+ }
includes/class-cyr-to-lat-main.php ADDED
@@ -0,0 +1,215 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Main class of the plugin.
4
+ *
5
+ * @package cyr-to-lat
6
+ */
7
+
8
+ /**
9
+ * Class Cyr_To_Lat_Main
10
+ */
11
+ class Cyr_To_Lat_Main {
12
+
13
+ /**
14
+ * Plugin settings.
15
+ *
16
+ * @var Cyr_To_Lat_Settings
17
+ */
18
+ private $settings;
19
+
20
+ /**
21
+ * Cyr_To_Lat constructor.
22
+ */
23
+ public function __construct() {
24
+ $this->init();
25
+ $this->init_hooks();
26
+ }
27
+
28
+ /**
29
+ * Init class.
30
+ */
31
+ public function init() {
32
+ $this->settings = new Cyr_To_Lat_Settings();
33
+ }
34
+
35
+ /**
36
+ * Init class hooks.
37
+ */
38
+ public function init_hooks() {
39
+ add_filter( 'sanitize_title', array( $this, 'ctl_sanitize_title' ), 9, 3 );
40
+ add_filter( 'sanitize_file_name', array( $this, 'ctl_sanitize_title' ), 10, 2 );
41
+
42
+ add_filter( 'wp_insert_post_data', array( $this, 'ctl_sanitize_post_name' ), 10, 2 );
43
+
44
+ if ( 'yes' === $this->settings->get_option( 'convert_existing_slugs' ) ) {
45
+ $this->settings->set_option( 'convert_existing_slugs', 'no' );
46
+ add_action( 'shutdown', array( $this, 'convert_existing_slugs' ) );
47
+ }
48
+ }
49
+
50
+ /**
51
+ * Sanitize title.
52
+ *
53
+ * @param string $title Sanitized title.
54
+ * @param string $raw_title The title prior to sanitization.
55
+ * @param string $context The context for which the title is being sanitized.
56
+ *
57
+ * @return string
58
+ */
59
+ public function ctl_sanitize_title( $title, $raw_title = '', $context = '' ) {
60
+ global $wpdb;
61
+
62
+ $pre = apply_filters( 'ctl_pre_sanitize_title', false, $title );
63
+
64
+ if ( false !== $pre ) {
65
+ return $pre;
66
+ }
67
+
68
+ // Locales list - https://make.wordpress.org/polyglots/teams/.
69
+ $locale = get_locale();
70
+ $iso9_table = $this->settings->get_option( $locale );
71
+ $iso9_table = ! empty( $iso9_table ) ? $iso9_table : Cyr_To_Lat_Conversion_Tables::get( $locale );
72
+
73
+ $is_term = false;
74
+ // phpcs:disable WordPress.PHP.DevelopmentFunctions.error_log_debug_backtrace
75
+ $backtrace = debug_backtrace();
76
+ // phpcs:enable
77
+ foreach ( $backtrace as $backtrace_entry ) {
78
+ if ( 'wp_insert_term' === $backtrace_entry['function'] ) {
79
+ $is_term = true;
80
+ break;
81
+ }
82
+ }
83
+
84
+ // phpcs:disable WordPress.DB.DirectDatabaseQuery
85
+ $term = $is_term ? $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM $wpdb->terms WHERE name = %s", $title ) ) : '';
86
+ // phpcs:enable
87
+
88
+ if ( ! empty( $term ) ) {
89
+ $title = $term;
90
+ } else {
91
+ $title = strtr( $title, apply_filters( 'ctl_table', $iso9_table ) );
92
+
93
+ if ( function_exists( 'iconv' ) ) {
94
+ $title = iconv( 'UTF-8', 'UTF-8//TRANSLIT//IGNORE', $title );
95
+ }
96
+
97
+ $title = preg_replace( "/[^A-Za-z0-9'_\-\.]/", '-', $title );
98
+ $title = preg_replace( '/\-+/', '-', $title );
99
+ $title = trim( $title, '-' );
100
+ }
101
+
102
+ return $title;
103
+ }
104
+
105
+ /**
106
+ * Convert Existing Slugs
107
+ */
108
+ public function convert_existing_slugs() {
109
+ global $wpdb;
110
+
111
+ // phpcs:disable WordPress.DB.DirectDatabaseQuery
112
+ $posts = $wpdb->get_results( "SELECT ID, post_name FROM $wpdb->posts WHERE post_name REGEXP('[^A-Za-z0-9\-]+') AND post_status IN ('publish', 'future', 'private')" );
113
+ // phpcs:enable
114
+
115
+ foreach ( (array) $posts as $post ) {
116
+ $sanitized_name = $this->ctl_sanitize_title( urldecode( $post->post_name ) );
117
+
118
+ if ( $post->post_name !== $sanitized_name ) {
119
+ add_post_meta( $post->ID, '_wp_old_slug', $post->post_name );
120
+ // phpcs:disable WordPress.DB.DirectDatabaseQuery
121
+ $wpdb->update( $wpdb->posts, array( 'post_name' => $sanitized_name ), array( 'ID' => $post->ID ) );
122
+ // phpcs:enable
123
+ }
124
+ }
125
+
126
+ // phpcs:disable WordPress.DB.DirectDatabaseQuery
127
+ $terms = $wpdb->get_results( "SELECT term_id, slug FROM $wpdb->terms WHERE slug REGEXP('[^A-Za-z0-9\-]+') " );
128
+ // phpcs:enable
129
+
130
+ foreach ( (array) $terms as $term ) {
131
+ $sanitized_slug = $this->ctl_sanitize_title( urldecode( $term->slug ) );
132
+
133
+ if ( $term->slug !== $sanitized_slug ) {
134
+ // phpcs:disable WordPress.DB.DirectDatabaseQuery
135
+ $wpdb->update( $wpdb->terms, array( 'slug' => $sanitized_slug ), array( 'term_id' => $term->term_id ) );
136
+ // phpcs:enable
137
+ }
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Check if Classic Editor plugin is active.
143
+ *
144
+ * @link https://kagg.eu/how-to-catch-gutenberg/
145
+ *
146
+ * @return bool
147
+ */
148
+ private function ctl_is_classic_editor_plugin_active() {
149
+ if ( ! function_exists( 'is_plugin_active' ) ) {
150
+ include_once ABSPATH . 'wp-admin/includes/plugin.php';
151
+ }
152
+
153
+ if ( is_plugin_active( 'classic-editor/classic-editor.php' ) ) {
154
+ return true;
155
+ }
156
+
157
+ return false;
158
+ }
159
+
160
+ /**
161
+ * Check if Block Editor is active.
162
+ * Must only be used after plugins_loaded action is fired.
163
+ *
164
+ * @link https://kagg.eu/how-to-catch-gutenberg/
165
+ *
166
+ * @return bool
167
+ */
168
+ private function ctl_is_gutenberg_editor_active() {
169
+
170
+ // Gutenberg plugin is installed and activated.
171
+ $gutenberg = ! ( false === has_filter( 'replace_editor', 'gutenberg_init' ) );
172
+
173
+ // Block editor since 5.0.
174
+ $block_editor = version_compare( $GLOBALS['wp_version'], '5.0-beta', '>' );
175
+
176
+ if ( ! $gutenberg && ! $block_editor ) {
177
+ return false;
178
+ }
179
+
180
+ if ( $this->ctl_is_classic_editor_plugin_active() ) {
181
+ $editor_option = get_option( 'classic-editor-replace' );
182
+ $block_editor_active = array( 'no-replace', 'block' );
183
+
184
+ return in_array( $editor_option, $block_editor_active, true );
185
+ }
186
+
187
+ return true;
188
+ }
189
+
190
+ /**
191
+ * Gutenberg support
192
+ *
193
+ * @param array $data An array of slashed post data.
194
+ * @param array $postarr An array of sanitized, but otherwise unmodified post data.
195
+ *
196
+ * @return mixed
197
+ */
198
+ public function ctl_sanitize_post_name( $data, $postarr = array() ) {
199
+
200
+ if ( ! $this->ctl_is_gutenberg_editor_active() ) {
201
+ return $data;
202
+ }
203
+
204
+ if (
205
+ ! $data['post_name'] && $data['post_title'] &&
206
+ ! in_array( $data['post_status'], array( 'auto-draft', 'revision' ), true )
207
+ ) {
208
+ $data['post_name'] = sanitize_title( $data['post_title'] );
209
+ }
210
+
211
+ return $data;
212
+ }
213
+ }
214
+
215
+ // eof.
includes/class-cyr-to-lat-settings.php ADDED
@@ -0,0 +1,671 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin Settings.
4
+ *
5
+ * @package cyr-to-lat
6
+ */
7
+
8
+ /**
9
+ * Class Cyr_To_Lat_Settings
10
+ *
11
+ * @class Cyr_To_Lat_Settings
12
+ */
13
+ class Cyr_To_Lat_Settings {
14
+
15
+ /**
16
+ * Admin screen id.
17
+ *
18
+ * @var string
19
+ */
20
+ const SCREEN_ID = 'toplevel_page_cyr-to-lat';
21
+
22
+ /**
23
+ * Option group.
24
+ *
25
+ * @var string
26
+ */
27
+ const OPTION_GROUP = 'cyr_to_lat_group';
28
+
29
+ /**
30
+ * Option page.
31
+ *
32
+ * @var string
33
+ */
34
+ const PAGE = 'cyr-to-lat';
35
+
36
+ /**
37
+ * Plugin options name.
38
+ *
39
+ * @var string
40
+ */
41
+ const OPTION_NAME = 'cyr_to_lat_settings';
42
+
43
+ /**
44
+ * Plugin options.
45
+ *
46
+ * @var array
47
+ */
48
+ private $options;
49
+
50
+ /**
51
+ * Form fields.
52
+ *
53
+ * @var array
54
+ */
55
+ public $form_fields;
56
+
57
+ /**
58
+ * Plugin options.
59
+ *
60
+ * @var array
61
+ */
62
+ public $settings;
63
+
64
+ /**
65
+ * Cyr_To_Lat_Settings constructor.
66
+ */
67
+ public function __construct() {
68
+ $this->load_plugin_textdomain();
69
+ $this->init_form_fields();
70
+ $this->init_settings();
71
+ $this->init_hooks();
72
+ }
73
+
74
+ /**
75
+ * Init class hooks.
76
+ */
77
+ public function init_hooks() {
78
+ add_filter(
79
+ 'plugin_action_links_' . plugin_basename( CYR_TO_LAT_FILE ),
80
+ array(
81
+ $this,
82
+ 'add_settings_link',
83
+ ),
84
+ 10,
85
+ 4
86
+ );
87
+
88
+ add_action( 'admin_menu', array( $this, 'add_settings_page' ) );
89
+ add_action( 'current_screen', array( $this, 'setup_sections' ) );
90
+ add_action( 'current_screen', array( $this, 'setup_fields' ) );
91
+
92
+ add_filter( 'pre_update_option_' . self::OPTION_NAME, array( $this, 'pre_update_option_filter' ), 10, 3 );
93
+
94
+ add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
95
+ }
96
+
97
+ /**
98
+ * Add link to plugin setting page on plugins page.
99
+ *
100
+ * @param array $actions An array of plugin action links. By default this can include 'activate',
101
+ * 'deactivate', and 'delete'. With Multisite active this can also include
102
+ * 'network_active' and 'network_only' items.
103
+ * @param string $plugin_file Path to the plugin file relative to the plugins directory.
104
+ * @param array $plugin_data An array of plugin data. See `get_plugin_data()`.
105
+ * @param string $context The plugin context. By default this can include 'all', 'active', 'inactive',
106
+ * 'recently_activated', 'upgrade', 'mustuse', 'dropins', and 'search'.
107
+ *
108
+ * @return array|mixed Plugin links
109
+ */
110
+ public function add_settings_link( $actions, $plugin_file, $plugin_data, $context ) {
111
+ $ctl_actions = array(
112
+ 'settings' =>
113
+ '<a href="' . admin_url( 'options-general.php?page=' . self::PAGE ) .
114
+ '" aria-label="' . esc_attr__( 'View Cyr To Lat settings', 'cyr2lat' ) . '">' .
115
+ esc_html__( 'Settings', 'cyr2lat' ) . '</a>',
116
+ );
117
+
118
+ return array_merge( $ctl_actions, $actions );
119
+ }
120
+
121
+ /**
122
+ * Init options form fields.
123
+ */
124
+ public function init_form_fields() {
125
+ $this->form_fields = array(
126
+ 'convert_existing_slugs' => array(
127
+ 'label' => __( 'Convert Existing Slugs', 'cyr2lat' ),
128
+ 'section' => 'general_section',
129
+ 'type' => 'checkbox',
130
+ 'placeholder' => '',
131
+ 'helper' => '',
132
+ 'supplemental' => '',
133
+ ),
134
+ 'iso9' => array(
135
+ 'label' => __( 'ISO9 Table', 'cyr2lat' ),
136
+ 'section' => 'iso9_section',
137
+ 'type' => 'table',
138
+ 'placeholder' => '',
139
+ 'helper' => '',
140
+ 'supplemental' => '',
141
+ 'default' => Cyr_To_Lat_Conversion_Tables::get(),
142
+ ),
143
+ 'bg_BG' => array(
144
+ 'label' => __( 'bg_BG Table', 'cyr2lat' ),
145
+ 'section' => 'bg_BG_section',
146
+ 'type' => 'table',
147
+ 'placeholder' => '',
148
+ 'helper' => '',
149
+ 'supplemental' => '',
150
+ 'default' => Cyr_To_Lat_Conversion_Tables::get( 'bg_BG' ),
151
+ ),
152
+ 'uk' => array(
153
+ 'label' => __( 'uk Table', 'cyr2lat' ),
154
+ 'section' => 'uk_section',
155
+ 'type' => 'table',
156
+ 'placeholder' => '',
157
+ 'helper' => '',
158
+ 'supplemental' => '',
159
+ 'default' => Cyr_To_Lat_Conversion_Tables::get( 'uk' ),
160
+ ),
161
+ 'ka_GE' => array(
162
+ 'label' => __( 'ka_GE Table', 'cyr2lat' ),
163
+ 'section' => 'ka_GE_section',
164
+ 'type' => 'table',
165
+ 'placeholder' => '',
166
+ 'helper' => '',
167
+ 'supplemental' => '',
168
+ 'default' => Cyr_To_Lat_Conversion_Tables::get( 'ka_GE' ),
169
+ ),
170
+ );
171
+ }
172
+
173
+ /**
174
+ * Initialise Settings.
175
+ *
176
+ * Store all settings in a single database entry
177
+ * and make sure the $settings array is either the default
178
+ * or the settings stored in the database.
179
+ */
180
+ public function init_settings() {
181
+ $this->settings = get_option( self::OPTION_NAME, null );
182
+
183
+ // If there are no settings defined, use defaults.
184
+ if ( ! is_array( $this->settings ) ) {
185
+ $form_fields = $this->get_form_fields();
186
+ $this->settings = array_merge( array_fill_keys( array_keys( $form_fields ), '' ), wp_list_pluck( $form_fields, 'default' ) );
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Get the form fields after they are initialized.
192
+ *
193
+ * @return array of options
194
+ */
195
+ public function get_form_fields() {
196
+ if ( empty( $this->form_fields ) ) {
197
+ $this->init_form_fields();
198
+ }
199
+
200
+ return array_map( array( $this, 'set_defaults' ), $this->form_fields );
201
+ }
202
+
203
+ /**
204
+ * Set default required properties for each field.
205
+ *
206
+ * @param array $field Settings field.
207
+ *
208
+ * @return array
209
+ */
210
+ protected function set_defaults( $field ) {
211
+ if ( ! isset( $field['default'] ) ) {
212
+ $field['default'] = '';
213
+ }
214
+
215
+ return $field;
216
+ }
217
+
218
+ /**
219
+ * Add settings page to the menu.
220
+ */
221
+ public function add_settings_page() {
222
+ $page_title = __( 'Cyr To Lat', 'cyr2lat' );
223
+ $menu_title = __( 'Cyr To Lat', 'cyr2lat' );
224
+ $capability = 'manage_options';
225
+ $slug = self::PAGE;
226
+ $callback = array( $this, 'ctl_settings_page' );
227
+ // phpcs:disable WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
228
+ $icon = 'data:image/svg+xml;base64,' . base64_encode( '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0" y="0" width="512" height="512" viewBox="0 0 512 512" enable-background="new 0 0 512 512" xml:space="preserve"><polygon fill="#EEEEEE" points="246.2 411.2 267.9 479.7 273.9 473.1 273.9 473.1 331 411.2 "/><path fill="#EEEEEE" d="M449.7 99.8H269.4l49.8 157.2 24.9-58.5h35.5l75 176.3h-40.2l-16-39.2h-54.3l23.1 72.8 -0.2 0h0.1l-71.7 77.9h154.3c23.4 0 42.4-19 42.4-42.4V142.3C492.1 118.8 473.2 99.8 449.7 99.8z"/><polygon fill="#EEEEEE" points="338.1 301.6 384.6 301.6 361.4 244.8 "/><path fill="#EEEEEE" d="M219.7 24.7H49c-16.6 0-30 13.5-30 30v301.6c0 16.6 13.5 30 30 30h285.3L219.7 24.7zM230.3 302.3c-30.5-8.3-59-21.9-82.9-39.4 -23.8 17.5-52.4 31.1-82.9 39.4l-3.4 0.9L52.7 273.2l3.5-0.9c24.7-6.6 47.2-16.8 67-30.3 -19.6-19.6-34.2-42.5-42.4-66.6H58v-27.2h75.9v-23.6h27.2v23.6h75.9v27.2h-22.7c-8.2 24.1-22.8 47-42.4 66.6 19.8 13.5 42.3 23.6 67 30.3l3.5 0.9 -8.5 30L230.3 302.3zM114 175.4c7.4 17 18.6 32.7 33.4 47 14.8-14.2 26-30 33.4-47H114z"/></svg>' );
229
+ // phpcs:enable
230
+ $position = null;
231
+ add_menu_page( $page_title, $menu_title, $capability, $slug, $callback, $icon );
232
+ }
233
+
234
+ /**
235
+ * Settings page.
236
+ */
237
+ public function ctl_settings_page() {
238
+ if ( ! $this->is_ctl_options_screen() ) {
239
+ return;
240
+ }
241
+
242
+ ?>
243
+ <div class="wrap">
244
+ <h2 id="title">
245
+ <?php