Version Description
(2019-06-26) =
- Pro: Remove all languages files. All translations are now maintained on TranslationsPress
- Pro: Move the languages metabox to a block editor plugin
- Pro: Better management of user capabilities when synchronizing posts
- Pro: Separate REST requests from the frontend
- Pro: Copy the post slug when duplicating a post
- Pro: Duplicate ACF term metas when terms are automatically duplicated when creating a new post translation
- Pro: Fix hierarchy lost when duplicating terms
- Pro: Fix page shared slugs with special characters
- Pro: Fix synchronized posts sharing their slug when the language is set from the content
- Pro: Fix PHP warning with ACF Pro 5.8.1
- Pro: Fix ACF clone fields not translated in repeaters
- Better management of user capablities when synchronizing taxonomies terms and custom fields
- Extend string translations search to translated strings #207
- Update plugin updater to 1.6.18
- Honor the filter
pll_flag
when performing the flag validation when creating a new language - Modify the title and the label for the language switcher menu items #307
- Add support for international domain names
- Add a title to the link icon used to add a translation #325
- Add a notice when a static front page is not translated in a language
- Add support for custom term fields in wpml-config.xml
- Add filter
pll_admin_languages_filter
for the list of items the admin bar language filter - Add compatibility with WP Offload Media Lite. Props Daniel Berkman
- Yoast SEO: Add post type archive url in all languages to the sitemap
- Fix www. not redirected to not www. for the home page in multiple domains #311
- Fix cropped images not being synchronized
- Fix auto added page to menus when the page is created with the block editor
- Fix embed of translated static front page #318
- Fix a possible infinite redirect if the static front page is not translated
- Fix incorrect behavior of action 'wpml_register_single_string' when updating the string source
- Fix fatal error with Jetpack when no languages has been defined yet #330
- Fix a conflict with Laravel Valet. Props @chesio. #250
- Fix a conflict with Thesis.
- Fix a conflict with Pods in the block editor. Props Jory Hogeveen. #369
- Fix fatal error with Twenty Fourteen introduced in version 2.5.4. #374
Download this release
Release Info
Developer | Chouby |
Plugin | Polylang |
Version | 2.6 |
Comparing to | |
See all releases |
Code changes from version 2.5.4 to 2.6
- admin/admin-base.php +77 -37
- admin/admin-block-editor.php +14 -4
- admin/admin-classic-editor.php +91 -61
- admin/admin-filters-columns.php +53 -24
- admin/admin-filters-media.php +18 -16
- admin/admin-filters-post.php +6 -6
- admin/admin-filters-term.php +108 -70
- admin/admin-filters.php +24 -19
- admin/admin-links.php +69 -30
- admin/admin-model.php +33 -24
- admin/admin-nav-menu.php +9 -76
- admin/admin-notices.php +5 -4
- admin/admin-static-pages.php +43 -2
- admin/admin-strings.php +8 -8
- admin/admin.php +70 -1
- admin/view-translations-media.php +8 -10
- admin/view-translations-post.php +10 -10
- admin/view-translations-term.php +8 -8
- css/admin.css +39 -0
- css/admin.min.css +1 -1
- frontend/choose-lang-content.php +1 -1
- frontend/choose-lang-url.php +10 -8
- frontend/choose-lang.php +20 -13
- frontend/frontend-auto-translate.php +1 -1
- frontend/frontend-filters-links.php +8 -7
- frontend/frontend-filters-search.php +3 -3
- frontend/frontend-filters.php +3 -3
- frontend/frontend-links.php +3 -3
- frontend/frontend-nav-menu.php +13 -16
- frontend/frontend-static-pages.php +11 -6
- frontend/frontend.php +36 -39
- include/api.php +5 -4
- include/base.php +40 -8
- include/class-polylang.php +76 -30
- include/crud-posts.php +4 -4
- include/crud-terms.php +1 -1
- include/filters.php +1 -1
- include/functions.php +68 -0
- include/language.php +33 -13
- include/links-abstract-domain.php +5 -1
- include/links-default.php +1 -1
- include/links-directory.php +5 -6
- include/links-domain.php +11 -3
- include/links-model.php +1 -1
- include/links-subdomain.php +1 -1
- include/links.php +0 -29
- include/model.php +26 -18
- include/nav-menu.php +67 -0
- include/olt-manager.php +1 -1
- include/pointer.php +2 -2
- include/query.php +1 -1
- include/rest-request.php +73 -0
- include/static-pages.php +27 -6
- include/switcher.php +4 -4
- include/translated-object.php +45 -7
- include/translated-post.php +91 -1
- include/translated-term.php +7 -4
- include/walker-dropdown.php +2 -2
- include/widget-languages.php +16 -19
- install/install-base.php +1 -1
- install/install.php +1 -1
- install/plugin-updater.php +89 -17
- install/t15s.php +169 -0
- install/upgrade.php +11 -11
- js/block-editor.js +93 -1
- js/block-editor.min.js +1 -1
- js/classic-editor.js +25 -0
- js/classic-editor.min.js +1 -1
- js/media.js +0 -6
- js/media.min.js +0 -1
- js/post.js +75 -5
- js/post.min.js +1 -1
- lingotek/lingotek.php +9 -15
- modules/plugins/as3cf.php +64 -0
- modules/plugins/cache-compat.php +2 -2
- modules/plugins/featured-content.php +19 -16
- modules/plugins/jetpack.php +2 -2
- modules/plugins/plugins-compat.php +27 -14
- modules/plugins/wp-import.php +4 -4
- modules/plugins/wpseo.php +45 -35
- modules/share-slug/settings-share-slug.php +2 -2
- modules/sync/admin-sync.php +17 -9
- modules/sync/settings-sync.php +1 -1
- modules/sync/sync-metas.php +44 -14
- modules/sync/sync-post-metas.php +4 -2
- modules/sync/sync-tax.php +48 -18
- modules/sync/sync.php +69 -18
- modules/wpml/settings-wpml.php +2 -2
- modules/wpml/wpml-api.php +1 -1
- modules/wpml/wpml-compat.php +19 -4
- modules/wpml/wpml-config.php +25 -1
- modules/wpml/wpml-legacy-api.php +6 -5
- polylang.php +13 -14
- readme.txt +40 -3
- settings/flags.php +2 -2
- settings/languages.php +1 -1
- settings/settings-browser.php +2 -2
- settings/settings-cpt.php +5 -5
- settings/settings-licenses.php +15 -9
- settings/settings-media.php +1 -1
- settings/settings-module.php +7 -7
- settings/settings-tools.php +2 -2
- settings/settings-url.php +17 -16
- settings/settings.php +50 -21
- settings/table-languages.php +2 -2
- settings/table-settings.php +5 -5
- settings/table-string.php +86 -30
- settings/view-about.php +1 -12
- settings/view-tab-lang.php +8 -8
- uninstall.php +15 -3
admin/admin-base.php
CHANGED
@@ -31,9 +31,11 @@ class PLL_Admin_Base extends PLL_Base {
|
|
31 |
|
32 |
add_action( 'customize_controls_enqueue_scripts', array( $this, 'customize_controls_enqueue_scripts' ) );
|
33 |
|
34 |
-
|
35 |
-
|
36 |
-
|
|
|
|
|
37 |
}
|
38 |
}
|
39 |
|
@@ -44,6 +46,8 @@ class PLL_Admin_Base extends PLL_Base {
|
|
44 |
* @since 1.2
|
45 |
*/
|
46 |
public function init() {
|
|
|
|
|
47 |
if ( ! $this->model->get_languages_list() ) {
|
48 |
return;
|
49 |
}
|
@@ -60,6 +64,12 @@ class PLL_Admin_Base extends PLL_Base {
|
|
60 |
|
61 |
// Adds the languages in admin bar
|
62 |
add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 100 ); // 100 determines the position
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
}
|
64 |
|
65 |
/**
|
@@ -118,19 +128,21 @@ class PLL_Admin_Base extends PLL_Base {
|
|
118 |
// 3 => 1 if loaded in footer
|
119 |
// FIXME: check if I can load more scripts in footer
|
120 |
$scripts = array(
|
121 |
-
'post' => array( array( 'edit' ), array( 'jquery', 'wp-ajax-response' ), 0, 1 ),
|
122 |
-
'media' => array( array( 'upload' ), array( 'jquery' ), 0, 1 ),
|
123 |
'term' => array( array( 'edit-tags', 'term' ), array( 'jquery', 'wp-ajax-response', 'jquery-ui-autocomplete' ), 0, 1 ),
|
124 |
'user' => array( array( 'profile', 'user-edit' ), array( 'jquery' ), 0, 0 ),
|
125 |
'widgets' => array( array( 'widgets' ), array( 'jquery' ), 0, 0 ),
|
126 |
);
|
127 |
|
128 |
if ( ! empty( $screen->post_type ) && $this->model->is_translated_post_type( $screen->post_type ) ) {
|
129 |
-
|
|
|
|
|
|
|
130 |
|
131 |
-
// Block editor in WP 5.0
|
132 |
-
if ( method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() ) {
|
133 |
-
$scripts['block-editor'] = array( array( 'post' ), array( 'wp-api-fetch' ), 0, 1 );
|
134 |
}
|
135 |
}
|
136 |
|
@@ -164,6 +176,22 @@ class PLL_Admin_Base extends PLL_Base {
|
|
164 |
* @since 2.4.0
|
165 |
*/
|
166 |
public function localize_scripts() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
if ( wp_script_is( 'pll_widgets', 'enqueued' ) ) {
|
168 |
wp_localize_script(
|
169 |
'pll_widgets',
|
@@ -202,7 +230,7 @@ class PLL_Admin_Base extends PLL_Base {
|
|
202 |
}
|
203 |
|
204 |
$str = http_build_query( $params );
|
205 |
-
$arr =
|
206 |
?>
|
207 |
<script type="text/javascript">
|
208 |
if (typeof jQuery != 'undefined') {
|
@@ -210,23 +238,23 @@ class PLL_Admin_Base extends PLL_Base {
|
|
210 |
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
|
211 |
if ( -1 != options.url.indexOf( ajaxurl ) || -1 != ajaxurl.indexOf( options.url ) ) {
|
212 |
if ( 'undefined' === typeof options.data ) {
|
213 |
-
options.data = ( 'get' === options.type.toLowerCase() ) ? '<?php echo $str; ?>' : <?php echo $arr; ?>;
|
214 |
} else {
|
215 |
if ( 'string' === typeof options.data ) {
|
216 |
if ( '' === options.data && 'get' === options.type.toLowerCase() ) {
|
217 |
-
options.url = options.url+'&<?php echo $str; ?>';
|
218 |
} else {
|
219 |
try {
|
220 |
var o = $.parseJSON(options.data);
|
221 |
-
o = $.extend(o, <?php echo $arr; ?>);
|
222 |
options.data = JSON.stringify(o);
|
223 |
}
|
224 |
catch(e) {
|
225 |
-
options.data = '<?php echo $str; ?>&'+options.data;
|
226 |
}
|
227 |
}
|
228 |
} else {
|
229 |
-
options.data = $.extend(options.data, <?php echo $arr; ?>);
|
230 |
}
|
231 |
}
|
232 |
}
|
@@ -246,31 +274,31 @@ class PLL_Admin_Base extends PLL_Base {
|
|
246 |
$this->curlang = $this->filter_lang;
|
247 |
|
248 |
// Edit Post
|
249 |
-
if ( isset( $_REQUEST['pll_post_id'] ) && $lang = $this->model->post->get_language( (int) $_REQUEST['pll_post_id'] ) ) {
|
250 |
$this->curlang = $lang;
|
251 |
-
} elseif ( 'post.php' === $GLOBALS['pagenow'] && isset( $_GET['post'] ) &&
|
252 |
$this->curlang = $lang;
|
253 |
-
} elseif ( 'post-new.php' === $GLOBALS['pagenow'] && ( empty( $_GET['post_type'] ) || $this->model->is_translated_post_type( $_GET['post_type'] ) ) ) {
|
254 |
-
$this->curlang = empty( $_GET['new_lang'] ) ? $this->pref_lang : $this->model->get_language( $_GET['new_lang'] );
|
255 |
}
|
256 |
|
257 |
// Edit Term
|
258 |
// FIXME 'edit-tags.php' for backward compatibility with WP < 4.5
|
259 |
-
elseif ( in_array( $GLOBALS['pagenow'], array( 'edit-tags.php', 'term.php' ) ) && isset( $_GET['tag_ID'] ) && $lang = $this->model->term->get_language( (int) $_GET['tag_ID'] ) ) {
|
260 |
$this->curlang = $lang;
|
261 |
-
} elseif ( isset( $_REQUEST['pll_term_id'] ) && $lang = $this->model->term->get_language( (int) $_REQUEST['pll_term_id'] ) ) {
|
262 |
$this->curlang = $lang;
|
263 |
-
} elseif ( 'edit-tags.php' === $GLOBALS['pagenow'] && isset( $_GET['taxonomy'] ) && $this->model->is_translated_taxonomy( $_GET['taxonomy'] ) ) {
|
264 |
-
if ( ! empty( $_GET['new_lang'] ) ) {
|
265 |
-
$this->curlang = $this->model->get_language( $_GET['new_lang'] );
|
266 |
} elseif ( empty( $this->curlang ) ) {
|
267 |
$this->curlang = $this->pref_lang;
|
268 |
}
|
269 |
}
|
270 |
|
271 |
// Ajax
|
272 |
-
if ( wp_doing_ajax() && ! empty( $_REQUEST['lang'] ) ) {
|
273 |
-
$this->curlang = $this->model->get_language( $_REQUEST['lang'] );
|
274 |
}
|
275 |
}
|
276 |
|
@@ -282,8 +310,9 @@ class PLL_Admin_Base extends PLL_Base {
|
|
282 |
public function init_user() {
|
283 |
// Language for admin language filter: may be empty
|
284 |
// $_GET['lang'] is numeric when editing a language, not when selecting a new language in the filter
|
285 |
-
|
286 |
-
|
|
|
287 |
}
|
288 |
|
289 |
$this->filter_lang = $this->model->get_language( get_user_meta( get_current_user_id(), 'pll_filter_content', true ) );
|
@@ -356,16 +385,27 @@ class PLL_Admin_Base extends PLL_Base {
|
|
356 |
esc_html( $selected->name )
|
357 |
);
|
358 |
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
367 |
|
368 |
-
foreach (
|
369 |
if ( $selected->slug === $lang->slug ) {
|
370 |
continue;
|
371 |
}
|
31 |
|
32 |
add_action( 'customize_controls_enqueue_scripts', array( $this, 'customize_controls_enqueue_scripts' ) );
|
33 |
|
34 |
+
if ( defined( 'POLYLANG_PRO' ) ) {
|
35 |
+
new PLL_Pro();
|
36 |
+
} elseif ( ! defined( 'PLL_LINGOTEK_AD' ) || PLL_LINGOTEK_AD ) {
|
37 |
+
require_once POLYLANG_DIR . '/lingotek/lingotek.php'; // Lingotek
|
38 |
+
add_action( 'wp_loaded', array( new PLL_Lingotek(), 'init' ) );
|
39 |
}
|
40 |
}
|
41 |
|
46 |
* @since 1.2
|
47 |
*/
|
48 |
public function init() {
|
49 |
+
parent::init();
|
50 |
+
|
51 |
if ( ! $this->model->get_languages_list() ) {
|
52 |
return;
|
53 |
}
|
64 |
|
65 |
// Adds the languages in admin bar
|
66 |
add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 100 ); // 100 determines the position
|
67 |
+
|
68 |
+
// Translate slugs, only for pretty permalinks
|
69 |
+
if ( get_option( 'permalink_structure' ) && class_exists( 'PLL_Translate_Slugs' ) ) {
|
70 |
+
$slugs_model = new PLL_Translate_Slugs_Model( $this );
|
71 |
+
$this->translate_slugs = new PLL_Translate_Slugs( $slugs_model, $this->curlang );
|
72 |
+
}
|
73 |
}
|
74 |
|
75 |
/**
|
128 |
// 3 => 1 if loaded in footer
|
129 |
// FIXME: check if I can load more scripts in footer
|
130 |
$scripts = array(
|
131 |
+
'post' => array( array( 'edit', 'upload' ), array( 'jquery', 'wp-ajax-response' ), 0, 1 ),
|
|
|
132 |
'term' => array( array( 'edit-tags', 'term' ), array( 'jquery', 'wp-ajax-response', 'jquery-ui-autocomplete' ), 0, 1 ),
|
133 |
'user' => array( array( 'profile', 'user-edit' ), array( 'jquery' ), 0, 0 ),
|
134 |
'widgets' => array( array( 'widgets' ), array( 'jquery' ), 0, 0 ),
|
135 |
);
|
136 |
|
137 |
if ( ! empty( $screen->post_type ) && $this->model->is_translated_post_type( $screen->post_type ) ) {
|
138 |
+
// Classic editor.
|
139 |
+
if ( ! method_exists( $screen, 'is_block_editor' ) || ! $screen->is_block_editor() ) {
|
140 |
+
$scripts['classic-editor'] = array( array( 'post', 'media', 'async-upload' ), array( 'jquery', 'wp-ajax-response', 'post' ), 0, 1 );
|
141 |
+
}
|
142 |
|
143 |
+
// Block editor with legacy metabox in WP 5.0+.
|
144 |
+
if ( method_exists( $screen, 'is_block_editor' ) && $screen->is_block_editor() && ! pll_use_block_editor_plugin() ) {
|
145 |
+
$scripts['block-editor'] = array( array( 'post' ), array( 'jquery', 'wp-ajax-response', 'wp-api-fetch' ), 0, 1 );
|
146 |
}
|
147 |
}
|
148 |
|
176 |
* @since 2.4.0
|
177 |
*/
|
178 |
public function localize_scripts() {
|
179 |
+
if ( wp_script_is( 'pll_classic-editor', 'enqueued' ) ) {
|
180 |
+
wp_localize_script(
|
181 |
+
'pll_classic-editor',
|
182 |
+
'confirm_text',
|
183 |
+
__( 'You are about to overwrite an existing translation. Are you sure you want to proceed?', 'polylang' )
|
184 |
+
);
|
185 |
+
}
|
186 |
+
|
187 |
+
if ( wp_script_is( 'pll_block-editor', 'enqueued' ) ) {
|
188 |
+
wp_localize_script(
|
189 |
+
'pll_block-editor',
|
190 |
+
'confirm_text',
|
191 |
+
__( 'You are about to overwrite an existing translation. Are you sure you want to proceed?', 'polylang' )
|
192 |
+
);
|
193 |
+
}
|
194 |
+
|
195 |
if ( wp_script_is( 'pll_widgets', 'enqueued' ) ) {
|
196 |
wp_localize_script(
|
197 |
'pll_widgets',
|
230 |
}
|
231 |
|
232 |
$str = http_build_query( $params );
|
233 |
+
$arr = wp_json_encode( $params );
|
234 |
?>
|
235 |
<script type="text/javascript">
|
236 |
if (typeof jQuery != 'undefined') {
|
238 |
$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
|
239 |
if ( -1 != options.url.indexOf( ajaxurl ) || -1 != ajaxurl.indexOf( options.url ) ) {
|
240 |
if ( 'undefined' === typeof options.data ) {
|
241 |
+
options.data = ( 'get' === options.type.toLowerCase() ) ? '<?php echo $str; // phpcs:ignore WordPress.Security.EscapeOutput ?>' : <?php echo $arr; // phpcs:ignore WordPress.Security.EscapeOutput ?>;
|
242 |
} else {
|
243 |
if ( 'string' === typeof options.data ) {
|
244 |
if ( '' === options.data && 'get' === options.type.toLowerCase() ) {
|
245 |
+
options.url = options.url+'&<?php echo $str; // phpcs:ignore WordPress.Security.EscapeOutput ?>';
|
246 |
} else {
|
247 |
try {
|
248 |
var o = $.parseJSON(options.data);
|
249 |
+
o = $.extend(o, <?php echo $arr; // phpcs:ignore WordPress.Security.EscapeOutput ?>);
|
250 |
options.data = JSON.stringify(o);
|
251 |
}
|
252 |
catch(e) {
|
253 |
+
options.data = '<?php echo $str; // phpcs:ignore WordPress.Security.EscapeOutput ?>&'+options.data;
|
254 |
}
|
255 |
}
|
256 |
} else {
|
257 |
+
options.data = $.extend(options.data, <?php echo $arr; // phpcs:ignore WordPress.Security.EscapeOutput ?>);
|
258 |
}
|
259 |
}
|
260 |
}
|
274 |
$this->curlang = $this->filter_lang;
|
275 |
|
276 |
// Edit Post
|
277 |
+
if ( isset( $_REQUEST['pll_post_id'] ) && $lang = $this->model->post->get_language( (int) $_REQUEST['pll_post_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
278 |
$this->curlang = $lang;
|
279 |
+
} elseif ( 'post.php' === $GLOBALS['pagenow'] && isset( $_GET['post'] ) && $lang = $this->model->post->get_language( (int) $_GET['post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
280 |
$this->curlang = $lang;
|
281 |
+
} elseif ( 'post-new.php' === $GLOBALS['pagenow'] && ( empty( $_GET['post_type'] ) || $this->model->is_translated_post_type( sanitize_key( $_GET['post_type'] ) ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
282 |
+
$this->curlang = empty( $_GET['new_lang'] ) ? $this->pref_lang : $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
283 |
}
|
284 |
|
285 |
// Edit Term
|
286 |
// FIXME 'edit-tags.php' for backward compatibility with WP < 4.5
|
287 |
+
elseif ( in_array( $GLOBALS['pagenow'], array( 'edit-tags.php', 'term.php' ) ) && isset( $_GET['tag_ID'] ) && $lang = $this->model->term->get_language( (int) $_GET['tag_ID'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
288 |
$this->curlang = $lang;
|
289 |
+
} elseif ( isset( $_REQUEST['pll_term_id'] ) && $lang = $this->model->term->get_language( (int) $_REQUEST['pll_term_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
290 |
$this->curlang = $lang;
|
291 |
+
} elseif ( 'edit-tags.php' === $GLOBALS['pagenow'] && isset( $_GET['taxonomy'] ) && $this->model->is_translated_taxonomy( sanitize_key( $_GET['taxonomy'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
292 |
+
if ( ! empty( $_GET['new_lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
293 |
+
$this->curlang = $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
294 |
} elseif ( empty( $this->curlang ) ) {
|
295 |
$this->curlang = $this->pref_lang;
|
296 |
}
|
297 |
}
|
298 |
|
299 |
// Ajax
|
300 |
+
if ( wp_doing_ajax() && ! empty( $_REQUEST['lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
301 |
+
$this->curlang = $this->model->get_language( sanitize_key( $_REQUEST['lang'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
302 |
}
|
303 |
}
|
304 |
|
310 |
public function init_user() {
|
311 |
// Language for admin language filter: may be empty
|
312 |
// $_GET['lang'] is numeric when editing a language, not when selecting a new language in the filter
|
313 |
+
// We intentionally don't use a nonce to update the language filter
|
314 |
+
if ( ! wp_doing_ajax() && ! empty( $_GET['lang'] ) && ! is_numeric( sanitize_key( $_GET['lang'] ) ) && current_user_can( 'edit_user', $user_id = get_current_user_id() ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
315 |
+
update_user_meta( $user_id, 'pll_filter_content', ( $lang = $this->model->get_language( sanitize_key( $_GET['lang'] ) ) ) ? $lang->slug : '' ); // phpcs:ignore WordPress.Security.NonceVerification
|
316 |
}
|
317 |
|
318 |
$this->filter_lang = $this->model->get_language( get_user_meta( get_current_user_id(), 'pll_filter_content', true ) );
|
385 |
esc_html( $selected->name )
|
386 |
);
|
387 |
|
388 |
+
/**
|
389 |
+
* Filters the admin languages filter submenu items
|
390 |
+
*
|
391 |
+
* @since 2.6
|
392 |
+
*
|
393 |
+
* @param array $items The admin languages filter submenu items.
|
394 |
+
*/
|
395 |
+
$items = apply_filters( 'pll_admin_languages_filter', array_merge( array( $all_item ), $this->model->get_languages_list() ) );
|
396 |
+
|
397 |
+
if ( ! empty( $items ) ) {
|
398 |
+
$wp_admin_bar->add_menu(
|
399 |
+
array(
|
400 |
+
'id' => 'languages',
|
401 |
+
'title' => $selected->flag . $title,
|
402 |
+
'href' => esc_url( add_query_arg( 'lang', $selected->slug, remove_query_arg( 'paged' ) ) ),
|
403 |
+
'meta' => array( 'title' => __( 'Filters content by language', 'polylang' ) ),
|
404 |
+
)
|
405 |
+
);
|
406 |
+
}
|
407 |
|
408 |
+
foreach ( $items as $lang ) {
|
409 |
if ( $selected->slug === $lang->slug ) {
|
410 |
continue;
|
411 |
}
|
admin/admin-block-editor.php
CHANGED
@@ -6,6 +6,7 @@
|
|
6 |
* @since 2.5
|
7 |
*/
|
8 |
class PLL_Admin_Block_Editor {
|
|
|
9 |
|
10 |
/**
|
11 |
* Constructor: setups filters and actions
|
@@ -15,6 +16,9 @@ class PLL_Admin_Block_Editor {
|
|
15 |
* @param object $polylang
|
16 |
*/
|
17 |
public function __construct( &$polylang ) {
|
|
|
|
|
|
|
18 |
add_filter( 'block_editor_preload_paths', array( $this, 'preload_paths' ), 10, 2 );
|
19 |
}
|
20 |
|
@@ -30,11 +34,17 @@ class PLL_Admin_Block_Editor {
|
|
30 |
* @return array
|
31 |
*/
|
32 |
public function preload_paths( $preload_paths, $post ) {
|
33 |
-
|
|
|
|
|
|
|
|
|
|
|
34 |
|
35 |
-
|
36 |
-
|
37 |
-
|
|
|
38 |
}
|
39 |
}
|
40 |
|
6 |
* @since 2.5
|
7 |
*/
|
8 |
class PLL_Admin_Block_Editor {
|
9 |
+
public $model;
|
10 |
|
11 |
/**
|
12 |
* Constructor: setups filters and actions
|
16 |
* @param object $polylang
|
17 |
*/
|
18 |
public function __construct( &$polylang ) {
|
19 |
+
$this->model = &$polylang->model;
|
20 |
+
$this->pref_lang = &$polylang->pref_lang;
|
21 |
+
|
22 |
add_filter( 'block_editor_preload_paths', array( $this, 'preload_paths' ), 10, 2 );
|
23 |
}
|
24 |
|
34 |
* @return array
|
35 |
*/
|
36 |
public function preload_paths( $preload_paths, $post ) {
|
37 |
+
if ( $this->model->is_translated_post_type( $post->post_type ) ) {
|
38 |
+
$lang = $this->model->post->get_language( $post->ID );
|
39 |
+
|
40 |
+
if ( ! $lang ) {
|
41 |
+
$lang = $this->pref_lang;
|
42 |
+
}
|
43 |
|
44 |
+
foreach ( $preload_paths as $k => $path ) {
|
45 |
+
if ( is_string( $path ) && '/' !== $path ) {
|
46 |
+
$preload_paths[ $k ] = $path . "&lang={$lang->slug}";
|
47 |
+
}
|
48 |
}
|
49 |
}
|
50 |
|
admin/admin-classic-editor.php
CHANGED
@@ -30,6 +30,9 @@ class PLL_Admin_Classic_Editor {
|
|
30 |
|
31 |
// Filters the pages by language in the parent dropdown list in the page attributes metabox
|
32 |
add_filter( 'page_attributes_dropdown_pages_args', array( $this, 'page_attributes_dropdown_pages_args' ), 10, 2 );
|
|
|
|
|
|
|
33 |
}
|
34 |
|
35 |
/**
|
@@ -42,7 +45,17 @@ class PLL_Admin_Classic_Editor {
|
|
42 |
*/
|
43 |
public function add_meta_boxes( $post_type, $post ) {
|
44 |
if ( $this->model->is_translated_post_type( $post_type ) ) {
|
45 |
-
add_meta_box(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
}
|
47 |
}
|
48 |
|
@@ -56,12 +69,26 @@ class PLL_Admin_Classic_Editor {
|
|
56 |
$post_id = $post_ID;
|
57 |
$post_type = get_post_type( $post_ID );
|
58 |
|
|
|
|
|
59 |
$lang = ( $lg = $this->model->post->get_language( $post_ID ) ) ? $lg :
|
60 |
-
( isset( $_GET['new_lang'] ) ? $this->model->get_language( $_GET['new_lang'] ) :
|
61 |
$this->pref_lang );
|
62 |
|
63 |
$dropdown = new PLL_Walker_Dropdown();
|
64 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
wp_nonce_field( 'pll_language', '_pll_nonce' );
|
66 |
|
67 |
// NOTE: the class "tags-input" allows to include the field in the autosave $_POST ( see autosave.js )
|
@@ -70,17 +97,9 @@ class PLL_Admin_Classic_Editor {
|
|
70 |
<label class="screen-reader-text" for="%2$s">%1$s</label>
|
71 |
<div id="select-%3$s-language">%4$s</div>',
|
72 |
esc_html__( 'Language', 'polylang' ),
|
73 |
-
|
74 |
-
'attachment' === $post_type ? 'media' : 'post',
|
75 |
-
$
|
76 |
-
$this->model->get_languages_list(),
|
77 |
-
array(
|
78 |
-
'name' => $id,
|
79 |
-
'class' => 'post_lang_choice tags-input',
|
80 |
-
'selected' => $lang ? $lang->slug : '',
|
81 |
-
'flag' => true,
|
82 |
-
)
|
83 |
-
)
|
84 |
);
|
85 |
|
86 |
/**
|
@@ -105,11 +124,20 @@ class PLL_Admin_Classic_Editor {
|
|
105 |
public function post_lang_choice() {
|
106 |
check_ajax_referer( 'pll_language', '_pll_nonce' );
|
107 |
|
|
|
|
|
|
|
|
|
108 |
global $post_ID; // Obliged to use the global variable for wp_popular_terms_checklist
|
109 |
$post_id = $post_ID = (int) $_POST['post_id'];
|
110 |
-
$lang = $this->model->get_language( $_POST['lang'] );
|
|
|
|
|
|
|
|
|
|
|
|
|
111 |
|
112 |
-
$post_type = $_POST['post_type'];
|
113 |
$post_type_object = get_post_type_object( $post_type );
|
114 |
if ( ! current_user_can( $post_type_object->cap->edit_post, $post_ID ) ) {
|
115 |
wp_die( -1 );
|
@@ -132,7 +160,7 @@ class PLL_Admin_Classic_Editor {
|
|
132 |
// Categories
|
133 |
if ( isset( $_POST['taxonomies'] ) ) {
|
134 |
// Not set for pages
|
135 |
-
foreach ( $_POST['taxonomies'] as $taxname ) {
|
136 |
$taxonomy = get_taxonomy( $taxname );
|
137 |
|
138 |
ob_start();
|
@@ -172,7 +200,7 @@ class PLL_Admin_Classic_Editor {
|
|
172 |
'exclude_tree' => $post->ID,
|
173 |
'selected' => $post->post_parent,
|
174 |
'name' => 'parent_id',
|
175 |
-
'show_option_none' => __( '(no parent)' ),
|
176 |
'sort_column' => 'menu_order, post_title',
|
177 |
'echo' => 0,
|
178 |
);
|
@@ -180,7 +208,7 @@ class PLL_Admin_Classic_Editor {
|
|
180 |
/** This filter is documented in wp-admin/includes/meta-boxes.php */
|
181 |
$dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post ); // Since WP 3.3
|
182 |
|
183 |
-
$x->Add( array( 'what' => 'pages', 'data' => wp_dropdown_pages( $dropdown_args ) ) );
|
184 |
}
|
185 |
|
186 |
// Flag
|
@@ -200,53 +228,32 @@ class PLL_Admin_Classic_Editor {
|
|
200 |
public function ajax_posts_not_translated() {
|
201 |
check_ajax_referer( 'pll_language', '_pll_nonce' );
|
202 |
|
203 |
-
if ( !
|
204 |
-
|
205 |
}
|
206 |
|
207 |
-
$
|
208 |
-
$translation_language = $this->model->get_language( $_GET['translation_language'] );
|
209 |
-
|
210 |
-
// Don't order by title: see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
|
211 |
-
$args = array(
|
212 |
-
's' => wp_unslash( $_GET['term'] ),
|
213 |
-
'suppress_filters' => 0, // To make the post_fields filter work
|
214 |
-
'lang' => 0, // Avoid admin language filter
|
215 |
-
'numberposts' => 20, // Limit to 20 posts
|
216 |
-
'post_status' => 'any',
|
217 |
-
'post_type' => $_GET['post_type'],
|
218 |
-
'tax_query' => array(
|
219 |
-
array(
|
220 |
-
'taxonomy' => 'language',
|
221 |
-
'field' => 'term_taxonomy_id', // WP 3.5+
|
222 |
-
'terms' => $translation_language->term_taxonomy_id,
|
223 |
-
),
|
224 |
-
),
|
225 |
-
);
|
226 |
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
* @param array $args WP_Query arguments
|
236 |
-
*/
|
237 |
-
$args = apply_filters( 'pll_ajax_posts_not_translated_args', $args );
|
238 |
-
$posts = get_posts( $args );
|
239 |
|
240 |
$return = array();
|
241 |
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
|
|
250 |
}
|
251 |
|
252 |
// Add current translation in list
|
@@ -262,7 +269,7 @@ class PLL_Admin_Classic_Editor {
|
|
262 |
);
|
263 |
}
|
264 |
|
265 |
-
wp_die(
|
266 |
}
|
267 |
|
268 |
/**
|
@@ -275,11 +282,34 @@ class PLL_Admin_Classic_Editor {
|
|
275 |
* @return array Modified arguments
|
276 |
*/
|
277 |
public function page_attributes_dropdown_pages_args( $dropdown_args, $post ) {
|
278 |
-
$dropdown_args['lang'] = isset( $_POST['lang'] ) ? $this->model->get_language( $_POST['lang'] ) : $this->model->post->get_language( $post->ID ); //
|
279 |
if ( ! $dropdown_args['lang'] ) {
|
280 |
$dropdown_args['lang'] = $this->pref_lang;
|
281 |
}
|
282 |
|
283 |
return $dropdown_args;
|
284 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
285 |
}
|
30 |
|
31 |
// Filters the pages by language in the parent dropdown list in the page attributes metabox
|
32 |
add_filter( 'page_attributes_dropdown_pages_args', array( $this, 'page_attributes_dropdown_pages_args' ), 10, 2 );
|
33 |
+
|
34 |
+
// Notice
|
35 |
+
add_action( 'edit_form_top', array( $this, 'edit_form_top' ) );
|
36 |
}
|
37 |
|
38 |
/**
|
45 |
*/
|
46 |
public function add_meta_boxes( $post_type, $post ) {
|
47 |
if ( $this->model->is_translated_post_type( $post_type ) ) {
|
48 |
+
add_meta_box(
|
49 |
+
'ml_box',
|
50 |
+
__( 'Languages', 'polylang' ),
|
51 |
+
array( $this, 'post_language' ),
|
52 |
+
$post_type,
|
53 |
+
'side',
|
54 |
+
'high',
|
55 |
+
array(
|
56 |
+
'__back_compat_meta_box' => pll_use_block_editor_plugin(),
|
57 |
+
)
|
58 |
+
);
|
59 |
}
|
60 |
}
|
61 |
|
69 |
$post_id = $post_ID;
|
70 |
$post_type = get_post_type( $post_ID );
|
71 |
|
72 |
+
$from_post_id = isset( $_GET['from_post'] ) ? (int) $_GET['from_post'] : 0; // phpcs:ignore WordPress.Security.NonceVerification
|
73 |
+
|
74 |
$lang = ( $lg = $this->model->post->get_language( $post_ID ) ) ? $lg :
|
75 |
+
( isset( $_GET['new_lang'] ) ? $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ) : // phpcs:ignore WordPress.Security.NonceVerification
|
76 |
$this->pref_lang );
|
77 |
|
78 |
$dropdown = new PLL_Walker_Dropdown();
|
79 |
|
80 |
+
$id = ( 'attachment' === $post_type ) ? sprintf( 'attachments[%d][language]', (int) $post_ID ) : 'post_lang_choice';
|
81 |
+
|
82 |
+
$dropdown_html = $dropdown->walk(
|
83 |
+
$this->model->get_languages_list(),
|
84 |
+
array(
|
85 |
+
'name' => $id,
|
86 |
+
'class' => 'post_lang_choice tags-input',
|
87 |
+
'selected' => $lang ? $lang->slug : '',
|
88 |
+
'flag' => true,
|
89 |
+
)
|
90 |
+
);
|
91 |
+
|
92 |
wp_nonce_field( 'pll_language', '_pll_nonce' );
|
93 |
|
94 |
// NOTE: the class "tags-input" allows to include the field in the autosave $_POST ( see autosave.js )
|
97 |
<label class="screen-reader-text" for="%2$s">%1$s</label>
|
98 |
<div id="select-%3$s-language">%4$s</div>',
|
99 |
esc_html__( 'Language', 'polylang' ),
|
100 |
+
esc_attr( $id ),
|
101 |
+
( 'attachment' === $post_type ? 'media' : 'post' ),
|
102 |
+
$dropdown_html // phpcs:ignore WordPress.Security.EscapeOutput
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
);
|
104 |
|
105 |
/**
|
124 |
public function post_lang_choice() {
|
125 |
check_ajax_referer( 'pll_language', '_pll_nonce' );
|
126 |
|
127 |
+
if ( ! isset( $_POST['post_id'], $_POST['lang'], $_POST['post_type'] ) ) {
|
128 |
+
wp_die( 0 );
|
129 |
+
}
|
130 |
+
|
131 |
global $post_ID; // Obliged to use the global variable for wp_popular_terms_checklist
|
132 |
$post_id = $post_ID = (int) $_POST['post_id'];
|
133 |
+
$lang = $this->model->get_language( sanitize_key( $_POST['lang'] ) );
|
134 |
+
|
135 |
+
$post_type = sanitize_key( $_POST['post_type'] );
|
136 |
+
|
137 |
+
if ( ! post_type_exists( $post_type ) ) {
|
138 |
+
wp_die( 0 );
|
139 |
+
}
|
140 |
|
|
|
141 |
$post_type_object = get_post_type_object( $post_type );
|
142 |
if ( ! current_user_can( $post_type_object->cap->edit_post, $post_ID ) ) {
|
143 |
wp_die( -1 );
|
160 |
// Categories
|
161 |
if ( isset( $_POST['taxonomies'] ) ) {
|
162 |
// Not set for pages
|
163 |
+
foreach ( array_map( 'sanitize_key', $_POST['taxonomies'] ) as $taxname ) {
|
164 |
$taxonomy = get_taxonomy( $taxname );
|
165 |
|
166 |
ob_start();
|
200 |
'exclude_tree' => $post->ID,
|
201 |
'selected' => $post->post_parent,
|
202 |
'name' => 'parent_id',
|
203 |
+
'show_option_none' => __( '(no parent)', 'polylang' ),
|
204 |
'sort_column' => 'menu_order, post_title',
|
205 |
'echo' => 0,
|
206 |
);
|
208 |
/** This filter is documented in wp-admin/includes/meta-boxes.php */
|
209 |
$dropdown_args = apply_filters( 'page_attributes_dropdown_pages_args', $dropdown_args, $post ); // Since WP 3.3
|
210 |
|
211 |
+
$x->Add( array( 'what' => 'pages', 'data' => wp_dropdown_pages( $dropdown_args ) ) ); // phpcs:ignore WordPress.Security.EscapeOutput
|
212 |
}
|
213 |
|
214 |
// Flag
|
228 |
public function ajax_posts_not_translated() {
|
229 |
check_ajax_referer( 'pll_language', '_pll_nonce' );
|
230 |
|
231 |
+
if ( ! isset( $_GET['post_type'], $_GET['post_language'], $_GET['translation_language'], $_GET['term'], $_GET['pll_post_id'] ) ) {
|
232 |
+
wp_die( 0 );
|
233 |
}
|
234 |
|
235 |
+
$post_type = sanitize_key( $_GET['post_type'] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
|
237 |
+
if ( ! post_type_exists( $post_type ) ) {
|
238 |
+
wp_die( 0 );
|
239 |
+
}
|
240 |
+
|
241 |
+
$term = wp_unslash( $_GET['term'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
242 |
+
|
243 |
+
$post_language = $this->model->get_language( sanitize_key( $_GET['post_language'] ) );
|
244 |
+
$translation_language = $this->model->get_language( sanitize_key( $_GET['translation_language'] ) );
|
|
|
|
|
|
|
|
|
245 |
|
246 |
$return = array();
|
247 |
|
248 |
+
$untranslated_posts = $this->model->post->get_untranslated( $post_type, $post_language, $translation_language, $term );
|
249 |
+
|
250 |
+
// format output
|
251 |
+
foreach ( $untranslated_posts as $post ) {
|
252 |
+
$return[] = array(
|
253 |
+
'id' => $post->ID,
|
254 |
+
'value' => $post->post_title,
|
255 |
+
'link' => $this->links->edit_post_translation_link( $post->ID ),
|
256 |
+
);
|
257 |
}
|
258 |
|
259 |
// Add current translation in list
|
269 |
);
|
270 |
}
|
271 |
|
272 |
+
wp_die( wp_json_encode( $return ) );
|
273 |
}
|
274 |
|
275 |
/**
|
282 |
* @return array Modified arguments
|
283 |
*/
|
284 |
public function page_attributes_dropdown_pages_args( $dropdown_args, $post ) {
|
285 |
+
$dropdown_args['lang'] = isset( $_POST['lang'] ) ? $this->model->get_language( sanitize_key( $_POST['lang'] ) ) : $this->model->post->get_language( $post->ID ); // phpcs:ignore WordPress.Security.NonceVerification
|
286 |
if ( ! $dropdown_args['lang'] ) {
|
287 |
$dropdown_args['lang'] = $this->pref_lang;
|
288 |
}
|
289 |
|
290 |
return $dropdown_args;
|
291 |
}
|
292 |
+
|
293 |
+
/**
|
294 |
+
* Displays a notice if the user has not sufficient rights to overwrite synchronized taxonomies and metas
|
295 |
+
*
|
296 |
+
* @since 2.6
|
297 |
+
*
|
298 |
+
* @param object $post Post currently being edited
|
299 |
+
*/
|
300 |
+
public function edit_form_top( $post ) {
|
301 |
+
if ( ! $this->model->post->current_user_can_synchronize( $post->ID ) ) {
|
302 |
+
?>
|
303 |
+
<div class="pll-notice notice notice-warning">
|
304 |
+
<p>
|
305 |
+
<?php
|
306 |
+
esc_html_e( 'Some taxonomies or metadata may be synchronized with existing translations that you are not allowed to modify.', 'polylang' );
|
307 |
+
echo ' ';
|
308 |
+
esc_html_e( 'If you attempt to modify them anyway, your changes will not be saved.', 'polylang' );
|
309 |
+
?>
|
310 |
+
</p>
|
311 |
+
</div>
|
312 |
+
<?php
|
313 |
+
}
|
314 |
+
}
|
315 |
}
|
admin/admin-filters-columns.php
CHANGED
@@ -108,8 +108,8 @@ class PLL_Admin_Filters_Columns {
|
|
108 |
* @param int $post_id
|
109 |
*/
|
110 |
public function post_column( $column, $post_id ) {
|
111 |
-
$inline = wp_doing_ajax() && isset( $_REQUEST['action'], $_POST['inline_lang_choice'] ) && 'inline-save' === $_REQUEST['action'];
|
112 |
-
$lang = $inline ? $this->model->get_language( $_POST['inline_lang_choice'] ) : $this->model->post->get_language( $post_id );
|
113 |
|
114 |
if ( false === strpos( $column, 'language_' ) || ! $lang ) {
|
115 |
return;
|
@@ -155,7 +155,7 @@ class PLL_Admin_Filters_Columns {
|
|
155 |
}
|
156 |
// Link to add a new translation
|
157 |
else {
|
158 |
-
echo $this->links->new_post_translation_link( $post_id, $language );
|
159 |
}
|
160 |
}
|
161 |
|
@@ -173,7 +173,7 @@ class PLL_Admin_Filters_Columns {
|
|
173 |
|
174 |
$elements = $this->model->get_languages_list();
|
175 |
if ( current_filter() == 'bulk_edit_custom_box' ) {
|
176 |
-
array_unshift( $elements, (object) array( 'slug' => -1, 'name' => __( '— No Change —' ) ) );
|
177 |
}
|
178 |
|
179 |
$dropdown = new PLL_Walker_Dropdown();
|
@@ -188,7 +188,7 @@ class PLL_Admin_Filters_Columns {
|
|
188 |
</div>
|
189 |
</fieldset>',
|
190 |
esc_html__( 'Language', 'polylang' ),
|
191 |
-
$dropdown->walk( $elements, array( 'name' => 'inline_lang_choice', 'id' => '' ) )
|
192 |
);
|
193 |
}
|
194 |
return $column;
|
@@ -216,13 +216,26 @@ class PLL_Admin_Filters_Columns {
|
|
216 |
* @param int $term_id
|
217 |
*/
|
218 |
public function term_column( $out, $column, $term_id ) {
|
219 |
-
$inline = wp_doing_ajax() && isset( $_REQUEST['action'], $_POST['inline_lang_choice'] ) && 'inline-save-tax' === $_REQUEST['action'];
|
220 |
-
if ( false === strpos( $column, 'language_' ) || ! ( $lang = $inline ? $this->model->get_language( $_POST['inline_lang_choice'] ) : $this->model->term->get_language( $term_id ) ) ) {
|
221 |
return $out;
|
222 |
}
|
223 |
|
224 |
-
|
225 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
|
227 |
if ( ! post_type_exists( $post_type ) || ! taxonomy_exists( $taxonomy ) ) {
|
228 |
return $out;
|
@@ -282,21 +295,29 @@ class PLL_Admin_Filters_Columns {
|
|
282 |
* @since 1.7
|
283 |
*/
|
284 |
public function ajax_update_post_rows() {
|
285 |
-
|
286 |
|
287 |
-
if ( !
|
288 |
-
|
289 |
}
|
290 |
|
291 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
|
293 |
$x = new WP_Ajax_Response();
|
294 |
-
$wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => $_POST['screen'] ) );
|
295 |
|
296 |
-
|
297 |
-
$translations =
|
298 |
$translations = array_map( 'intval', $translations );
|
299 |
|
|
|
|
|
300 |
foreach ( $translations as $post_id ) {
|
301 |
$level = is_post_type_hierarchical( $post_type ) ? count( get_ancestors( $post_id, $post_type ) ) : 0;
|
302 |
if ( $post = get_post( $post_id ) ) {
|
@@ -316,22 +337,30 @@ class PLL_Admin_Filters_Columns {
|
|
316 |
* @since 1.7
|
317 |
*/
|
318 |
public function ajax_update_term_rows() {
|
319 |
-
|
320 |
|
321 |
-
if ( !
|
322 |
-
|
323 |
}
|
324 |
|
325 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
|
327 |
$x = new WP_Ajax_Response();
|
328 |
-
$wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => $_POST['screen'] ) );
|
329 |
|
330 |
-
|
331 |
-
$translations =
|
332 |
-
$translations = array_unique( $translations ); // remove duplicates
|
333 |
$translations = array_map( 'intval', $translations );
|
334 |
|
|
|
|
|
|
|
335 |
foreach ( $translations as $term_id ) {
|
336 |
$level = is_taxonomy_hierarchical( $taxonomy ) ? count( get_ancestors( $term_id, $taxonomy ) ) : 0;
|
337 |
if ( $tag = get_term( $term_id, $taxonomy ) ) {
|
108 |
* @param int $post_id
|
109 |
*/
|
110 |
public function post_column( $column, $post_id ) {
|
111 |
+
$inline = wp_doing_ajax() && isset( $_REQUEST['action'], $_POST['inline_lang_choice'] ) && 'inline-save' === $_REQUEST['action']; // phpcs:ignore WordPress.Security.NonceVerification
|
112 |
+
$lang = $inline ? $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) ) : $this->model->post->get_language( $post_id ); // phpcs:ignore WordPress.Security.NonceVerification
|
113 |
|
114 |
if ( false === strpos( $column, 'language_' ) || ! $lang ) {
|
115 |
return;
|
155 |
}
|
156 |
// Link to add a new translation
|
157 |
else {
|
158 |
+
echo $this->links->new_post_translation_link( $post_id, $language ); // phpcs:ignore WordPress.Security.EscapeOutput
|
159 |
}
|
160 |
}
|
161 |
|
173 |
|
174 |
$elements = $this->model->get_languages_list();
|
175 |
if ( current_filter() == 'bulk_edit_custom_box' ) {
|
176 |
+
array_unshift( $elements, (object) array( 'slug' => -1, 'name' => __( '— No Change —', 'polylang' ) ) );
|
177 |
}
|
178 |
|
179 |
$dropdown = new PLL_Walker_Dropdown();
|
188 |
</div>
|
189 |
</fieldset>',
|
190 |
esc_html__( 'Language', 'polylang' ),
|
191 |
+
$dropdown->walk( $elements, array( 'name' => 'inline_lang_choice', 'id' => '' ) ) // phpcs:ignore WordPress.Security.EscapeOutput
|
192 |
);
|
193 |
}
|
194 |
return $column;
|
216 |
* @param int $term_id
|
217 |
*/
|
218 |
public function term_column( $out, $column, $term_id ) {
|
219 |
+
$inline = wp_doing_ajax() && isset( $_REQUEST['action'], $_POST['inline_lang_choice'] ) && 'inline-save-tax' === $_REQUEST['action']; // phpcs:ignore WordPress.Security.NonceVerification
|
220 |
+
if ( false === strpos( $column, 'language_' ) || ! ( $lang = $inline ? $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) ) : $this->model->term->get_language( $term_id ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
221 |
return $out;
|
222 |
}
|
223 |
|
224 |
+
if ( isset( $_REQUEST['post_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
225 |
+
$post_type = sanitize_key( $_REQUEST['post_type'] ); // phpcs:ignore WordPress.Security.NonceVerification
|
226 |
+
}
|
227 |
+
|
228 |
+
if ( isset( $GLOBALS['post_type'] ) ) {
|
229 |
+
$post_type = $GLOBALS['post_type'];
|
230 |
+
}
|
231 |
+
|
232 |
+
if ( isset( $_REQUEST['taxonomy'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
233 |
+
$taxonomy = sanitize_key( $_REQUEST['taxonomy'] ); // phpcs:ignore WordPress.Security.NonceVerification
|
234 |
+
}
|
235 |
+
|
236 |
+
if ( isset( $GLOBALS['taxonomy'] ) ) {
|
237 |
+
$taxonomy = $GLOBALS['taxonomy'];
|
238 |
+
}
|
239 |
|
240 |
if ( ! post_type_exists( $post_type ) || ! taxonomy_exists( $taxonomy ) ) {
|
241 |
return $out;
|
295 |
* @since 1.7
|
296 |
*/
|
297 |
public function ajax_update_post_rows() {
|
298 |
+
check_ajax_referer( 'inlineeditnonce', '_pll_nonce' );
|
299 |
|
300 |
+
if ( ! isset( $_POST['post_type'], $_POST['post_id'], $_POST['screen'] ) ) {
|
301 |
+
wp_die( 0 );
|
302 |
}
|
303 |
|
304 |
+
$post_type = sanitize_key( $_POST['post_type'] );
|
305 |
+
|
306 |
+
if ( ! post_type_exists( $post_type ) || ! $this->model->is_translated_post_type( $post_type ) ) {
|
307 |
+
wp_die( 0 );
|
308 |
+
}
|
309 |
+
|
310 |
+
global $wp_list_table;
|
311 |
+
$wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => sanitize_key( $_POST['screen'] ) ) );
|
312 |
|
313 |
$x = new WP_Ajax_Response();
|
|
|
314 |
|
315 |
+
// Collect old translations
|
316 |
+
$translations = empty( $_POST['translations'] ) ? array() : explode( ',', $_POST['translations'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
317 |
$translations = array_map( 'intval', $translations );
|
318 |
|
319 |
+
$translations = array_merge( $translations, array( (int) $_POST['post_id'] ) ); // Add current post
|
320 |
+
|
321 |
foreach ( $translations as $post_id ) {
|
322 |
$level = is_post_type_hierarchical( $post_type ) ? count( get_ancestors( $post_id, $post_type ) ) : 0;
|
323 |
if ( $post = get_post( $post_id ) ) {
|
337 |
* @since 1.7
|
338 |
*/
|
339 |
public function ajax_update_term_rows() {
|
340 |
+
check_ajax_referer( 'pll_language', '_pll_nonce' );
|
341 |
|
342 |
+
if ( ! isset( $_POST['taxonomy'], $_POST['term_id'], $_POST['screen'] ) ) {
|
343 |
+
wp_die( 0 );
|
344 |
}
|
345 |
|
346 |
+
$taxonomy = sanitize_key( $_POST['taxonomy'] );
|
347 |
+
|
348 |
+
if ( ! taxonomy_exists( $taxonomy ) || ! $this->model->is_translated_taxonomy( $taxonomy ) ) {
|
349 |
+
wp_die( 0 );
|
350 |
+
}
|
351 |
+
|
352 |
+
global $wp_list_table;
|
353 |
+
$wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => sanitize_key( $_POST['screen'] ) ) );
|
354 |
|
355 |
$x = new WP_Ajax_Response();
|
|
|
356 |
|
357 |
+
// Collect old translations
|
358 |
+
$translations = empty( $_POST['translations'] ) ? array() : explode( ',', $_POST['translations'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
|
|
359 |
$translations = array_map( 'intval', $translations );
|
360 |
|
361 |
+
$translations = array_merge( $translations, $this->model->term->get_translations( (int) $_POST['term_id'] ) ); // Add current translations
|
362 |
+
$translations = array_unique( $translations ); // Remove duplicates
|
363 |
+
|
364 |
foreach ( $translations as $term_id ) {
|
365 |
$level = is_taxonomy_hierarchical( $taxonomy ) ? count( get_ancestors( $term_id, $taxonomy ) ) : 0;
|
366 |
if ( $tag = get_term( $term_id, $taxonomy ) ) {
|
admin/admin-filters-media.php
CHANGED
@@ -28,7 +28,7 @@ class PLL_Admin_Filters_Media extends PLL_Admin_Filters_Post_Base {
|
|
28 |
add_filter( 'attachment_fields_to_save', array( $this, 'save_media' ), 10, 2 );
|
29 |
|
30 |
// Creates a media translation
|
31 |
-
if ( isset( $_GET['action'], $_GET['new_lang'], $_GET['from_media'] ) && 'translate_media' === $_GET['action'] ) {
|
32 |
add_action( 'admin_init', array( $this, 'translate_media' ) );
|
33 |
}
|
34 |
}
|
@@ -74,21 +74,23 @@ class PLL_Admin_Filters_Media extends PLL_Admin_Filters_Post_Base {
|
|
74 |
* @since 0.9
|
75 |
*/
|
76 |
public function translate_media() {
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
exit;
|
87 |
}
|
88 |
-
|
89 |
-
$tr_id = $this->posts->create_media_translation( $post_id, $_GET['new_lang'] );
|
90 |
-
wp_safe_redirect( admin_url( sprintf( 'post.php?post=%d&action=edit', $tr_id ) ) ); // WP 3.5+
|
91 |
-
exit;
|
92 |
}
|
93 |
|
94 |
/**
|
@@ -108,8 +110,8 @@ class PLL_Admin_Filters_Media extends PLL_Admin_Filters_Post_Base {
|
|
108 |
$this->model->post->set_language( $post['ID'], $attachment['language'] );
|
109 |
}
|
110 |
|
111 |
-
if ( isset( $_POST['media_tr_lang'] ) ) {
|
112 |
-
$this->save_translations( $post['ID'], $_POST['media_tr_lang'] );
|
113 |
}
|
114 |
|
115 |
return $post;
|
28 |
add_filter( 'attachment_fields_to_save', array( $this, 'save_media' ), 10, 2 );
|
29 |
|
30 |
// Creates a media translation
|
31 |
+
if ( isset( $_GET['action'], $_GET['new_lang'], $_GET['from_media'] ) && 'translate_media' === $_GET['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
32 |
add_action( 'admin_init', array( $this, 'translate_media' ) );
|
33 |
}
|
34 |
}
|
74 |
* @since 0.9
|
75 |
*/
|
76 |
public function translate_media() {
|
77 |
+
if ( isset( $_GET['from_media'], $_GET['new_lang'] ) ) {
|
78 |
+
// Security check
|
79 |
+
check_admin_referer( 'translate_media' );
|
80 |
+
$post_id = (int) $_GET['from_media'];
|
81 |
+
|
82 |
+
// Bails if the translations already exists
|
83 |
+
// See https://wordpress.org/support/topic/edit-translation-in-media-attachments?#post-7322303
|
84 |
+
// Or if the source media does not exist
|
85 |
+
if ( $this->model->post->get_translation( $post_id, sanitize_key( $_GET['new_lang'] ) ) || ! get_post( $post_id ) ) {
|
86 |
+
wp_safe_redirect( wp_get_referer() );
|
87 |
+
exit;
|
88 |
+
}
|
89 |
+
|
90 |
+
$tr_id = $this->posts->create_media_translation( $post_id, sanitize_key( $_GET['new_lang'] ) );
|
91 |
+
wp_safe_redirect( admin_url( sprintf( 'post.php?post=%d&action=edit', $tr_id ) ) ); // WP 3.5+
|
92 |
exit;
|
93 |
}
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
|
96 |
/**
|
110 |
$this->model->post->set_language( $post['ID'], $attachment['language'] );
|
111 |
}
|
112 |
|
113 |
+
if ( isset( $_POST['media_tr_lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
114 |
+
$this->save_translations( $post['ID'], array_map( 'absint', $_POST['media_tr_lang'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
115 |
}
|
116 |
|
117 |
return $post;
|
admin/admin-filters-post.php
CHANGED
@@ -104,17 +104,17 @@ class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
|
|
104 |
* @since 2.3
|
105 |
*/
|
106 |
public function edit_post() {
|
107 |
-
if ( isset( $_POST['post_lang_choice'], $_POST['post_ID'] ) && $post_id = (int) $_POST['post_ID'] ) {
|
108 |
check_admin_referer( 'pll_language', '_pll_nonce' );
|
109 |
|
110 |
$post = get_post( $post_id );
|
111 |
$post_type_object = get_post_type_object( $post->post_type );
|
112 |
|
113 |
if ( current_user_can( $post_type_object->cap->edit_post, $post_id ) ) {
|
114 |
-
$this->model->post->set_language( $post_id, $this->model->get_language( $_POST['post_lang_choice'] ) );
|
115 |
|
116 |
if ( isset( $_POST['post_tr_lang'] ) ) {
|
117 |
-
$this->save_translations( $post_id, $_POST['post_tr_lang'] );
|
118 |
}
|
119 |
}
|
120 |
}
|
@@ -160,10 +160,10 @@ class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
|
|
160 |
* @since 2.3
|
161 |
*/
|
162 |
public function bulk_edit_posts() {
|
163 |
-
if ( isset( $_GET['bulk_edit'], $_GET['inline_lang_choice'] ) && -1 !== $_GET['inline_lang_choice'] ) {
|
164 |
check_admin_referer( 'bulk-posts' );
|
165 |
|
166 |
-
if ( $lang = $this->model->get_language( $_GET['inline_lang_choice'] ) ) {
|
167 |
$post_ids = array_map( 'intval', (array) $_REQUEST['post'] );
|
168 |
foreach ( $post_ids as $post_id ) {
|
169 |
$this->inline_save_language( $post_id, $lang );
|
@@ -182,7 +182,7 @@ class PLL_Admin_Filters_Post extends PLL_Admin_Filters_Post_Base {
|
|
182 |
|
183 |
if ( isset( $_POST['post_ID'], $_POST['inline_lang_choice'] ) ) {
|
184 |
$post_id = (int) $_POST['post_ID'];
|
185 |
-
$lang = $this->model->get_language( $_POST['inline_lang_choice'] );
|
186 |
if ( $post_id && $lang ) {
|
187 |
$this->inline_save_language( $post_id, $lang );
|
188 |
}
|
104 |
* @since 2.3
|
105 |
*/
|
106 |
public function edit_post() {
|
107 |
+
if ( isset( $_POST['post_lang_choice'], $_POST['post_ID'] ) && $post_id = (int) $_POST['post_ID'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
108 |
check_admin_referer( 'pll_language', '_pll_nonce' );
|
109 |
|
110 |
$post = get_post( $post_id );
|
111 |
$post_type_object = get_post_type_object( $post->post_type );
|
112 |
|
113 |
if ( current_user_can( $post_type_object->cap->edit_post, $post_id ) ) {
|
114 |
+
$this->model->post->set_language( $post_id, $this->model->get_language( sanitize_key( $_POST['post_lang_choice'] ) ) );
|
115 |
|
116 |
if ( isset( $_POST['post_tr_lang'] ) ) {
|
117 |
+
$this->save_translations( $post_id, array_map( 'absint', $_POST['post_tr_lang'] ) );
|
118 |
}
|
119 |
}
|
120 |
}
|
160 |
* @since 2.3
|
161 |
*/
|
162 |
public function bulk_edit_posts() {
|
163 |
+
if ( isset( $_GET['bulk_edit'], $_GET['inline_lang_choice'], $_REQUEST['post'] ) && -1 !== $_GET['inline_lang_choice'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
164 |
check_admin_referer( 'bulk-posts' );
|
165 |
|
166 |
+
if ( $lang = $this->model->get_language( sanitize_key( $_GET['inline_lang_choice'] ) ) ) {
|
167 |
$post_ids = array_map( 'intval', (array) $_REQUEST['post'] );
|
168 |
foreach ( $post_ids as $post_id ) {
|
169 |
$this->inline_save_language( $post_id, $lang );
|
182 |
|
183 |
if ( isset( $_POST['post_ID'], $_POST['inline_lang_choice'] ) ) {
|
184 |
$post_id = (int) $_POST['post_ID'];
|
185 |
+
$lang = $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) );
|
186 |
if ( $post_id && $lang ) {
|
187 |
$this->inline_save_language( $post_id, $lang );
|
188 |
}
|
admin/admin-filters-term.php
CHANGED
@@ -55,16 +55,38 @@ class PLL_Admin_Filters_Term {
|
|
55 |
* @since 0.1
|
56 |
*/
|
57 |
public function add_term_form() {
|
58 |
-
|
59 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
|
61 |
-
if ( ! taxonomy_exists( $taxonomy ) || ! post_type_exists( $post_type ) ) {
|
62 |
return;
|
63 |
}
|
64 |
|
65 |
-
$
|
|
|
|
|
|
|
66 |
$dropdown = new PLL_Walker_Dropdown();
|
67 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
68 |
wp_nonce_field( 'pll_language', '_pll_nonce' );
|
69 |
|
70 |
printf(
|
@@ -74,20 +96,12 @@ class PLL_Admin_Filters_Term {
|
|
74 |
<p>%s</p>
|
75 |
</div>',
|
76 |
esc_html__( 'Language', 'polylang' ),
|
77 |
-
$
|
78 |
-
$this->model->get_languages_list(),
|
79 |
-
array(
|
80 |
-
'name' => 'term_lang_choice',
|
81 |
-
'value' => 'term_id',
|
82 |
-
'selected' => $lang ? $lang->term_id : '',
|
83 |
-
'flag' => true,
|
84 |
-
)
|
85 |
-
),
|
86 |
esc_html__( 'Sets the language', 'polylang' )
|
87 |
);
|
88 |
|
89 |
-
if ( ! empty( $
|
90 |
-
printf( '<input type="hidden" name="from_tag" value="%d" />', (int) $
|
91 |
}
|
92 |
|
93 |
// Adds translation fields
|
@@ -106,7 +120,13 @@ class PLL_Admin_Filters_Term {
|
|
106 |
* @param object $tag
|
107 |
*/
|
108 |
public function edit_term_form( $tag ) {
|
109 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
110 |
|
111 |
if ( ! post_type_exists( $post_type ) ) {
|
112 |
return;
|
@@ -118,15 +138,27 @@ class PLL_Admin_Filters_Term {
|
|
118 |
$lang = $this->model->term->get_language( $term_id );
|
119 |
$lang = empty( $lang ) ? $this->pref_lang : $lang;
|
120 |
|
121 |
-
$dropdown = new PLL_Walker_Dropdown();
|
122 |
-
|
123 |
// Disable the language dropdown and the translations input fields for default categories to prevent removal
|
124 |
$disabled = in_array( get_option( 'default_category' ), $this->model->term->get_translations( $term_id ) );
|
125 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
126 |
printf(
|
127 |
'<tr class="form-field">
|
128 |
<th scope="row">
|
129 |
-
%s
|
130 |
<label for="term_lang_choice">%s</label>
|
131 |
</th>
|
132 |
<td id="select-edit-term-language">
|
@@ -134,18 +166,8 @@ class PLL_Admin_Filters_Term {
|
|
134 |
<p class="description">%s</p>
|
135 |
</td>
|
136 |
</tr>',
|
137 |
-
wp_nonce_field( 'pll_language', '_pll_nonce', true, false ),
|
138 |
esc_html__( 'Language', 'polylang' ),
|
139 |
-
$
|
140 |
-
$this->model->get_languages_list(),
|
141 |
-
array(
|
142 |
-
'name' => 'term_lang_choice',
|
143 |
-
'value' => 'term_id',
|
144 |
-
'selected' => $lang ? $lang->term_id : '',
|
145 |
-
'disabled' => $disabled,
|
146 |
-
'flag' => true,
|
147 |
-
)
|
148 |
-
),
|
149 |
esc_html__( 'Sets the language', 'polylang' )
|
150 |
);
|
151 |
|
@@ -165,10 +187,15 @@ class PLL_Admin_Filters_Term {
|
|
165 |
* @return string modified html
|
166 |
*/
|
167 |
public function wp_dropdown_cats( $output ) {
|
168 |
-
if ( isset( $_GET['taxonomy']
|
169 |
-
$
|
|
|
|
|
|
|
|
|
|
|
170 |
if ( $term && $id = $term->parent ) {
|
171 |
-
$lang = $this->model->get_language( $_GET['new_lang'] );
|
172 |
if ( $parent = $this->model->term->get_translation( $id, $lang ) ) {
|
173 |
return str_replace( '"' . $parent . '"', '"' . $parent . '" selected="selected"', $output );
|
174 |
}
|
@@ -185,7 +212,7 @@ class PLL_Admin_Filters_Term {
|
|
185 |
* @param int $post_id
|
186 |
*/
|
187 |
public function pre_post_update( $post_id ) {
|
188 |
-
if ( isset( $_GET['bulk_edit'] ) ) {
|
189 |
$this->post_id = $post_id;
|
190 |
}
|
191 |
}
|
@@ -205,14 +232,13 @@ class PLL_Admin_Filters_Term {
|
|
205 |
|
206 |
// Edit tags
|
207 |
if ( isset( $_POST['term_lang_choice'] ) ) {
|
208 |
-
if ( '
|
209 |
-
check_ajax_referer(
|
210 |
-
}
|
211 |
-
|
212 |
-
check_admin_referer( 'pll_language', '_pll_nonce' ); // edit tags or tags metabox
|
213 |
}
|
214 |
|
215 |
-
$this->model->term->set_language( $term_id, $this->model->get_language( $_POST['term_lang_choice'] ) );
|
216 |
}
|
217 |
|
218 |
// *Post* bulk edit, in case a new term is created
|
@@ -252,7 +278,7 @@ class PLL_Admin_Filters_Term {
|
|
252 |
}
|
253 |
|
254 |
else {
|
255 |
-
$this->model->term->set_language( $term_id, $this->model->get_language( $_GET['inline_lang_choice'] ) );
|
256 |
}
|
257 |
}
|
258 |
|
@@ -264,7 +290,7 @@ class PLL_Admin_Filters_Term {
|
|
264 |
);
|
265 |
|
266 |
$old_lang = $this->model->term->get_language( $term_id ); // Stores the old language
|
267 |
-
$lang = $this->model->get_language( $_POST['inline_lang_choice'] ); // New language
|
268 |
$translations = $this->model->term->get_translations( $term_id );
|
269 |
|
270 |
// Checks if the new language already exists in the translation group
|
@@ -285,7 +311,7 @@ class PLL_Admin_Filters_Term {
|
|
285 |
// Edit post
|
286 |
elseif ( isset( $_POST['post_lang_choice'] ) ) { // FIXME should be useless now
|
287 |
check_admin_referer( 'pll_language', '_pll_nonce' );
|
288 |
-
$this->model->term->set_language( $term_id, $this->model->get_language( $_POST['post_lang_choice'] ) );
|
289 |
}
|
290 |
}
|
291 |
|
@@ -301,10 +327,14 @@ class PLL_Admin_Filters_Term {
|
|
301 |
// Security check as 'wp_update_term' can be called from outside WP admin
|
302 |
check_admin_referer( 'pll_language', '_pll_nonce' );
|
303 |
|
|
|
|
|
304 |
// Save translations after checking the translated term is in the right language ( as well as cast id to int )
|
305 |
-
|
306 |
-
|
307 |
-
|
|
|
|
|
308 |
}
|
309 |
|
310 |
$this->model->term->save_translations( $term_id, $translations );
|
@@ -332,10 +362,10 @@ class PLL_Admin_Filters_Term {
|
|
332 |
// As 'wp_update_term' can be called from outside WP admin
|
333 |
// 2nd test for creating tags when creating / editing a post
|
334 |
$tax = get_taxonomy( $taxonomy );
|
335 |
-
if ( current_user_can( $tax->cap->edit_terms ) || ( isset( $_POST['tax_input'][ $taxonomy ] ) && current_user_can( $tax->cap->assign_terms ) ) ) {
|
336 |
$this->save_language( $term_id, $taxonomy );
|
337 |
|
338 |
-
if ( isset( $_POST['term_tr_lang'] ) ) {
|
339 |
$translations = $this->save_translations( $term_id );
|
340 |
}
|
341 |
}
|
@@ -367,21 +397,21 @@ class PLL_Admin_Filters_Term {
|
|
367 |
|
368 |
// If the term already exists in another language
|
369 |
if ( ! $slug && $this->model->is_translated_taxonomy( $taxonomy ) && term_exists( $name, $taxonomy ) ) {
|
370 |
-
if ( isset( $_POST['term_lang_choice'] ) ) {
|
371 |
-
$slug = $name . '-' . $this->model->get_language( $_POST['term_lang_choice'] )->slug;
|
372 |
}
|
373 |
|
374 |
-
elseif ( isset( $_POST['inline_lang_choice'] ) ) {
|
375 |
-
$slug = $name . '-' . $this->model->get_language( $_POST['inline_lang_choice'] )->slug;
|
376 |
}
|
377 |
|
378 |
// *Post* bulk edit, in case a new term is created
|
379 |
-
elseif ( isset( $_GET['bulk_edit'], $_GET['inline_lang_choice'] ) ) {
|
380 |
// Bulk edit does not modify the language
|
381 |
-
if ( -1 == $_GET['inline_lang_choice'] ) {
|
382 |
$slug = $name . '-' . $this->model->post->get_language( $this->post_id )->slug;
|
383 |
} else {
|
384 |
-
$slug = $name . '-' . $this->model->get_language( $_GET['inline_lang_choice'] )->slug;
|
385 |
}
|
386 |
}
|
387 |
}
|
@@ -397,13 +427,17 @@ class PLL_Admin_Filters_Term {
|
|
397 |
public function term_lang_choice() {
|
398 |
check_ajax_referer( 'pll_language', '_pll_nonce' );
|
399 |
|
400 |
-
|
|
|
|
|
|
|
|
|
401 |
$term_id = isset( $_POST['term_id'] ) ? (int) $_POST['term_id'] : null;
|
402 |
-
$taxonomy = $_POST['taxonomy'];
|
403 |
-
$post_type = $_POST['post_type'];
|
404 |
|
405 |
if ( ! post_type_exists( $post_type ) || ! taxonomy_exists( $taxonomy ) ) {
|
406 |
-
|
407 |
}
|
408 |
|
409 |
ob_start();
|
@@ -423,7 +457,7 @@ class PLL_Admin_Filters_Term {
|
|
423 |
'name' => 'parent',
|
424 |
'orderby' => 'name',
|
425 |
'hierarchical' => true,
|
426 |
-
'show_option_none' => __( 'None' ),
|
427 |
'echo' => 0,
|
428 |
);
|
429 |
$x->Add( array( 'what' => 'parent', 'data' => wp_dropdown_categories( $args ) ) );
|
@@ -460,16 +494,20 @@ class PLL_Admin_Filters_Term {
|
|
460 |
public function ajax_terms_not_translated() {
|
461 |
check_ajax_referer( 'pll_language', '_pll_nonce' );
|
462 |
|
463 |
-
|
464 |
-
|
465 |
-
|
|
|
|
|
|
|
|
|
466 |
|
467 |
if ( ! post_type_exists( $post_type ) || ! taxonomy_exists( $taxonomy ) ) {
|
468 |
-
|
469 |
}
|
470 |
|
471 |
-
$term_language = $this->model->get_language( $_GET['term_language'] );
|
472 |
-
$translation_language = $this->model->get_language( $_GET['translation_language'] );
|
473 |
|
474 |
$return = array();
|
475 |
|
@@ -487,8 +525,8 @@ class PLL_Admin_Filters_Term {
|
|
487 |
}
|
488 |
|
489 |
// Add current translation in list
|
490 |
-
// Not in add term
|
491 |
-
if ( 'undefined' !== $_GET['term_id'] && $term_id = $this->model->term->get_translation( (int) $_GET['term_id'], $translation_language ) ) {
|
492 |
$term = get_term( $term_id, $taxonomy );
|
493 |
array_unshift(
|
494 |
$return,
|
@@ -500,7 +538,7 @@ class PLL_Admin_Filters_Term {
|
|
500 |
);
|
501 |
}
|
502 |
|
503 |
-
wp_die(
|
504 |
}
|
505 |
|
506 |
/**
|
@@ -577,7 +615,7 @@ class PLL_Admin_Filters_Term {
|
|
577 |
$translations[ $key ] = _split_shared_term( $tr_id, $tr_term->term_taxonomy_id );
|
578 |
|
579 |
// Hack translation ids sent by the form to avoid overwrite in PLL_Admin_Filters_Term::save_translations
|
580 |
-
if ( isset( $_POST['term_tr_lang'][ $key ] ) && $_POST['term_tr_lang'][ $key ] == $tr_id ) {
|
581 |
$_POST['term_tr_lang'][ $key ] = $translations[ $key ];
|
582 |
}
|
583 |
}
|
55 |
* @since 0.1
|
56 |
*/
|
57 |
public function add_term_form() {
|
58 |
+
if ( isset( $_GET['taxonomy'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
59 |
+
$taxonomy = sanitize_key( $_GET['taxonomy'] ); // phpcs:ignore WordPress.Security.NonceVerification
|
60 |
+
}
|
61 |
+
|
62 |
+
if ( isset( $_REQUEST['post_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
63 |
+
$post_type = sanitize_key( $_REQUEST['post_type'] ); // phpcs:ignore WordPress.Security.NonceVerification
|
64 |
+
}
|
65 |
+
|
66 |
+
if ( isset( $GLOBALS['post_type'] ) ) {
|
67 |
+
$post_type = $GLOBALS['post_type'];
|
68 |
+
}
|
69 |
|
70 |
+
if ( empty( $taxonomy ) || ! taxonomy_exists( $taxonomy ) || ! post_type_exists( $post_type ) ) {
|
71 |
return;
|
72 |
}
|
73 |
|
74 |
+
$from_term_id = isset( $_GET['from_tag'] ) ? (int) $_GET['from_tag'] : 0; // phpcs:ignore WordPress.Security.NonceVerification
|
75 |
+
|
76 |
+
$lang = isset( $_GET['new_lang'] ) ? $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ) : $this->pref_lang; // phpcs:ignore WordPress.Security.NonceVerification
|
77 |
+
|
78 |
$dropdown = new PLL_Walker_Dropdown();
|
79 |
|
80 |
+
$dropdown_html = $dropdown->walk(
|
81 |
+
$this->model->get_languages_list(),
|
82 |
+
array(
|
83 |
+
'name' => 'term_lang_choice',
|
84 |
+
'value' => 'term_id',
|
85 |
+
'selected' => $lang ? $lang->term_id : '',
|
86 |
+
'flag' => true,
|
87 |
+
)
|
88 |
+
);
|
89 |
+
|
90 |
wp_nonce_field( 'pll_language', '_pll_nonce' );
|
91 |
|
92 |
printf(
|
96 |
<p>%s</p>
|
97 |
</div>',
|
98 |
esc_html__( 'Language', 'polylang' ),
|
99 |
+
$dropdown_html, // phpcs:ignore
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
esc_html__( 'Sets the language', 'polylang' )
|
101 |
);
|
102 |
|
103 |
+
if ( ! empty( $from_term_id ) ) {
|
104 |
+
printf( '<input type="hidden" name="from_tag" value="%d" />', (int) $from_term_id );
|
105 |
}
|
106 |
|
107 |
// Adds translation fields
|
120 |
* @param object $tag
|
121 |
*/
|
122 |
public function edit_term_form( $tag ) {
|
123 |
+
if ( isset( $_REQUEST['post_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
124 |
+
$post_type = sanitize_key( $_REQUEST['post_type'] ); // phpcs:ignore WordPress.Security.NonceVerification
|
125 |
+
}
|
126 |
+
|
127 |
+
if ( isset( $GLOBALS['post_type'] ) ) {
|
128 |
+
$post_type = $GLOBALS['post_type'];
|
129 |
+
}
|
130 |
|
131 |
if ( ! post_type_exists( $post_type ) ) {
|
132 |
return;
|
138 |
$lang = $this->model->term->get_language( $term_id );
|
139 |
$lang = empty( $lang ) ? $this->pref_lang : $lang;
|
140 |
|
|
|
|
|
141 |
// Disable the language dropdown and the translations input fields for default categories to prevent removal
|
142 |
$disabled = in_array( get_option( 'default_category' ), $this->model->term->get_translations( $term_id ) );
|
143 |
|
144 |
+
$dropdown = new PLL_Walker_Dropdown();
|
145 |
+
|
146 |
+
$dropdown_html = $dropdown->walk(
|
147 |
+
$this->model->get_languages_list(),
|
148 |
+
array(
|
149 |
+
'name' => 'term_lang_choice',
|
150 |
+
'value' => 'term_id',
|
151 |
+
'selected' => $lang ? $lang->term_id : '',
|
152 |
+
'disabled' => $disabled,
|
153 |
+
'flag' => true,
|
154 |
+
)
|
155 |
+
);
|
156 |
+
|
157 |
+
wp_nonce_field( 'pll_language', '_pll_nonce' );
|
158 |
+
|
159 |
printf(
|
160 |
'<tr class="form-field">
|
161 |
<th scope="row">
|
|
|
162 |
<label for="term_lang_choice">%s</label>
|
163 |
</th>
|
164 |
<td id="select-edit-term-language">
|
166 |
<p class="description">%s</p>
|
167 |
</td>
|
168 |
</tr>',
|
|
|
169 |
esc_html__( 'Language', 'polylang' ),
|
170 |
+
$dropdown_html, // phpcs:ignore
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
171 |
esc_html__( 'Sets the language', 'polylang' )
|
172 |
);
|
173 |
|
187 |
* @return string modified html
|
188 |
*/
|
189 |
public function wp_dropdown_cats( $output ) {
|
190 |
+
if ( isset( $_GET['taxonomy'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
191 |
+
$taxonomy = sanitize_key( $_GET['taxonomy'] ); // phpcs:ignore WordPress.Security.NonceVerification
|
192 |
+
}
|
193 |
+
|
194 |
+
if ( isset( $taxonomy, $_GET['from_tag'], $_GET['new_lang'] ) && taxonomy_exists( $taxonomy ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
195 |
+
$term = get_term( (int) $_GET['from_tag'], $taxonomy ); // phpcs:ignore WordPress.Security.NonceVerification
|
196 |
+
|
197 |
if ( $term && $id = $term->parent ) {
|
198 |
+
$lang = $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
199 |
if ( $parent = $this->model->term->get_translation( $id, $lang ) ) {
|
200 |
return str_replace( '"' . $parent . '"', '"' . $parent . '" selected="selected"', $output );
|
201 |
}
|
212 |
* @param int $post_id
|
213 |
*/
|
214 |
public function pre_post_update( $post_id ) {
|
215 |
+
if ( isset( $_GET['bulk_edit'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
216 |
$this->post_id = $post_id;
|
217 |
}
|
218 |
}
|
232 |
|
233 |
// Edit tags
|
234 |
if ( isset( $_POST['term_lang_choice'] ) ) {
|
235 |
+
if ( isset( $_POST['action'] ) && sanitize_key( $_POST['action'] ) === 'add-' . $taxonomy ) { // phpcs:ignore WordPress.Security.NonceVerification
|
236 |
+
check_ajax_referer( 'add-' . $taxonomy, '_ajax_nonce-add-' . $taxonomy ); // Category metabox
|
237 |
+
} else {
|
238 |
+
check_admin_referer( 'pll_language', '_pll_nonce' ); // Edit tags or tags metabox
|
|
|
239 |
}
|
240 |
|
241 |
+
$this->model->term->set_language( $term_id, $this->model->get_language( sanitize_key( $_POST['term_lang_choice'] ) ) );
|
242 |
}
|
243 |
|
244 |
// *Post* bulk edit, in case a new term is created
|
278 |
}
|
279 |
|
280 |
else {
|
281 |
+
$this->model->term->set_language( $term_id, $this->model->get_language( sanitize_key( $_GET['inline_lang_choice'] ) ) );
|
282 |
}
|
283 |
}
|
284 |
|
290 |
);
|
291 |
|
292 |
$old_lang = $this->model->term->get_language( $term_id ); // Stores the old language
|
293 |
+
$lang = $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) ); // New language
|
294 |
$translations = $this->model->term->get_translations( $term_id );
|
295 |
|
296 |
// Checks if the new language already exists in the translation group
|
311 |
// Edit post
|
312 |
elseif ( isset( $_POST['post_lang_choice'] ) ) { // FIXME should be useless now
|
313 |
check_admin_referer( 'pll_language', '_pll_nonce' );
|
314 |
+
$this->model->term->set_language( $term_id, $this->model->get_language( sanitize_key( $_POST['post_lang_choice'] ) ) );
|
315 |
}
|
316 |
}
|
317 |
|
327 |
// Security check as 'wp_update_term' can be called from outside WP admin
|
328 |
check_admin_referer( 'pll_language', '_pll_nonce' );
|
329 |
|
330 |
+
$translations = array();
|
331 |
+
|
332 |
// Save translations after checking the translated term is in the right language ( as well as cast id to int )
|
333 |
+
if ( isset( $_POST['term_tr_lang'] ) ) {
|
334 |
+
foreach ( array_map( 'absint', $_POST['term_tr_lang'] ) as $lang => $tr_id ) {
|
335 |
+
$tr_lang = $this->model->term->get_language( $tr_id );
|
336 |
+
$translations[ $lang ] = $tr_lang && $tr_lang->slug == $lang ? $tr_id : 0;
|
337 |
+
}
|
338 |
}
|
339 |
|
340 |
$this->model->term->save_translations( $term_id, $translations );
|
362 |
// As 'wp_update_term' can be called from outside WP admin
|
363 |
// 2nd test for creating tags when creating / editing a post
|
364 |
$tax = get_taxonomy( $taxonomy );
|
365 |
+
if ( current_user_can( $tax->cap->edit_terms ) || ( isset( $_POST['tax_input'][ $taxonomy ] ) && current_user_can( $tax->cap->assign_terms ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
366 |
$this->save_language( $term_id, $taxonomy );
|
367 |
|
368 |
+
if ( isset( $_POST['term_tr_lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
369 |
$translations = $this->save_translations( $term_id );
|
370 |
}
|
371 |
}
|
397 |
|
398 |
// If the term already exists in another language
|
399 |
if ( ! $slug && $this->model->is_translated_taxonomy( $taxonomy ) && term_exists( $name, $taxonomy ) ) {
|
400 |
+
if ( isset( $_POST['term_lang_choice'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
401 |
+
$slug = $name . '-' . $this->model->get_language( sanitize_key( $_POST['term_lang_choice'] ) )->slug; // phpcs:ignore WordPress.Security.NonceVerification
|
402 |
}
|
403 |
|
404 |
+
elseif ( isset( $_POST['inline_lang_choice'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
405 |
+
$slug = $name . '-' . $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) )->slug; // phpcs:ignore WordPress.Security.NonceVerification
|
406 |
}
|
407 |
|
408 |
// *Post* bulk edit, in case a new term is created
|
409 |
+
elseif ( isset( $_GET['bulk_edit'], $_GET['inline_lang_choice'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
410 |
// Bulk edit does not modify the language
|
411 |
+
if ( -1 == $_GET['inline_lang_choice'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
412 |
$slug = $name . '-' . $this->model->post->get_language( $this->post_id )->slug;
|
413 |
} else {
|
414 |
+
$slug = $name . '-' . $this->model->get_language( sanitize_key( $_GET['inline_lang_choice'] ) )->slug; // phpcs:ignore WordPress.Security.NonceVerification
|
415 |
}
|
416 |
}
|
417 |
}
|
427 |
public function term_lang_choice() {
|
428 |
check_ajax_referer( 'pll_language', '_pll_nonce' );
|
429 |
|
430 |
+
if ( ! isset( $_POST['taxonomy'], $_POST['post_type'], $_POST['lang'] ) ) {
|
431 |
+
wp_die( 0 );
|
432 |
+
}
|
433 |
+
|
434 |
+
$lang = $this->model->get_language( sanitize_key( $_POST['lang'] ) );
|
435 |
$term_id = isset( $_POST['term_id'] ) ? (int) $_POST['term_id'] : null;
|
436 |
+
$taxonomy = sanitize_key( $_POST['taxonomy'] );
|
437 |
+
$post_type = sanitize_key( $_POST['post_type'] );
|
438 |
|
439 |
if ( ! post_type_exists( $post_type ) || ! taxonomy_exists( $taxonomy ) ) {
|
440 |
+
wp_die( 0 );
|
441 |
}
|
442 |
|
443 |
ob_start();
|
457 |
'name' => 'parent',
|
458 |
'orderby' => 'name',
|
459 |
'hierarchical' => true,
|
460 |
+
'show_option_none' => __( 'None', 'polylang' ),
|
461 |
'echo' => 0,
|
462 |
);
|
463 |
$x->Add( array( 'what' => 'parent', 'data' => wp_dropdown_categories( $args ) ) );
|
494 |
public function ajax_terms_not_translated() {
|
495 |
check_ajax_referer( 'pll_language', '_pll_nonce' );
|
496 |
|
497 |
+
if ( ! isset( $_GET['term'], $_GET['post_type'], $_GET['taxonomy'], $_GET['term_language'], $_GET['translation_language'] ) ) {
|
498 |
+
wp_die( 0 );
|
499 |
+
}
|
500 |
+
|
501 |
+
$s = wp_unslash( $_GET['term'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
502 |
+
$post_type = sanitize_key( $_GET['post_type'] );
|
503 |
+
$taxonomy = sanitize_key( $_GET['taxonomy'] );
|
504 |
|
505 |
if ( ! post_type_exists( $post_type ) || ! taxonomy_exists( $taxonomy ) ) {
|
506 |
+
wp_die( 0 );
|
507 |
}
|
508 |
|
509 |
+
$term_language = $this->model->get_language( sanitize_key( $_GET['term_language'] ) );
|
510 |
+
$translation_language = $this->model->get_language( sanitize_key( $_GET['translation_language'] ) );
|
511 |
|
512 |
$return = array();
|
513 |
|
525 |
}
|
526 |
|
527 |
// Add current translation in list
|
528 |
+
// Not in add term as term_id is not set
|
529 |
+
if ( isset( $_GET['term_id'] ) && 'undefined' !== $_GET['term_id'] && $term_id = $this->model->term->get_translation( (int) $_GET['term_id'], $translation_language ) ) {
|
530 |
$term = get_term( $term_id, $taxonomy );
|
531 |
array_unshift(
|
532 |
$return,
|
538 |
);
|
539 |
}
|
540 |
|
541 |
+
wp_die( wp_json_encode( $return ) );
|
542 |
}
|
543 |
|
544 |
/**
|
615 |
$translations[ $key ] = _split_shared_term( $tr_id, $tr_term->term_taxonomy_id );
|
616 |
|
617 |
// Hack translation ids sent by the form to avoid overwrite in PLL_Admin_Filters_Term::save_translations
|
618 |
+
if ( isset( $_POST['term_tr_lang'][ $key ] ) && $_POST['term_tr_lang'][ $key ] == $tr_id ) { // phpcs:ignore WordPress.Security.NonceVerification
|
619 |
$_POST['term_tr_lang'][ $key ] = $translations[ $key ];
|
620 |
}
|
621 |
}
|
admin/admin-filters.php
CHANGED
@@ -57,24 +57,27 @@ class PLL_Admin_Filters extends PLL_Filters {
|
|
57 |
$screen = get_current_screen();
|
58 |
|
59 |
// Test the Widgets screen and the Customizer to avoid displaying the option in page builders
|
60 |
-
// Saving the widget reloads the form. And curiously the action is in $_REQUEST but neither in $_POST,
|
61 |
-
if ( ( isset( $screen ) && 'widgets' === $screen->base ) || ( isset( $_REQUEST['action'] ) && 'save-widget' === $_REQUEST['action'] ) || isset( $GLOBALS['wp_customize'] ) ) {
|
62 |
$dropdown = new PLL_Walker_Dropdown();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
printf(
|
64 |
'<p><label for="%1$s">%2$s %3$s</label></p>',
|
65 |
esc_attr( $widget->id . '_lang_choice' ),
|
66 |
esc_html__( 'The widget is displayed for:', 'polylang' ),
|
67 |
-
$
|
68 |
-
array_merge(
|
69 |
-
array( (object) array( 'slug' => 0, 'name' => __( 'All languages', 'polylang' ) ) ),
|
70 |
-
$this->model->get_languages_list()
|
71 |
-
),
|
72 |
-
array(
|
73 |
-
'name' => $widget->id . '_lang_choice',
|
74 |
-
'class' => 'tags-input pll-lang-choice',
|
75 |
-
'selected' => empty( $instance['pll_lang'] ) ? '' : $instance['pll_lang'],
|
76 |
-
)
|
77 |
-
)
|
78 |
);
|
79 |
}
|
80 |
}
|
@@ -92,8 +95,10 @@ class PLL_Admin_Filters extends PLL_Filters {
|
|
92 |
* @return array Widget options
|
93 |
*/
|
94 |
public function widget_update_callback( $instance, $new_instance, $old_instance, $widget ) {
|
95 |
-
|
96 |
-
|
|
|
|
|
97 |
} else {
|
98 |
unset( $instance['pll_lang'] );
|
99 |
}
|
@@ -112,7 +117,7 @@ class PLL_Admin_Filters extends PLL_Filters {
|
|
112 |
// Biography translations
|
113 |
foreach ( $this->model->get_languages_list() as $lang ) {
|
114 |
$meta = $lang->slug == $this->options['default_lang'] ? 'description' : 'description_' . $lang->slug;
|
115 |
-
$description = empty( $_POST[ 'description_' . $lang->slug ] ) ? '' : trim( $_POST[ 'description_' . $lang->slug ] );
|
116 |
|
117 |
/** This filter is documented in wp-includes/user.php */
|
118 |
$description = apply_filters( 'pre_user_description', $description ); // Applies WP default filter wp_filter_kses
|
@@ -183,11 +188,11 @@ class PLL_Admin_Filters extends PLL_Filters {
|
|
183 |
* @return string
|
184 |
*/
|
185 |
public function get_locale( $locale ) {
|
186 |
-
if ( isset( $_POST['post_lang_choice'] ) && $lang = $this->model->get_language( $_POST['post_lang_choice'] ) ) {
|
187 |
$locale = $lang->locale;
|
188 |
-
} elseif ( isset( $_POST['term_lang_choice'] ) && $lang = $this->model->get_language( $_POST['term_lang_choice'] ) ) {
|
189 |
$locale = $lang->locale;
|
190 |
-
} elseif ( isset( $_POST['inline_lang_choice'] ) && $lang = $this->model->get_language( $_POST['inline_lang_choice'] ) ) {
|
191 |
$locale = $lang->locale;
|
192 |
} elseif ( ! empty( $this->curlang ) ) {
|
193 |
$locale = $this->curlang->locale;
|
57 |
$screen = get_current_screen();
|
58 |
|
59 |
// Test the Widgets screen and the Customizer to avoid displaying the option in page builders
|
60 |
+
// Saving the widget reloads the form. And curiously the action is in $_REQUEST but neither in $_POST, nor in $_GET.
|
61 |
+
if ( ( isset( $screen ) && 'widgets' === $screen->base ) || ( isset( $_REQUEST['action'] ) && 'save-widget' === $_REQUEST['action'] ) || isset( $GLOBALS['wp_customize'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
62 |
$dropdown = new PLL_Walker_Dropdown();
|
63 |
+
|
64 |
+
$dropdown_html = $dropdown->walk(
|
65 |
+
array_merge(
|
66 |
+
array( (object) array( 'slug' => 0, 'name' => __( 'All languages', 'polylang' ) ) ),
|
67 |
+
$this->model->get_languages_list()
|
68 |
+
),
|
69 |
+
array(
|
70 |
+
'name' => $widget->id . '_lang_choice',
|
71 |
+
'class' => 'tags-input pll-lang-choice',
|
72 |
+
'selected' => empty( $instance['pll_lang'] ) ? '' : $instance['pll_lang'],
|
73 |
+
)
|
74 |
+
);
|
75 |
+
|
76 |
printf(
|
77 |
'<p><label for="%1$s">%2$s %3$s</label></p>',
|
78 |
esc_attr( $widget->id . '_lang_choice' ),
|
79 |
esc_html__( 'The widget is displayed for:', 'polylang' ),
|
80 |
+
$dropdown_html // phpcs:ignore WordPress.Security.EscapeOutput
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
);
|
82 |
}
|
83 |
}
|
95 |
* @return array Widget options
|
96 |
*/
|
97 |
public function widget_update_callback( $instance, $new_instance, $old_instance, $widget ) {
|
98 |
+
$key = $widget->id . '_lang_choice';
|
99 |
+
|
100 |
+
if ( ! empty( $_POST[ $key ] ) && $lang = $this->model->get_language( sanitize_key( $_POST[ $key ] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
101 |
+
$instance['pll_lang'] = $lang->slug;
|
102 |
} else {
|
103 |
unset( $instance['pll_lang'] );
|
104 |
}
|
117 |
// Biography translations
|
118 |
foreach ( $this->model->get_languages_list() as $lang ) {
|
119 |
$meta = $lang->slug == $this->options['default_lang'] ? 'description' : 'description_' . $lang->slug;
|
120 |
+
$description = empty( $_POST[ 'description_' . $lang->slug ] ) ? '' : trim( $_POST[ 'description_' . $lang->slug ] ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
|
121 |
|
122 |
/** This filter is documented in wp-includes/user.php */
|
123 |
$description = apply_filters( 'pre_user_description', $description ); // Applies WP default filter wp_filter_kses
|
188 |
* @return string
|
189 |
*/
|
190 |
public function get_locale( $locale ) {
|
191 |
+
if ( isset( $_POST['post_lang_choice'] ) && $lang = $this->model->get_language( sanitize_key( $_POST['post_lang_choice'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
192 |
$locale = $lang->locale;
|
193 |
+
} elseif ( isset( $_POST['term_lang_choice'] ) && $lang = $this->model->get_language( sanitize_key( $_POST['term_lang_choice'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
194 |
$locale = $lang->locale;
|
195 |
+
} elseif ( isset( $_POST['inline_lang_choice'] ) && $lang = $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
196 |
$locale = $lang->locale;
|
197 |
} elseif ( ! empty( $this->curlang ) ) {
|
198 |
$locale = $this->curlang->locale;
|
admin/admin-links.php
CHANGED
@@ -7,16 +7,63 @@
|
|
7 |
*/
|
8 |
class PLL_Admin_Links extends PLL_Links {
|
9 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
/**
|
11 |
* Get the link to create a new post translation
|
12 |
*
|
13 |
* @since 1.5
|
14 |
*
|
15 |
-
* @param int $post_id
|
16 |
-
* @param object $language
|
|
|
|
|
17 |
* @return string
|
18 |
*/
|
19 |
-
public function get_new_post_translation_link( $post_id, $language ) {
|
20 |
$post_type = get_post_type( $post_id );
|
21 |
$post_type_object = get_post_type_object( get_post_type( $post_id ) );
|
22 |
if ( ! current_user_can( $post_type_object->cap->create_posts ) ) {
|
@@ -31,15 +78,21 @@ class PLL_Admin_Links extends PLL_Links {
|
|
31 |
}
|
32 |
}
|
33 |
|
34 |
-
if ( 'attachment'
|
35 |
$args = array(
|
36 |
'action' => 'translate_media',
|
37 |
'from_media' => $post_id,
|
38 |
'new_lang' => $language->slug,
|
39 |
);
|
40 |
|
|
|
|
|
41 |
// Add nonce for media as we will directly publish a new attachment from a click on this link
|
42 |
-
|
|
|
|
|
|
|
|
|
43 |
} else {
|
44 |
$args = array(
|
45 |
'post_type' => $post_type,
|
@@ -47,7 +100,13 @@ class PLL_Admin_Links extends PLL_Links {
|
|
47 |
'new_lang' => $language->slug,
|
48 |
);
|
49 |
|
50 |
-
$link =
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
}
|
52 |
|
53 |
/**
|
@@ -73,12 +132,7 @@ class PLL_Admin_Links extends PLL_Links {
|
|
73 |
*/
|
74 |
public function new_post_translation_link( $post_id, $language ) {
|
75 |
$link = $this->get_new_post_translation_link( $post_id, $language );
|
76 |
-
return $link
|
77 |
-
'<a href="%1$s" class="pll_icon_add"><span class="screen-reader-text">%2$s</span></a>',
|
78 |
-
esc_url( $link ),
|
79 |
-
/* translators: accessibility text, %s is a native language name */
|
80 |
-
esc_html( sprintf( __( 'Add a translation in %s', 'polylang' ), $language->name ) )
|
81 |
-
) : '';
|
82 |
}
|
83 |
|
84 |
/**
|
@@ -92,12 +146,7 @@ class PLL_Admin_Links extends PLL_Links {
|
|
92 |
public function edit_post_translation_link( $post_id ) {
|
93 |
$link = get_edit_post_link( $post_id );
|
94 |
$language = $this->model->post->get_language( $post_id );
|
95 |
-
return $link
|
96 |
-
'<a href="%1$s" class="pll_icon_edit"><span class="screen-reader-text">%2$s</span></a>',
|
97 |
-
esc_url( $link ),
|
98 |
-
/* translators: accessibility text, %s is a native language name */
|
99 |
-
esc_html( sprintf( __( 'Edit the translation in %s', 'polylang' ), $language->name ) )
|
100 |
-
) : '';
|
101 |
}
|
102 |
|
103 |
/**
|
@@ -153,12 +202,7 @@ class PLL_Admin_Links extends PLL_Links {
|
|
153 |
*/
|
154 |
public function new_term_translation_link( $term_id, $taxonomy, $post_type, $language ) {
|
155 |
$link = $this->get_new_term_translation_link( $term_id, $taxonomy, $post_type, $language );
|
156 |
-
return $link
|
157 |
-
'<a href="%1$s" class="pll_icon_add"><span class="screen-reader-text">%2$s</span></a>',
|
158 |
-
esc_url( $link ),
|
159 |
-
/* translators: accessibility text, %s is a native language name */
|
160 |
-
esc_html( sprintf( __( 'Add a translation in %s', 'polylang' ), $language->name ) )
|
161 |
-
) : '';
|
162 |
}
|
163 |
|
164 |
/**
|
@@ -174,11 +218,6 @@ class PLL_Admin_Links extends PLL_Links {
|
|
174 |
public function edit_term_translation_link( $term_id, $taxonomy, $post_type ) {
|
175 |
$link = get_edit_term_link( $term_id, $taxonomy, $post_type );
|
176 |
$language = $this->model->term->get_language( $term_id );
|
177 |
-
return $link
|
178 |
-
'<a href="%1$s" class="pll_icon_edit"><span class="screen-reader-text">%2$s</span></a>',
|
179 |
-
esc_url( $link ),
|
180 |
-
/* translators: accessibility text, %s is a native language name */
|
181 |
-
esc_html( sprintf( __( 'Edit the translation in %s', 'polylang' ), $language->name ) )
|
182 |
-
) : '';
|
183 |
}
|
184 |
}
|
7 |
*/
|
8 |
class PLL_Admin_Links extends PLL_Links {
|
9 |
|
10 |
+
/**
|
11 |
+
* Returns html markup for a new translation link
|
12 |
+
*
|
13 |
+
* @since 2.6
|
14 |
+
*
|
15 |
+
* @param string $link The new translation link.
|
16 |
+
* @param object $language The language of the new translation.
|
17 |
+
* @return string
|
18 |
+
*/
|
19 |
+
protected function new_translation_link( $link, $language ) {
|
20 |
+
$str = '';
|
21 |
+
|
22 |
+
if ( $link ) {
|
23 |
+
/* translators: accessibility text, %s is a native language name */
|
24 |
+
$hint = sprintf( __( 'Add a translation in %s', 'polylang' ), $language->name );
|
25 |
+
|
26 |
+
$str = sprintf(
|
27 |
+
'<a href="%1$s" title="%2$s" class="pll_icon_add"><span class="screen-reader-text">%3$s</span></a>',
|
28 |
+
esc_url( $link ),
|
29 |
+
esc_attr( $hint ),
|
30 |
+
esc_html( $hint )
|
31 |
+
);
|
32 |
+
}
|
33 |
+
|
34 |
+
return $str;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Returns html markup for a translation link
|
39 |
+
*
|
40 |
+
* @since 2.6
|
41 |
+
*
|
42 |
+
* @param string $link The translation link.
|
43 |
+
* @param object $language The language of the translation.
|
44 |
+
* @return string
|
45 |
+
*/
|
46 |
+
public function edit_translation_link( $link, $language ) {
|
47 |
+
return $link ? sprintf(
|
48 |
+
'<a href="%1$s" class="pll_icon_edit"><span class="screen-reader-text">%2$s</span></a>',
|
49 |
+
esc_url( $link ),
|
50 |
+
/* translators: accessibility text, %s is a native language name */
|
51 |
+
esc_html( sprintf( __( 'Edit the translation in %s', 'polylang' ), $language->name ) )
|
52 |
+
) : '';
|
53 |
+
}
|
54 |
+
|
55 |
/**
|
56 |
* Get the link to create a new post translation
|
57 |
*
|
58 |
* @since 1.5
|
59 |
*
|
60 |
+
* @param int $post_id The source post id.
|
61 |
+
* @param object $language The language of the new translation.
|
62 |
+
* @param string $context Optional. Defaults to 'display' which encodes '&' to '&'.
|
63 |
+
* Otherwise, preserves '&'.
|
64 |
* @return string
|
65 |
*/
|
66 |
+
public function get_new_post_translation_link( $post_id, $language, $context = 'display' ) {
|
67 |
$post_type = get_post_type( $post_id );
|
68 |
$post_type_object = get_post_type_object( get_post_type( $post_id ) );
|
69 |
if ( ! current_user_can( $post_type_object->cap->create_posts ) ) {
|
78 |
}
|
79 |
}
|
80 |
|
81 |
+
if ( 'attachment' === $post_type ) {
|
82 |
$args = array(
|
83 |
'action' => 'translate_media',
|
84 |
'from_media' => $post_id,
|
85 |
'new_lang' => $language->slug,
|
86 |
);
|
87 |
|
88 |
+
$link = add_query_arg( $args, admin_url( 'admin.php' ) );
|
89 |
+
|
90 |
// Add nonce for media as we will directly publish a new attachment from a click on this link
|
91 |
+
if ( 'display' === $context ) {
|
92 |
+
$link = wp_nonce_url( $link, 'translate_media' );
|
93 |
+
} else {
|
94 |
+
$link = add_query_arg( '_wpnonce', wp_create_nonce( 'translate_media' ), $link );
|
95 |
+
}
|
96 |
} else {
|
97 |
$args = array(
|
98 |
'post_type' => $post_type,
|
100 |
'new_lang' => $language->slug,
|
101 |
);
|
102 |
|
103 |
+
$link = add_query_arg( $args, admin_url( 'post-new.php' ) );
|
104 |
+
|
105 |
+
if ( 'display' === $context ) {
|
106 |
+
$link = wp_nonce_url( $link, 'new-post-translation' );
|
107 |
+
} else {
|
108 |
+
$link = add_query_arg( '_wpnonce', wp_create_nonce( 'new-post-translation' ), $link );
|
109 |
+
}
|
110 |
}
|
111 |
|
112 |
/**
|
132 |
*/
|
133 |
public function new_post_translation_link( $post_id, $language ) {
|
134 |
$link = $this->get_new_post_translation_link( $post_id, $language );
|
135 |
+
return $this->new_translation_link( $link, $language );
|
|
|
|
|
|
|
|
|
|
|
136 |
}
|
137 |
|
138 |
/**
|
146 |
public function edit_post_translation_link( $post_id ) {
|
147 |
$link = get_edit_post_link( $post_id );
|
148 |
$language = $this->model->post->get_language( $post_id );
|
149 |
+
return $this->edit_translation_link( $link, $language );
|
|
|
|
|
|
|
|
|
|
|
150 |
}
|
151 |
|
152 |
/**
|
202 |
*/
|
203 |
public function new_term_translation_link( $term_id, $taxonomy, $post_type, $language ) {
|
204 |
$link = $this->get_new_term_translation_link( $term_id, $taxonomy, $post_type, $language );
|
205 |
+
return $this->new_translation_link( $link, $language );
|
|
|
|
|
|
|
|
|
|
|
206 |
}
|
207 |
|
208 |
/**
|
218 |
public function edit_term_translation_link( $term_id, $taxonomy, $post_type ) {
|
219 |
$link = get_edit_term_link( $term_id, $taxonomy, $post_type );
|
220 |
$language = $this->model->term->get_language( $term_id );
|
221 |
+
return $this->edit_translation_link( $link, $language );
|
|
|
|
|
|
|
|
|
|
|
222 |
}
|
223 |
}
|
admin/admin-model.php
CHANGED
@@ -28,17 +28,17 @@ class PLL_Admin_Model extends PLL_Model {
|
|
28 |
* @return bool true if success / false if failed
|
29 |
*/
|
30 |
public function add_language( $args ) {
|
31 |
-
|
32 |
-
|
|
|
33 |
}
|
34 |
|
35 |
// First the language taxonomy
|
36 |
-
$description =
|
37 |
$r = wp_insert_term( $args['name'], 'language', array( 'slug' => $args['slug'], 'description' => $description ) );
|
38 |
if ( is_wp_error( $r ) ) {
|
39 |
// Avoid an ugly fatal error if something went wrong ( reported once in the forum )
|
40 |
-
|
41 |
-
return false;
|
42 |
}
|
43 |
wp_update_term( (int) $r['term_id'], 'language', array( 'term_group' => (int) $args['term_group'] ) ); // can't set the term group directly in wp_insert_term
|
44 |
|
@@ -74,8 +74,6 @@ class PLL_Admin_Model extends PLL_Model {
|
|
74 |
|
75 |
$this->clean_languages_cache(); // Again to set add mo_id in the cached languages list
|
76 |
flush_rewrite_rules(); // Refresh rewrite rules
|
77 |
-
|
78 |
-
add_settings_error( 'general', 'pll_languages_created', __( 'Language added.', 'polylang' ), 'updated' );
|
79 |
return true;
|
80 |
}
|
81 |
|
@@ -90,7 +88,7 @@ class PLL_Admin_Model extends PLL_Model {
|
|
90 |
$lang = $this->get_language( (int) $lang_id );
|
91 |
|
92 |
if ( empty( $lang ) ) {
|
93 |
-
return;
|
94 |
}
|
95 |
|
96 |
// Oops ! we are deleting the default language...
|
@@ -157,7 +155,7 @@ class PLL_Admin_Model extends PLL_Model {
|
|
157 |
|
158 |
update_option( 'polylang', $this->options );
|
159 |
flush_rewrite_rules(); // refresh rewrite rules
|
160 |
-
|
161 |
}
|
162 |
|
163 |
/**
|
@@ -181,8 +179,10 @@ class PLL_Admin_Model extends PLL_Model {
|
|
181 |
*/
|
182 |
public function update_language( $args ) {
|
183 |
$lang = $this->get_language( (int) $args['lang_id'] );
|
184 |
-
|
185 |
-
|
|
|
|
|
186 |
}
|
187 |
|
188 |
// Update links to this language in posts and terms in case the slug has been modified
|
@@ -235,7 +235,7 @@ class PLL_Admin_Model extends PLL_Model {
|
|
235 |
update_option( 'polylang', $this->options );
|
236 |
|
237 |
// And finally update the language itself
|
238 |
-
$description =
|
239 |
wp_update_term( (int) $lang->term_id, 'language', array( 'slug' => $slug, 'name' => $args['name'], 'description' => $description, 'term_group' => (int) $args['term_group'] ) );
|
240 |
wp_update_term( (int) $lang->tl_term_id, 'term_language', array( 'slug' => 'pll_' . $slug, 'name' => $args['name'] ) );
|
241 |
|
@@ -250,7 +250,6 @@ class PLL_Admin_Model extends PLL_Model {
|
|
250 |
|
251 |
$this->clean_languages_cache();
|
252 |
flush_rewrite_rules(); // Refresh rewrite rules
|
253 |
-
add_settings_error( 'general', 'pll_languages_updated', __( 'Language updated.', 'polylang' ), 'updated' );
|
254 |
return true;
|
255 |
}
|
256 |
|
@@ -266,35 +265,45 @@ class PLL_Admin_Model extends PLL_Model {
|
|
266 |
* @return bool true if success / false if failed
|
267 |
*/
|
268 |
protected function validate_lang( $args, $lang = null ) {
|
|
|
|
|
269 |
// Validate locale with the same pattern as WP 4.3. See #28303
|
270 |
if ( ! preg_match( '#^[a-z]{2,3}(?:_[A-Z]{2})?(?:_[a-z0-9]+)?$#', $args['locale'], $matches ) ) {
|
271 |
-
|
272 |
}
|
273 |
|
274 |
// Validate slug characters
|
275 |
if ( ! preg_match( '#^[a-z_-]+$#', $args['slug'] ) ) {
|
276 |
-
|
277 |
}
|
278 |
|
279 |
// Validate slug is unique
|
280 |
foreach ( $this->get_languages_list() as $language ) {
|
281 |
if ( $language->slug === $args['slug'] && ( null === $lang || ( isset( $lang ) && $lang->term_id != $language->term_id ) ) ) {
|
282 |
-
|
283 |
}
|
284 |
}
|
285 |
|
286 |
// Validate name
|
287 |
// No need to sanitize it as wp_insert_term will do it for us
|
288 |
if ( empty( $args['name'] ) ) {
|
289 |
-
|
290 |
}
|
291 |
|
292 |
// Validate flag
|
293 |
if ( ! empty( $args['flag'] ) && ! file_exists( POLYLANG_DIR . '/flags/' . $args['flag'] . '.png' ) ) {
|
294 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
295 |
}
|
296 |
|
297 |
-
return
|
298 |
}
|
299 |
|
300 |
/**
|
@@ -355,7 +364,7 @@ class PLL_Admin_Model extends PLL_Model {
|
|
355 |
$term = uniqid( 'pll_' ); // the term name
|
356 |
$terms[] = $wpdb->prepare( '( %s, %s )', $term, $term );
|
357 |
$slugs[] = $wpdb->prepare( '%s', $term );
|
358 |
-
$description[ $term ] =
|
359 |
$count[ $term ] = count( $t );
|
360 |
}
|
361 |
|
@@ -386,7 +395,7 @@ class PLL_Admin_Model extends PLL_Model {
|
|
386 |
|
387 |
// Prepare objects relationships
|
388 |
foreach ( $terms as $term ) {
|
389 |
-
$t =
|
390 |
if ( in_array( $t, $translations ) ) {
|
391 |
foreach ( $t as $object_id ) {
|
392 |
if ( ! empty( $object_id ) ) {
|
@@ -446,7 +455,7 @@ class PLL_Admin_Model extends PLL_Model {
|
|
446 |
)
|
447 |
);
|
448 |
|
449 |
-
// PHPCS:disable WordPress.DB.PreparedSQL
|
450 |
$terms = $wpdb->get_col(
|
451 |
sprintf(
|
452 |
"SELECT {$wpdb->term_taxonomy}.term_id FROM {$wpdb->term_taxonomy}
|
@@ -487,7 +496,7 @@ class PLL_Admin_Model extends PLL_Model {
|
|
487 |
|
488 |
foreach ( $terms as $term ) {
|
489 |
$term_ids[ $term->taxonomy ][] = $term->term_id;
|
490 |
-
$tr =
|
491 |
if ( ! empty( $tr[ $old_slug ] ) ) {
|
492 |
if ( $new_slug ) {
|
493 |
$tr[ $new_slug ] = $tr[ $old_slug ]; // Suppress this for delete
|
@@ -501,7 +510,7 @@ class PLL_Admin_Model extends PLL_Model {
|
|
501 |
$dt['t'][] = (int) $term->term_id;
|
502 |
$dt['tt'][] = (int) $term->term_taxonomy_id;
|
503 |
} else {
|
504 |
-
$ut['case'][] = $wpdb->prepare( 'WHEN %d THEN %s', $term->term_id,
|
505 |
$ut['in'][] = (int) $term->term_id;
|
506 |
}
|
507 |
}
|
28 |
* @return bool true if success / false if failed
|
29 |
*/
|
30 |
public function add_language( $args ) {
|
31 |
+
$errors = $this->validate_lang( $args );
|
32 |
+
if ( $errors->get_error_code() ) { // Using has_errors() would be more meaningful but is available only since WP 5.0
|
33 |
+
return $errors;
|
34 |
}
|
35 |
|
36 |
// First the language taxonomy
|
37 |
+
$description = maybe_serialize( array( 'locale' => $args['locale'], 'rtl' => (int) $args['rtl'], 'flag_code' => empty( $args['flag'] ) ? '' : $args['flag'] ) );
|
38 |
$r = wp_insert_term( $args['name'], 'language', array( 'slug' => $args['slug'], 'description' => $description ) );
|
39 |
if ( is_wp_error( $r ) ) {
|
40 |
// Avoid an ugly fatal error if something went wrong ( reported once in the forum )
|
41 |
+
return new WP_Error( 'pll_add_language', __( 'Impossible to add the language.', 'polylang' ) );
|
|
|
42 |
}
|
43 |
wp_update_term( (int) $r['term_id'], 'language', array( 'term_group' => (int) $args['term_group'] ) ); // can't set the term group directly in wp_insert_term
|
44 |
|
74 |
|
75 |
$this->clean_languages_cache(); // Again to set add mo_id in the cached languages list
|
76 |
flush_rewrite_rules(); // Refresh rewrite rules
|
|
|
|
|
77 |
return true;
|
78 |
}
|
79 |
|
88 |
$lang = $this->get_language( (int) $lang_id );
|
89 |
|
90 |
if ( empty( $lang ) ) {
|
91 |
+
return false;
|
92 |
}
|
93 |
|
94 |
// Oops ! we are deleting the default language...
|
155 |
|
156 |
update_option( 'polylang', $this->options );
|
157 |
flush_rewrite_rules(); // refresh rewrite rules
|
158 |
+
return true;
|
159 |
}
|
160 |
|
161 |
/**
|
179 |
*/
|
180 |
public function update_language( $args ) {
|
181 |
$lang = $this->get_language( (int) $args['lang_id'] );
|
182 |
+
|
183 |
+
$errors = $this->validate_lang( $args, $lang );
|
184 |
+
if ( $errors->get_error_code() ) { // Using has_errors() would be more meaningful but is available only since WP 5.0
|
185 |
+
return $errors;
|
186 |
}
|
187 |
|
188 |
// Update links to this language in posts and terms in case the slug has been modified
|
235 |
update_option( 'polylang', $this->options );
|
236 |
|
237 |
// And finally update the language itself
|
238 |
+
$description = maybe_serialize( array( 'locale' => $args['locale'], 'rtl' => (int) $args['rtl'], 'flag_code' => empty( $args['flag'] ) ? '' : $args['flag'] ) );
|
239 |
wp_update_term( (int) $lang->term_id, 'language', array( 'slug' => $slug, 'name' => $args['name'], 'description' => $description, 'term_group' => (int) $args['term_group'] ) );
|
240 |
wp_update_term( (int) $lang->tl_term_id, 'term_language', array( 'slug' => 'pll_' . $slug, 'name' => $args['name'] ) );
|
241 |
|
250 |
|
251 |
$this->clean_languages_cache();
|
252 |
flush_rewrite_rules(); // Refresh rewrite rules
|
|
|
253 |
return true;
|
254 |
}
|
255 |
|
265 |
* @return bool true if success / false if failed
|
266 |
*/
|
267 |
protected function validate_lang( $args, $lang = null ) {
|
268 |
+
$errors = new WP_Error();
|
269 |
+
|
270 |
// Validate locale with the same pattern as WP 4.3. See #28303
|
271 |
if ( ! preg_match( '#^[a-z]{2,3}(?:_[A-Z]{2})?(?:_[a-z0-9]+)?$#', $args['locale'], $matches ) ) {
|
272 |
+
$errors->add( 'pll_invalid_locale', __( 'Enter a valid WordPress locale', 'polylang' ) );
|
273 |
}
|
274 |
|
275 |
// Validate slug characters
|
276 |
if ( ! preg_match( '#^[a-z_-]+$#', $args['slug'] ) ) {
|
277 |
+
$errors->add( 'pll_invalid_slug', __( 'The language code contains invalid characters', 'polylang' ) );
|
278 |
}
|
279 |
|
280 |
// Validate slug is unique
|
281 |
foreach ( $this->get_languages_list() as $language ) {
|
282 |
if ( $language->slug === $args['slug'] && ( null === $lang || ( isset( $lang ) && $lang->term_id != $language->term_id ) ) ) {
|
283 |
+
$errors->add( 'pll_non_unique_slug', __( 'The language code must be unique', 'polylang' ) );
|
284 |
}
|
285 |
}
|
286 |
|
287 |
// Validate name
|
288 |
// No need to sanitize it as wp_insert_term will do it for us
|
289 |
if ( empty( $args['name'] ) ) {
|
290 |
+
$errors->add( 'pll_invalid_name', __( 'The language must have a name', 'polylang' ) );
|
291 |
}
|
292 |
|
293 |
// Validate flag
|
294 |
if ( ! empty( $args['flag'] ) && ! file_exists( POLYLANG_DIR . '/flags/' . $args['flag'] . '.png' ) ) {
|
295 |
+
$flag = PLL_Language::get_flag_informations( $args['flag'] );
|
296 |
+
|
297 |
+
if ( ! empty( $flag['url'] ) ) {
|
298 |
+
$response = function_exists( 'vip_safe_wp_remote_get' ) ? vip_safe_wp_remote_get( esc_url_raw( $flag['url'] ) ) : wp_remote_get( esc_url_raw( $flag['url'] ) );
|
299 |
+
}
|
300 |
+
|
301 |
+
if ( empty( $response ) || is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
|
302 |
+
$errors->add( 'pll_invalid_flag', __( 'The flag does not exist', 'polylang' ) );
|
303 |
+
}
|
304 |
}
|
305 |
|
306 |
+
return $errors;
|
307 |
}
|
308 |
|
309 |
/**
|
364 |
$term = uniqid( 'pll_' ); // the term name
|
365 |
$terms[] = $wpdb->prepare( '( %s, %s )', $term, $term );
|
366 |
$slugs[] = $wpdb->prepare( '%s', $term );
|
367 |
+
$description[ $term ] = maybe_serialize( $t );
|
368 |
$count[ $term ] = count( $t );
|
369 |
}
|
370 |
|
395 |
|
396 |
// Prepare objects relationships
|
397 |
foreach ( $terms as $term ) {
|
398 |
+
$t = maybe_unserialize( $term->description );
|
399 |
if ( in_array( $t, $translations ) ) {
|
400 |
foreach ( $t as $object_id ) {
|
401 |
if ( ! empty( $object_id ) ) {
|
455 |
)
|
456 |
);
|
457 |
|
458 |
+
// PHPCS:disable WordPress.DB.PreparedSQL
|
459 |
$terms = $wpdb->get_col(
|
460 |
sprintf(
|
461 |
"SELECT {$wpdb->term_taxonomy}.term_id FROM {$wpdb->term_taxonomy}
|
496 |
|
497 |
foreach ( $terms as $term ) {
|
498 |
$term_ids[ $term->taxonomy ][] = $term->term_id;
|
499 |
+
$tr = maybe_unserialize( $term->description );
|
500 |
if ( ! empty( $tr[ $old_slug ] ) ) {
|
501 |
if ( $new_slug ) {
|
502 |
$tr[ $new_slug ] = $tr[ $old_slug ]; // Suppress this for delete
|
510 |
$dt['t'][] = (int) $term->term_id;
|
511 |
$dt['tt'][] = (int) $term->term_taxonomy_id;
|
512 |
} else {
|
513 |
+
$ut['case'][] = $wpdb->prepare( 'WHEN %d THEN %s', $term->term_id, maybe_serialize( $tr ) );
|
514 |
$ut['in'][] = (int) $term->term_id;
|
515 |
}
|
516 |
}
|
admin/admin-nav-menu.php
CHANGED
@@ -17,8 +17,6 @@ class PLL_Admin_Nav_Menu extends PLL_Nav_Menu {
|
|
17 |
public function __construct( &$polylang ) {
|
18 |
parent::__construct( $polylang );
|
19 |
|
20 |
-
$this->theme = get_option( 'stylesheet' );
|
21 |
-
|
22 |
// Populates nav menus locations
|
23 |
// Since WP 4.4, must be done before customize_register is fired
|
24 |
add_filter( 'theme_mod_nav_menu_locations', array( $this, 'theme_mod_nav_menu_locations' ), 20 );
|
@@ -36,15 +34,11 @@ class PLL_Admin_Nav_Menu extends PLL_Nav_Menu {
|
|
36 |
public function admin_init() {
|
37 |
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
|
38 |
add_action( 'wp_update_nav_menu_item', array( $this, 'wp_update_nav_menu_item' ), 10, 2 );
|
39 |
-
add_filter( 'wp_get_nav_menu_items', array( $this, 'translate_switcher_title' ) );
|
40 |
|
41 |
// Translation of menus based on chosen locations
|
42 |
add_filter( 'pre_update_option_theme_mods_' . $this->theme, array( $this, 'pre_update_option_theme_mods' ) );
|
43 |
add_action( 'delete_nav_menu', array( $this, 'delete_nav_menu' ) );
|
44 |
|
45 |
-
// Filter _wp_auto_add_pages_to_menu by language
|
46 |
-
add_action( 'transition_post_status', array( $this, 'auto_add_pages_to_menu' ), 5, 3 ); // before _wp_auto_add_pages_to_menu
|
47 |
-
|
48 |
// FIXME is it possible to choose the order ( after theme locations in WP3.5 and older ) ?
|
49 |
// FIXME not displayed if Polylang is activated before the first time the user goes to nav menus http://core.trac.wordpress.org/ticket/16828
|
50 |
add_meta_box( 'pll_lang_switch_box', __( 'Language switcher', 'polylang' ), array( $this, 'lang_switch' ), 'nav-menus', 'side', 'high' );
|
@@ -68,17 +62,17 @@ class PLL_Admin_Nav_Menu extends PLL_Nav_Menu {
|
|
68 |
<ul id="lang-switch-checklist" class="categorychecklist form-no-clear">
|
69 |
<li>
|
70 |
<label class="menu-item-title">
|
71 |
-
<input type="checkbox" class="menu-item-checkbox" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-object-id]" value="-1"> <?php esc_html_e( '
|
72 |
</label>
|
73 |
-
<input type="hidden" class="menu-item-type" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-type]" value="custom">
|
74 |
-
<input type="hidden" class="menu-item-title" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-title]" value="<?php esc_html_e( '
|
75 |
-
<input type="hidden" class="menu-item-url" name="menu-item[<?php echo $_nav_menu_placeholder; ?>][menu-item-url]" value="#pll_switcher">
|
76 |
</li>
|
77 |
</ul>
|
78 |
</div>
|
79 |
<p class="button-controls">
|
80 |
<span class="add-to-menu">
|
81 |
-
<input type="submit" <?php disabled( $nav_menu_selected_id, 0 ); ?> class="button-secondary submit-add-to-menu right" value="<?php esc_attr_e( 'Add to Menu' ); ?>" name="add-post-type-menu-item" id="submit-posttype-lang-switch">
|
82 |
<span class="spinner"></span>
|
83 |
</span>
|
84 |
</p>
|
@@ -101,7 +95,7 @@ class PLL_Admin_Nav_Menu extends PLL_Nav_Menu {
|
|
101 |
wp_enqueue_script( 'pll_nav_menu', plugins_url( '/js/nav-menu' . $suffix . '.js', POLYLANG_FILE ), array( 'jquery' ), POLYLANG_VERSION );
|
102 |
|
103 |
$data['strings'] = PLL_Switcher::get_switcher_options( 'menu', 'string' ); // The strings for the options
|
104 |
-
$data['title'] = __( '
|
105 |
|
106 |
// Get all language switcher menu items
|
107 |
$items = get_posts(
|
@@ -133,7 +127,7 @@ class PLL_Admin_Nav_Menu extends PLL_Nav_Menu {
|
|
133 |
* @param int $menu_item_db_id
|
134 |
*/
|
135 |
public function wp_update_nav_menu_item( $menu_id = 0, $menu_item_db_id = 0 ) {
|
136 |
-
if ( empty( $_POST['menu-item-url'][ $menu_item_db_id ] ) || '#pll_switcher'
|
137 |
return;
|
138 |
}
|
139 |
|
@@ -157,23 +151,6 @@ class PLL_Admin_Nav_Menu extends PLL_Nav_Menu {
|
|
157 |
}
|
158 |
}
|
159 |
|
160 |
-
/**
|
161 |
-
* Translates the language switcher menu items title in case the user switches the admin language
|
162 |
-
*
|
163 |
-
* @since 1.1.1
|
164 |
-
*
|
165 |
-
* @param array $items
|
166 |
-
* @return array modified $items
|
167 |
-
*/
|
168 |
-
public function translate_switcher_title( $items ) {
|
169 |
-
foreach ( $items as $item ) {
|
170 |
-
if ( '#pll_switcher' == $item->url ) {
|
171 |
-
$item->post_title = __( 'Language switcher', 'polylang' );
|
172 |
-
}
|
173 |
-
}
|
174 |
-
return $items;
|
175 |
-
}
|
176 |
-
|
177 |
/**
|
178 |
* Assign menu languages and translations based on ( temporary ) locations
|
179 |
*
|
@@ -210,14 +187,14 @@ class PLL_Admin_Nav_Menu extends PLL_Nav_Menu {
|
|
210 |
if ( current_user_can( 'edit_theme_options' ) && isset( $mods['nav_menu_locations'] ) ) {
|
211 |
|
212 |
// Manage Locations tab in Appearance -> Menus
|
213 |
-
if ( isset( $_GET['action'] ) && 'locations'
|
214 |
check_admin_referer( 'save-menu-locations' );
|
215 |
$this->options['nav_menus'][ $this->theme ] = array();
|
216 |
}
|
217 |
|
218 |
// Edit Menus tab in Appearance -> Menus
|
219 |
// Add the test of $_POST['update-nav-menu-nonce'] to avoid conflict with Vantage theme
|
220 |
-
elseif ( isset( $_POST['action'], $_POST['update-nav-menu-nonce'] ) && 'update'
|
221 |
check_admin_referer( 'update-nav_menu', 'update-nav-menu-nonce' );
|
222 |
$this->options['nav_menus'][ $this->theme ] = array();
|
223 |
}
|
@@ -289,48 +266,4 @@ class PLL_Admin_Nav_Menu extends PLL_Nav_Menu {
|
|
289 |
update_option( 'polylang', $this->options );
|
290 |
}
|
291 |
}
|
292 |
-
|
293 |
-
/**
|
294 |
-
* Filters the option nav_menu_options for auto added pages to menu
|
295 |
-
*
|
296 |
-
* @since 0.9.4
|
297 |
-
*
|
298 |
-
* @param array $options
|
299 |
-
* @return array Modified options
|
300 |
-
*/
|
301 |
-
public function nav_menu_options( $options ) {
|
302 |
-
$options['auto_add'] = array_intersect( $options['auto_add'], $this->auto_add_menus );
|
303 |
-
return $options;
|
304 |
-
}
|
305 |
-
|
306 |
-
/**
|
307 |
-
* Filters _wp_auto_add_pages_to_menu by language
|
308 |
-
*
|
309 |
-
* @since 0.9.4
|
310 |
-
*
|
311 |
-
* @param string $new_status Transition to this post status.
|
312 |
-
* @param string $old_status Previous post status.
|
313 |
-
* @param object $post Post data.
|
314 |
-
*/
|
315 |
-
public function auto_add_pages_to_menu( $new_status, $old_status, $post ) {
|
316 |
-
if ( 'publish' != $new_status || 'publish' == $old_status || 'page' != $post->post_type || ! empty( $post->post_parent ) ) {
|
317 |
-
return;
|
318 |
-
}
|
319 |
-
|
320 |
-
if ( ! empty( $this->options['nav_menus'][ $this->theme ] ) ) {
|
321 |
-
$this->auto_add_menus = array();
|
322 |
-
|
323 |
-
$lang = $this->model->post->get_language( $post->ID );
|
324 |
-
$lang = empty( $lang ) ? $this->options['default_lang'] : $lang->slug; // If the page has no language yet, the default language will be assigned
|
325 |
-
|
326 |
-
// Get all the menus in the page language
|
327 |
-
foreach ( $this->options['nav_menus'][ $this->theme ] as $loc ) {
|
328 |
-
if ( ! empty( $loc[ $lang ] ) ) {
|
329 |
-
$this->auto_add_menus[] = $loc[ $lang ];
|
330 |
-
}
|
331 |
-
}
|
332 |
-
|
333 |
-
add_filter( 'option_nav_menu_options', array( $this, 'nav_menu_options' ) );
|
334 |
-
}
|
335 |
-
}
|
336 |
}
|
17 |
public function __construct( &$polylang ) {
|
18 |
parent::__construct( $polylang );
|
19 |
|
|
|
|
|
20 |
// Populates nav menus locations
|
21 |
// Since WP 4.4, must be done before customize_register is fired
|
22 |
add_filter( 'theme_mod_nav_menu_locations', array( $this, 'theme_mod_nav_menu_locations' ), 20 );
|
34 |
public function admin_init() {
|
35 |
add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
|
36 |
add_action( 'wp_update_nav_menu_item', array( $this, 'wp_update_nav_menu_item' ), 10, 2 );
|
|
|
37 |
|
38 |
// Translation of menus based on chosen locations
|
39 |
add_filter( 'pre_update_option_theme_mods_' . $this->theme, array( $this, 'pre_update_option_theme_mods' ) );
|
40 |
add_action( 'delete_nav_menu', array( $this, 'delete_nav_menu' ) );
|
41 |
|
|
|
|
|
|
|
42 |
// FIXME is it possible to choose the order ( after theme locations in WP3.5 and older ) ?
|
43 |
// FIXME not displayed if Polylang is activated before the first time the user goes to nav menus http://core.trac.wordpress.org/ticket/16828
|
44 |
add_meta_box( 'pll_lang_switch_box', __( 'Language switcher', 'polylang' ), array( $this, 'lang_switch' ), 'nav-menus', 'side', 'high' );
|
62 |
<ul id="lang-switch-checklist" class="categorychecklist form-no-clear">
|
63 |
<li>
|
64 |
<label class="menu-item-title">
|
65 |
+
<input type="checkbox" class="menu-item-checkbox" name="menu-item[<?php echo (int) $_nav_menu_placeholder; ?>][menu-item-object-id]" value="-1"> <?php esc_html_e( 'Languages', 'polylang' ); ?>
|
66 |
</label>
|
67 |
+
<input type="hidden" class="menu-item-type" name="menu-item[<?php echo (int) $_nav_menu_placeholder; ?>][menu-item-type]" value="custom">
|
68 |
+
<input type="hidden" class="menu-item-title" name="menu-item[<?php echo (int) $_nav_menu_placeholder; ?>][menu-item-title]" value="<?php esc_html_e( 'Languages', 'polylang' ); ?>">
|
69 |
+
<input type="hidden" class="menu-item-url" name="menu-item[<?php echo (int) $_nav_menu_placeholder; ?>][menu-item-url]" value="#pll_switcher">
|
70 |
</li>
|
71 |
</ul>
|
72 |
</div>
|
73 |
<p class="button-controls">
|
74 |
<span class="add-to-menu">
|
75 |
+
<input type="submit" <?php disabled( $nav_menu_selected_id, 0 ); ?> class="button-secondary submit-add-to-menu right" value="<?php esc_attr_e( 'Add to Menu', 'polylang' ); ?>" name="add-post-type-menu-item" id="submit-posttype-lang-switch">
|
76 |
<span class="spinner"></span>
|
77 |
</span>
|
78 |
</p>
|
95 |
wp_enqueue_script( 'pll_nav_menu', plugins_url( '/js/nav-menu' . $suffix . '.js', POLYLANG_FILE ), array( 'jquery' ), POLYLANG_VERSION );
|
96 |
|
97 |
$data['strings'] = PLL_Switcher::get_switcher_options( 'menu', 'string' ); // The strings for the options
|
98 |
+
$data['title'] = __( 'Languages', 'polylang' ); // The title
|
99 |
|
100 |
// Get all language switcher menu items
|
101 |
$items = get_posts(
|
127 |
* @param int $menu_item_db_id
|
128 |
*/
|
129 |
public function wp_update_nav_menu_item( $menu_id = 0, $menu_item_db_id = 0 ) {
|
130 |
+
if ( empty( $_POST['menu-item-url'][ $menu_item_db_id ] ) || '#pll_switcher' !== $_POST['menu-item-url'][ $menu_item_db_id ] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
131 |
return;
|
132 |
}
|
133 |
|
151 |
}
|
152 |
}
|
153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
/**
|
155 |
* Assign menu languages and translations based on ( temporary ) locations
|
156 |
*
|
187 |
if ( current_user_can( 'edit_theme_options' ) && isset( $mods['nav_menu_locations'] ) ) {
|
188 |
|
189 |
// Manage Locations tab in Appearance -> Menus
|
190 |
+
if ( isset( $_GET['action'] ) && 'locations' === $_GET['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
191 |
check_admin_referer( 'save-menu-locations' );
|
192 |
$this->options['nav_menus'][ $this->theme ] = array();
|
193 |
}
|
194 |
|
195 |
// Edit Menus tab in Appearance -> Menus
|
196 |
// Add the test of $_POST['update-nav-menu-nonce'] to avoid conflict with Vantage theme
|
197 |
+
elseif ( isset( $_POST['action'], $_POST['update-nav-menu-nonce'] ) && 'update' === $_POST['action'] ) {
|
198 |
check_admin_referer( 'update-nav_menu', 'update-nav-menu-nonce' );
|
199 |
$this->options['nav_menus'][ $this->theme ] = array();
|
200 |
}
|
266 |
update_option( 'polylang', $this->options );
|
267 |
}
|
268 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
269 |
}
|
admin/admin-notices.php
CHANGED
@@ -8,7 +8,7 @@
|
|
8 |
* @since 2.3.9
|
9 |
*/
|
10 |
class PLL_Admin_Notices {
|
11 |
-
static
|
12 |
|
13 |
/**
|
14 |
* Constructor
|
@@ -155,7 +155,8 @@ class PLL_Admin_Notices {
|
|
155 |
printf(
|
156 |
'<a class="notice-dismiss" href="%s"><span class="screen-reader-text">%s</span></a>',
|
157 |
esc_url( wp_nonce_url( add_query_arg( 'pll-hide-notice', $name ), $name, '_pll_notice_nonce' ) ),
|
158 |
-
|
|
|
159 |
);
|
160 |
}
|
161 |
|
@@ -173,7 +174,7 @@ class PLL_Admin_Notices {
|
|
173 |
<?php
|
174 |
printf(
|
175 |
/* translators: %1$s is link start tag, %2$s is link end tag. */
|
176 |
-
esc_html__( 'We have noticed that you are using Polylang with WooCommerce.
|
177 |
'<a href="https://polylang.pro/downloads/polylang-for-woocommerce/">',
|
178 |
'</a>'
|
179 |
);
|
@@ -198,7 +199,7 @@ class PLL_Admin_Notices {
|
|
198 |
<?php
|
199 |
printf(
|
200 |
/* translators: %1$s is link start tag, %2$s is link end tag. */
|
201 |
-
esc_html__( 'We have noticed that you
|
202 |
'<a href="https://wordpress.org/support/plugin/polylang/reviews/?rate=5#new-post">',
|
203 |
'</a>'
|
204 |
);
|
8 |
* @since 2.3.9
|
9 |
*/
|
10 |
class PLL_Admin_Notices {
|
11 |
+
private static $notices = array();
|
12 |
|
13 |
/**
|
14 |
* Constructor
|
155 |
printf(
|
156 |
'<a class="notice-dismiss" href="%s"><span class="screen-reader-text">%s</span></a>',
|
157 |
esc_url( wp_nonce_url( add_query_arg( 'pll-hide-notice', $name ), $name, '_pll_notice_nonce' ) ),
|
158 |
+
/* translators: accessibility text */
|
159 |
+
esc_html__( 'Dismiss this notice.', 'polylang' )
|
160 |
);
|
161 |
}
|
162 |
|
174 |
<?php
|
175 |
printf(
|
176 |
/* translators: %1$s is link start tag, %2$s is link end tag. */
|
177 |
+
esc_html__( 'We have noticed that you are using Polylang with WooCommerce. To ensure compatibility, we recommend you use %1$sPolylang for WooCommerce%2$s.', 'polylang' ),
|
178 |
'<a href="https://polylang.pro/downloads/polylang-for-woocommerce/">',
|
179 |
'</a>'
|
180 |
);
|
199 |
<?php
|
200 |
printf(
|
201 |
/* translators: %1$s is link start tag, %2$s is link end tag. */
|
202 |
+
esc_html__( 'We have noticed that you have been using Polylang for some time. We hope you love it, and we would really appreciate it if you would %1$sgive us a 5 stars rating%2$s.', 'polylang' ),
|
203 |
'<a href="https://wordpress.org/support/plugin/polylang/reviews/?rate=5#new-post">',
|
204 |
'</a>'
|
205 |
);
|
admin/admin-static-pages.php
CHANGED
@@ -6,6 +6,7 @@
|
|
6 |
* @since 1.8
|
7 |
*/
|
8 |
class PLL_Admin_Static_Pages extends PLL_Static_Pages {
|
|
|
9 |
|
10 |
/**
|
11 |
* Constructor: setups filters and actions
|
@@ -17,6 +18,8 @@ class PLL_Admin_Static_Pages extends PLL_Static_Pages {
|
|
17 |
public function __construct( &$polylang ) {
|
18 |
parent::__construct( $polylang );
|
19 |
|
|
|
|
|
20 |
// Removes the editor and the template select dropdown for pages for posts
|
21 |
add_filter( 'use_block_editor_for_post', array( $this, 'use_block_editor_for_post' ), 10, 2 ); // Since WP 5.0
|
22 |
add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 10, 2 );
|
@@ -33,6 +36,8 @@ class PLL_Admin_Static_Pages extends PLL_Static_Pages {
|
|
33 |
|
34 |
// Prevents WP resetting the option
|
35 |
add_filter( 'pre_update_option_show_on_front', array( $this, 'update_show_on_front' ), 10, 2 );
|
|
|
|
|
36 |
}
|
37 |
|
38 |
/**
|
@@ -87,11 +92,11 @@ class PLL_Admin_Static_Pages extends PLL_Static_Pages {
|
|
87 |
*/
|
88 |
public function display_post_states( $post_states, $post ) {
|
89 |
if ( in_array( $post->ID, $this->model->get_languages_list( array( 'fields' => 'page_on_front' ) ) ) ) {
|
90 |
-
$post_states['page_on_front'] = __( 'Front Page' );
|
91 |
}
|
92 |
|
93 |
if ( in_array( $post->ID, $this->model->get_languages_list( array( 'fields' => 'page_for_posts' ) ) ) ) {
|
94 |
-
$post_states['page_for_posts'] = __( 'Posts Page' );
|
95 |
}
|
96 |
|
97 |
return $post_states;
|
@@ -184,4 +189,40 @@ class PLL_Admin_Static_Pages extends PLL_Static_Pages {
|
|
184 |
}
|
185 |
return $value;
|
186 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
}
|
6 |
* @since 1.8
|
7 |
*/
|
8 |
class PLL_Admin_Static_Pages extends PLL_Static_Pages {
|
9 |
+
protected $links;
|
10 |
|
11 |
/**
|
12 |
* Constructor: setups filters and actions
|
18 |
public function __construct( &$polylang ) {
|
19 |
parent::__construct( $polylang );
|
20 |
|
21 |
+
$this->links = &$polylang->links;
|
22 |
+
|
23 |
// Removes the editor and the template select dropdown for pages for posts
|
24 |
add_filter( 'use_block_editor_for_post', array( $this, 'use_block_editor_for_post' ), 10, 2 ); // Since WP 5.0
|
25 |
add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 10, 2 );
|
36 |
|
37 |
// Prevents WP resetting the option
|
38 |
add_filter( 'pre_update_option_show_on_front', array( $this, 'update_show_on_front' ), 10, 2 );
|
39 |
+
|
40 |
+
add_action( 'admin_notices', array( $this, 'notice_must_translate' ) );
|
41 |
}
|
42 |
|
43 |
/**
|
92 |
*/
|
93 |
public function display_post_states( $post_states, $post ) {
|
94 |
if ( in_array( $post->ID, $this->model->get_languages_list( array( 'fields' => 'page_on_front' ) ) ) ) {
|
95 |
+
$post_states['page_on_front'] = __( 'Front Page', 'polylang' );
|
96 |
}
|
97 |
|
98 |
if ( in_array( $post->ID, $this->model->get_languages_list( array( 'fields' => 'page_for_posts' ) ) ) ) {
|
99 |
+
$post_states['page_for_posts'] = __( 'Posts Page', 'polylang' );
|
100 |
}
|
101 |
|
102 |
return $post_states;
|
189 |
}
|
190 |
return $value;
|
191 |
}
|
192 |
+
|
193 |
+
/**
|
194 |
+
* Add a notice to translate the static front page if it is not translated in all languages
|
195 |
+
* This is especially useful after a new language is created.
|
196 |
+
* The notice is not dismissible and displayed on the Languages pages and the list of pages.
|
197 |
+
*
|
198 |
+
* @since 2.6
|
199 |
+
*/
|
200 |
+
public function notice_must_translate() {
|
201 |
+
$screen = get_current_screen();
|
202 |
+
|
203 |
+
if ( $this->page_on_front && ( 'toplevel_page_mlang' === $screen->id || 'edit-page' === $screen->id ) ) {
|
204 |
+
$untranslated = array();
|
205 |
+
|
206 |
+
foreach ( $this->model->get_languages_list() as $language ) {
|
207 |
+
if ( ! $this->model->post->get( $this->page_on_front, $language ) ) {
|
208 |
+
$untranslated[] = sprintf(
|
209 |
+
'<a href="%s">%s</a>',
|
210 |
+
esc_url( $this->links->get_new_post_translation_link( $this->page_on_front, $language ) ),
|
211 |
+
esc_html( $language->name )
|
212 |
+
);
|
213 |
+
}
|
214 |
+
}
|
215 |
+
|
216 |
+
if ( ! empty( $untranslated ) ) {
|
217 |
+
printf(
|
218 |
+
'<div class="error"><p>%s</p></div>',
|
219 |
+
sprintf(
|
220 |
+
/* translators: %s is a comma separated list of native language names */
|
221 |
+
esc_html__( 'You must translate your static front page in %s.', 'polylang' ),
|
222 |
+
implode( ', ', $untranslated ) // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
223 |
+
)
|
224 |
+
);
|
225 |
+
}
|
226 |
+
}
|
227 |
+
}
|
228 |
}
|
admin/admin-strings.php
CHANGED
@@ -6,8 +6,8 @@
|
|
6 |
* @since 1.6
|
7 |
*/
|
8 |
class PLL_Admin_Strings {
|
9 |
-
static
|
10 |
-
static
|
11 |
|
12 |
/**
|
13 |
* Add filters
|
@@ -51,10 +51,10 @@ class PLL_Admin_Strings {
|
|
51 |
public static function &get_strings() {
|
52 |
self::$default_strings = array(
|
53 |
'options' => array(
|
54 |
-
'blogname' => __( 'Site Title' ),
|
55 |
-
'blogdescription' => __( 'Tagline' ),
|
56 |
-
'date_format' => __( 'Date Format' ),
|
57 |
-
'time_format' => __( 'Time Format' ),
|
58 |
),
|
59 |
'widget_title' => __( 'Widget title', 'polylang' ),
|
60 |
'widget_text' => __( 'Widget text', 'polylang' ),
|
@@ -125,11 +125,11 @@ class PLL_Admin_Strings {
|
|
125 |
}
|
126 |
|
127 |
if ( $name == self::$default_strings['widget_title'] ) {
|
128 |
-
$translation =
|
129 |
}
|
130 |
|
131 |
if ( $name == self::$default_strings['widget_text'] && ! current_user_can( 'unfiltered_html' ) ) {
|
132 |
-
$translation =
|
133 |
}
|
134 |
|
135 |
return $translation;
|
6 |
* @since 1.6
|
7 |
*/
|
8 |
class PLL_Admin_Strings {
|
9 |
+
protected static $strings = array(); // strings to translate
|
10 |
+
protected static $default_strings; // default strings to register
|
11 |
|
12 |
/**
|
13 |
* Add filters
|
51 |
public static function &get_strings() {
|
52 |
self::$default_strings = array(
|
53 |
'options' => array(
|
54 |
+
'blogname' => __( 'Site Title', 'polylang' ),
|
55 |
+
'blogdescription' => __( 'Tagline', 'polylang' ),
|
56 |
+
'date_format' => __( 'Date Format', 'polylang' ),
|
57 |
+
'time_format' => __( 'Time Format', 'polylang' ),
|
58 |
),
|
59 |
'widget_title' => __( 'Widget title', 'polylang' ),
|
60 |
'widget_text' => __( 'Widget text', 'polylang' ),
|
125 |
}
|
126 |
|
127 |
if ( $name == self::$default_strings['widget_title'] ) {
|
128 |
+
$translation = sanitize_text_field( $translation );
|
129 |
}
|
130 |
|
131 |
if ( $name == self::$default_strings['widget_text'] && ! current_user_can( 'unfiltered_html' ) ) {
|
132 |
+
$translation = wp_kses_post( $translation );
|
133 |
}
|
134 |
|
135 |
return $translation;
|
admin/admin.php
CHANGED
@@ -48,7 +48,7 @@ class PLL_Admin extends PLL_Admin_Base {
|
|
48 |
}
|
49 |
|
50 |
/**
|
51 |
-
*
|
52 |
* Loads the settings pages or the filters base on the request
|
53 |
*
|
54 |
* @since 1.2
|
@@ -60,6 +60,12 @@ class PLL_Admin extends PLL_Admin_Base {
|
|
60 |
// Priority 5 to make sure filters are there before customize_register is fired
|
61 |
if ( $this->model->get_languages_list() ) {
|
62 |
add_action( 'wp_loaded', array( $this, 'add_filters' ), 5 );
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
}
|
64 |
}
|
65 |
|
@@ -120,5 +126,68 @@ class PLL_Admin extends PLL_Admin_Base {
|
|
120 |
|
121 |
$this->posts = new PLL_CRUD_Posts( $this );
|
122 |
$this->terms = new PLL_CRUD_Terms( $this );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
123 |
}
|
124 |
}
|
48 |
}
|
49 |
|
50 |
/**
|
51 |
+
* Setups filters and action needed on all admin pages and on plugins page
|
52 |
* Loads the settings pages or the filters base on the request
|
53 |
*
|
54 |
* @since 1.2
|
60 |
// Priority 5 to make sure filters are there before customize_register is fired
|
61 |
if ( $this->model->get_languages_list() ) {
|
62 |
add_action( 'wp_loaded', array( $this, 'add_filters' ), 5 );
|
63 |
+
add_action( 'admin_init', array( $this, 'maybe_load_sync_post' ) );
|
64 |
+
|
65 |
+
// Bulk Translate
|
66 |
+
if ( class_exists( 'PLL_Bulk_Translate' ) ) {
|
67 |
+
add_action( 'current_screen', array( $this->bulk_translate = new PLL_Bulk_Translate( $this ), 'init' ) );
|
68 |
+
}
|
69 |
}
|
70 |
}
|
71 |
|
126 |
|
127 |
$this->posts = new PLL_CRUD_Posts( $this );
|
128 |
$this->terms = new PLL_CRUD_Terms( $this );
|
129 |
+
|
130 |
+
// Advanced media
|
131 |
+
if ( $this->options['media_support'] && class_exists( 'PLL_Admin_Advanced_Media' ) ) {
|
132 |
+
$this->advanced_media = new PLL_Admin_Advanced_Media( $this );
|
133 |
+
}
|
134 |
+
|
135 |
+
// Share term slugs
|
136 |
+
if ( get_option( 'permalink_structure' ) && $this->options['force_lang'] && class_exists( 'PLL_Admin_Share_Term_Slug' ) ) {
|
137 |
+
$this->share_term_slug = new PLL_Admin_Share_Term_Slug( $this );
|
138 |
+
}
|
139 |
+
|
140 |
+
if ( class_exists( 'PLL_Sync_Content' ) ) {
|
141 |
+
$this->sync_content = new PLL_Sync_Content( $this );
|
142 |
+
}
|
143 |
+
|
144 |
+
// Duplicate content
|
145 |
+
if ( class_exists( 'PLL_Duplicate' ) ) {
|
146 |
+
$this->duplicate = new PLL_Duplicate( $this );
|
147 |
+
}
|
148 |
+
|
149 |
+
if ( class_exists( 'PLL_Duplicate_REST' ) ) {
|
150 |
+
$this->duplicate_rest = new PLL_Duplicate_REST();
|
151 |
+
}
|
152 |
+
|
153 |
+
// Block editor metabox
|
154 |
+
if ( pll_use_block_editor_plugin() ) {
|
155 |
+
$this->block_editor_plugin = new PLL_Block_Editor_Plugin( $this );
|
156 |
+
}
|
157 |
+
}
|
158 |
+
|
159 |
+
/**
|
160 |
+
* Load the post synchronization object, depending on the editor in use.
|
161 |
+
*
|
162 |
+
* @since 2.6
|
163 |
+
*/
|
164 |
+
public function maybe_load_sync_post() {
|
165 |
+
// Post synchronization
|
166 |
+
if ( 'post-new.php' === $GLOBALS['pagenow'] && function_exists( 'use_block_editor_for_post' ) ) {
|
167 |
+
// We need to wait until we know which editor is in use
|
168 |
+
add_filter( 'use_block_editor_for_post', array( $this, '_maybe_load_sync_post' ), 999 ); // After the plugin Classic Editor
|
169 |
+
} elseif ( 'post.php' === $GLOBALS['pagenow'] && function_exists( 'use_block_editor_for_post' ) && isset( $_GET['post'] ) && empty( $_GET['meta-box-loader'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
170 |
+
$this->_maybe_load_sync_post( use_block_editor_for_post( (int) $_GET['post'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
171 |
+
} else {
|
172 |
+
$this->_maybe_load_sync_post( false );
|
173 |
+
}
|
174 |
+
}
|
175 |
+
|
176 |
+
/**
|
177 |
+
* Load the post synchronization object, depending on the editor in use.
|
178 |
+
*
|
179 |
+
* @since 2.6
|
180 |
+
*
|
181 |
+
* @param bool $is_block_editor Whether to use the block editor or not
|
182 |
+
* @return bool
|
183 |
+
*/
|
184 |
+
public function _maybe_load_sync_post( $is_block_editor ) {
|
185 |
+
if ( class_exists( 'PLL_Sync_Post_REST' ) && pll_use_block_editor_plugin() && $is_block_editor ) {
|
186 |
+
$this->sync_post = new PLL_Sync_Post_REST( $this );
|
187 |
+
} elseif ( class_exists( 'PLL_Sync_Post' ) ) {
|
188 |
+
$this->sync_post = new PLL_Sync_Post( $this );
|
189 |
+
}
|
190 |
+
|
191 |
+
return $is_block_editor;
|
192 |
}
|
193 |
}
|
admin/view-translations-media.php
CHANGED
@@ -18,22 +18,20 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
18 |
}
|
19 |
?>
|
20 |
<tr>
|
21 |
-
<td class = "pll-media-language-column"><span class = "pll-translation-flag"><?php echo $language->flag; ?></span><?php echo esc_html( $language->name ); ?></td>
|
22 |
<td class = "pll-media-edit-column">
|
23 |
<?php
|
24 |
-
// The translation exists
|
25 |
if ( ( $translation_id = $this->model->post->get_translation( $post_id, $language ) ) && $translation_id !== $post_id ) {
|
|
|
26 |
printf(
|
27 |
-
'<input type="hidden" name="media_tr_lang[%s]" value="%d"
|
28 |
esc_attr( $language->slug ),
|
29 |
-
esc_attr( $translation_id )
|
30 |
-
$this->links->edit_post_translation_link( $translation_id )
|
31 |
);
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
echo $this->links->new_post_translation_link( $post_id, $language );
|
37 |
}
|
38 |
?>
|
39 |
</td>
|
18 |
}
|
19 |
?>
|
20 |
<tr>
|
21 |
+
<td class = "pll-media-language-column"><span class = "pll-translation-flag"><?php echo $language->flag; // phpcs:ignore WordPress.Security.EscapeOutput ?></span><?php echo esc_html( $language->name ); ?></td>
|
22 |
<td class = "pll-media-edit-column">
|
23 |
<?php
|
|
|
24 |
if ( ( $translation_id = $this->model->post->get_translation( $post_id, $language ) ) && $translation_id !== $post_id ) {
|
25 |
+
// The translation exists
|
26 |
printf(
|
27 |
+
'<input type="hidden" name="media_tr_lang[%s]" value="%d" />',
|
28 |
esc_attr( $language->slug ),
|
29 |
+
esc_attr( $translation_id )
|
|
|
30 |
);
|
31 |
+
echo $this->links->edit_post_translation_link( $translation_id ); // phpcs:ignore WordPress.Security.EscapeOutput
|
32 |
+
} else {
|
33 |
+
// No translation
|
34 |
+
echo $this->links->new_post_translation_link( $post_id, $language ); // phpcs:ignore WordPress.Security.EscapeOutput
|
|
|
35 |
}
|
36 |
?>
|
37 |
</td>
|
admin/view-translations-post.php
CHANGED
@@ -17,12 +17,12 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
17 |
}
|
18 |
|
19 |
$value = $this->model->post->get_translation( $post_ID, $language );
|
20 |
-
if ( ! $value || $value == $post_ID ) { // $value == $post_ID happens if the post has been (
|
21 |
$value = '';
|
22 |
}
|
23 |
|
24 |
-
if (
|
25 |
-
$value = $this->model->post->get(
|
26 |
}
|
27 |
|
28 |
$link = $add_link = $this->links->new_post_translation_link( $post_ID, $language );
|
@@ -33,9 +33,9 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
33 |
}
|
34 |
?>
|
35 |
<tr>
|
36 |
-
<th class = "pll-language-column"><?php echo $language->flag ? $language->flag : esc_html( $language->slug ); ?></th>
|
37 |
-
<td class = "hidden"><?php echo $add_link; ?></td>
|
38 |
-
<td class = "pll-edit-column pll-column-icon"><?php echo $link; ?></td>
|
39 |
<?php
|
40 |
|
41 |
/**
|
@@ -55,11 +55,11 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
55 |
esc_attr( $language->slug ),
|
56 |
/* translators: accessibility text */
|
57 |
esc_html__( 'Translation', 'polylang' ),
|
58 |
-
empty( $value ) ? 0 : esc_attr( $selected->ID ),
|
59 |
-
empty( $value ) ? '' : esc_attr( $selected->post_title ),
|
60 |
-
empty( $link )
|
61 |
esc_attr( $language->get_locale( 'display' ) ),
|
62 |
-
$language->is_rtl ? 'rtl' : 'ltr'
|
63 |
);
|
64 |
?>
|
65 |
</td>
|
17 |
}
|
18 |
|
19 |
$value = $this->model->post->get_translation( $post_ID, $language );
|
20 |
+
if ( ! $value || $value == $post_ID ) { // $value == $post_ID happens if the post has been (auto)saved before changing the language
|
21 |
$value = '';
|
22 |
}
|
23 |
|
24 |
+
if ( ! empty( $from_post_id ) ) {
|
25 |
+
$value = $this->model->post->get( $from_post_id, $language );
|
26 |
}
|
27 |
|
28 |
$link = $add_link = $this->links->new_post_translation_link( $post_ID, $language );
|
33 |
}
|
34 |
?>
|
35 |
<tr>
|
36 |
+
<th class = "pll-language-column"><?php echo $language->flag ? $language->flag : esc_html( $language->slug ); // phpcs:ignore WordPress.Security.EscapeOutput ?></th>
|
37 |
+
<td class = "hidden"><?php echo $add_link; // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
|
38 |
+
<td class = "pll-edit-column pll-column-icon"><?php echo $link; // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
|
39 |
<?php
|
40 |
|
41 |
/**
|
55 |
esc_attr( $language->slug ),
|
56 |
/* translators: accessibility text */
|
57 |
esc_html__( 'Translation', 'polylang' ),
|
58 |
+
( empty( $value ) ? 0 : esc_attr( $selected->ID ) ),
|
59 |
+
( empty( $value ) ? '' : esc_attr( $selected->post_title ) ),
|
60 |
+
disabled( empty( $link ), true, false ),
|
61 |
esc_attr( $language->get_locale( 'display' ) ),
|
62 |
+
( $language->is_rtl ? 'rtl' : 'ltr' )
|
63 |
);
|
64 |
?>
|
65 |
</td>
|
admin/view-translations-term.php
CHANGED
@@ -34,7 +34,7 @@ else {
|
|
34 |
if ( isset( $term_id ) && ( $translation_id = $this->model->term->get_translation( $term_id, $language ) ) && $translation_id != $term_id ) {
|
35 |
$translation = get_term( $translation_id, $taxonomy );
|
36 |
}
|
37 |
-
if (
|
38 |
$translation = get_term( $translation_id, $taxonomy );
|
39 |
}
|
40 |
|
@@ -48,7 +48,7 @@ else {
|
|
48 |
?>
|
49 |
<tr>
|
50 |
<th class = "pll-language-column">
|
51 |
-
<span class = "pll-translation-flag"><?php echo $language->flag ? $language->flag : esc_html( $language->slug ); ?></span>
|
52 |
<?php
|
53 |
printf(
|
54 |
'<span class="pll-language-name%1$s">%2$s</span>',
|
@@ -60,8 +60,8 @@ else {
|
|
60 |
<?php
|
61 |
if ( isset( $term_id ) ) {
|
62 |
?>
|
63 |
-
<td class = "hidden"><?php echo $add_link; ?></td>
|
64 |
-
<td class = "pll-edit-column"><?php echo $link; ?></td>
|
65 |
<?php
|
66 |
}
|
67 |
?>
|
@@ -74,11 +74,11 @@ else {
|
|
74 |
esc_attr( $language->slug ),
|
75 |
/* translators: accessibility text */
|
76 |
esc_html__( 'Translation', 'polylang' ),
|
77 |
-
empty( $translation ) ? 0 : esc_attr( $translation->term_id ),
|
78 |
-
empty( $translation ) ? '' : esc_attr( $translation->name ),
|
79 |
-
empty( $disabled )
|
80 |
esc_attr( $language->get_locale( 'display' ) ),
|
81 |
-
$language->is_rtl ? 'rtl' : 'ltr'
|
82 |
);
|
83 |
?>
|
84 |
</td>
|
34 |
if ( isset( $term_id ) && ( $translation_id = $this->model->term->get_translation( $term_id, $language ) ) && $translation_id != $term_id ) {
|
35 |
$translation = get_term( $translation_id, $taxonomy );
|
36 |
}
|
37 |
+
if ( ! empty( $from_term_id ) && ( $translation_id = $this->model->term->get( $from_term_id, $language ) ) && ! $this->model->term->get_translation( $translation_id, $lang ) ) {
|
38 |
$translation = get_term( $translation_id, $taxonomy );
|
39 |
}
|
40 |
|
48 |
?>
|
49 |
<tr>
|
50 |
<th class = "pll-language-column">
|
51 |
+
<span class = "pll-translation-flag"><?php echo $language->flag ? $language->flag : esc_html( $language->slug ); // phpcs:ignore WordPress.Security.EscapeOutput ?></span>
|
52 |
<?php
|
53 |
printf(
|
54 |
'<span class="pll-language-name%1$s">%2$s</span>',
|
60 |
<?php
|
61 |
if ( isset( $term_id ) ) {
|
62 |
?>
|
63 |
+
<td class = "hidden"><?php echo $add_link; // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
|
64 |
+
<td class = "pll-edit-column"><?php echo $link; // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
|
65 |
<?php
|
66 |
}
|
67 |
?>
|
74 |
esc_attr( $language->slug ),
|
75 |
/* translators: accessibility text */
|
76 |
esc_html__( 'Translation', 'polylang' ),
|
77 |
+
( empty( $translation ) ? 0 : esc_attr( $translation->term_id ) ),
|
78 |
+
( empty( $translation ) ? '' : esc_attr( $translation->name ) ),
|
79 |
+
disabled( empty( $disabled ), false, false ),
|
80 |
esc_attr( $language->get_locale( 'display' ) ),
|
81 |
+
( $language->is_rtl ? 'rtl' : 'ltr' )
|
82 |
);
|
83 |
?>
|
84 |
</td>
|
css/admin.css
CHANGED
@@ -219,6 +219,25 @@ td[class*='column-language_'] {
|
|
219 |
float: right;
|
220 |
}
|
221 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
/* language and translations in edit-tags.php */
|
223 |
.pll-translation-flag { /* also for media */
|
224 |
margin-right: 14px;
|
@@ -305,6 +324,26 @@ td[class*='column-language_'] {
|
|
305 |
text-decoration: none;
|
306 |
}
|
307 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
308 |
@media screen and ( max-width: 782px ) {
|
309 |
/* settings */
|
310 |
#wpbody-content .pll-settings .pll-configure > td {
|
219 |
float: right;
|
220 |
}
|
221 |
|
222 |
+
/* Languages metabox buttons */
|
223 |
+
.pll-button {
|
224 |
+
padding: 0;
|
225 |
+
height: 20px;
|
226 |
+
background: none;
|
227 |
+
border: none;
|
228 |
+
font-size: 20px;
|
229 |
+
cursor: pointer;
|
230 |
+
}
|
231 |
+
|
232 |
+
.pll-button:not(.wp-ui-text-highlight) {
|
233 |
+
color: #DDDDDD;
|
234 |
+
}
|
235 |
+
|
236 |
+
#pll-duplicate {
|
237 |
+
float: right;
|
238 |
+
margin: 13px 7px;
|
239 |
+
}
|
240 |
+
|
241 |
/* language and translations in edit-tags.php */
|
242 |
.pll-translation-flag { /* also for media */
|
243 |
margin-right: 14px;
|
324 |
text-decoration: none;
|
325 |
}
|
326 |
|
327 |
+
/* Bulk translate */
|
328 |
+
.bulk-translate-save .button {
|
329 |
+
margin-right: 20px;
|
330 |
+
}
|
331 |
+
|
332 |
+
#wpbody-content #pll-translate fieldset {
|
333 |
+
display: inline-block;
|
334 |
+
width: 300px;
|
335 |
+
}
|
336 |
+
|
337 |
+
#pll-translate .pll-translation-flag {
|
338 |
+
margin-right: 0.3em;
|
339 |
+
}
|
340 |
+
|
341 |
+
#pll-translate .title {
|
342 |
+
display: block;
|
343 |
+
margin: 0.2em 0;
|
344 |
+
line-height: 2.5;
|
345 |
+
}
|
346 |
+
|
347 |
@media screen and ( max-width: 782px ) {
|
348 |
/* settings */
|
349 |
#wpbody-content .pll-settings .pll-configure > td {
|
css/admin.min.css
CHANGED
@@ -1 +1 @@
|
|
1 |
-
#pll-licenses-table td,.translation label{vertical-align:top}#post-translations a,.pll-notice a.notice-dismiss{text-decoration:none}#add-lang select{width:95%}.column-locale,.languages .column-slug{width:15%}.column-default_lang{width:5%}.column-count,.column-flag,.column-term_group{width:10%}.icon-default-lang:before{font-family:dashicons;content:"\f155"}.form-field input[type=radio]{width:auto;margin-right:2px}#pll-about-box p,#pll-recommended p{text-align:justify}#pll-about-box input{margin:0;padding:0;float:right}.stringstranslations .column-context,.stringstranslations .column-name{width:10%}.stringstranslations .column-string{width:33%}.translation label{display:inline-block;width:23%}.translation input,.translation textarea{width:72%}.pll-settings{margin-top:20px}.pll-settings .plugin-title{width:25%}#wpbody-content .pll-settings .pll-configure tr{display:table-row}#wpbody-content .pll-settings .pll-configure td{display:table-cell}#wpbody-content .pll-settings .pll-configure>td{padding:20px 20px 20px 40px}.pll-configure legend{font-size:14px;font-weight:600;margin-bottom:.5em}.pll-configure td .description{margin-top:2px;margin-bottom:.5em}.pll-configure p.submit{margin-top:20px}.pll-configure .button{margin-right:20px}.pll-configure fieldset{margin-bottom:1.5em}.pll-inline-block-list{margin:0}.pll-inline-block-list li{display:inline-block;margin:0;width:250px}#pll-domains-table td{padding:2px 2px 2px 1.5em;-webkit-box-shadow:none;box-shadow:none;border:none}.pll-settings-url-col{display:inline-block;width:49%;vertical-align:top}#pll-licenses-table label{font-size:1em;font-weight:600}.pll-configure .pll-deactivate-license{margin:0 0 0 20px}td[class*=column-language_],th[class*=column-language_]{width:1.5em}.pll-dir-rtl input[type=text],.pll-dir-rtl textarea{direction:rtl}.pll-dir-ltr input[type=text],.pll-dir-ltr textarea{direction:ltr}.pll-dir-ltr .tr_lang,.pll-dir-rtl .tr_lang{direction:inherit}#post-translations p{float:left}#post-translations table{table-layout:fixed;width:100%;clear:both}#post-translations .pll-column-icon,#post-translations .pll-language-column{width:20px}#post-translations .tr_lang{width:100%}#post-translations td{padding:2px}#post-translations .spinner,#term-translations .spinner{float:none;margin:0;background-position:center;width:auto}.pll-column-icon{text-align:center}#select-post-language .pll-select-flag{padding:4px;margin-right:32px}#select-media-language .pll-select-flag{padding:4px;margin-right:10px}.pll-media-edit-column{float:right}.pll-translation-flag{margin-right:14px}#select-add-term-language .pll-select-flag{padding:11px;margin-right:13px}#select-edit-term-language .pll-select-flag{padding:11px;margin-right:4px}#term-translations p{font-weight:400;font-style:normal;padding:2px;color:#23282d}#add-term-translations,#edit-term-translations{width:95%}#term-translations .pll-language-column{line-height:28px;width:20%}#add-term-translations .pll-language-column,#term-translations .pll-edit-column{width:20px}#edit-term-translations .pll-language-column{padding:15px 10px;font-weight:400}.pll_icon_tick:before{content:"\f147"}.pll_icon_add:before{content:"\f132"}.pll_icon_edit:before{content:"\f464"}[class^=pll_icon_]{font:20px/1 dashicons;vertical-align:middle}#wpadminbar #wp-admin-bar-languages .ab-item img{margin:0 8px 0 2px}#wpadminbar #wp-admin-bar-languages #wp-admin-bar-all .ab-item .ab-icon{float:none;top:4px}#wpadminbar #wp-admin-bar-languages .ab-icon:before{content:"\f326";top:1px}.pll-notice.notice{padding-right:38px;position:relative}@media screen and (max-width:782px){#wpbody-content .pll-settings .pll-configure>td{padding:20px}#wpbody-content .pll-settings #cb{padding:20px 9px}.pll-inline-block{width:auto}.pll-settings-url-col{display:block;width:100%}#wpbody-content .pll-settings #pll-licenses-table td{display:block}.pll-configure .pll-deactivate-license{margin:10px 0 5px}.stringstranslations .column-context,.stringstranslations .column-name{display:none}.translation label{display:block;width:95%;padding-left:0}.translation input{width:95%}#edit-term-translations .pll-language-name,#select-add-term-language .pll-select-flag,#select-edit-term-language .pll-select-flag{display:none}#edit-term-translations{width:100%}#add-term-translations .pll-language-column{line-height:38px}#edit-term-translations td{padding:8px 10px}#edit-term-translations .pll-edit-column,#edit-term-translations .pll-language-column{width:20px}.term-translations .pll-edit-column,.term-translations .pll-language-column,.term-translations .pll-translation-column{display:table-cell}.term-translations .hidden{display:none}#wpadminbar #wp-admin-bar-languages{display:block}#wpadminbar #wp-admin-bar-languages>.ab-item{width:50px;text-align:center}#wpadminbar #wp-admin-bar-languages>.ab-item .ab-icon:before{font:32px/1 dashicons;top:-1px}#wpadminbar #wp-admin-bar-languages>.ab-item img{margin:19px 0}#wpadminbar #wp-admin-bar-languages #wp-admin-bar-all .ab-item .ab-icon{margin-right:6px;font-size:20px!important;line-height:20px!important}}
|
1 |
+
#pll-licenses-table td,.translation label{vertical-align:top}#post-translations a,.pll-notice a.notice-dismiss{text-decoration:none}#add-lang select{width:95%}.column-locale,.languages .column-slug{width:15%}.column-default_lang{width:5%}.column-count,.column-flag,.column-term_group{width:10%}.icon-default-lang:before{font-family:dashicons;content:"\f155"}.form-field input[type=radio]{width:auto;margin-right:2px}#pll-about-box p,#pll-recommended p{text-align:justify}#pll-about-box input{margin:0;padding:0;float:right}.stringstranslations .column-context,.stringstranslations .column-name{width:10%}.stringstranslations .column-string{width:33%}.translation label{display:inline-block;width:23%}.translation input,.translation textarea{width:72%}.pll-settings{margin-top:20px}.pll-settings .plugin-title{width:25%}#wpbody-content .pll-settings .pll-configure tr{display:table-row}#wpbody-content .pll-settings .pll-configure td{display:table-cell}#wpbody-content .pll-settings .pll-configure>td{padding:20px 20px 20px 40px}.pll-configure legend{font-size:14px;font-weight:600;margin-bottom:.5em}.pll-configure td .description{margin-top:2px;margin-bottom:.5em}.pll-configure p.submit{margin-top:20px}.pll-configure .button{margin-right:20px}.pll-configure fieldset{margin-bottom:1.5em}.pll-inline-block-list{margin:0}.pll-inline-block-list li{display:inline-block;margin:0;width:250px}#pll-domains-table td{padding:2px 2px 2px 1.5em;-webkit-box-shadow:none;box-shadow:none;border:none}.pll-settings-url-col{display:inline-block;width:49%;vertical-align:top}#pll-licenses-table label{font-size:1em;font-weight:600}.pll-configure .pll-deactivate-license{margin:0 0 0 20px}td[class*=column-language_],th[class*=column-language_]{width:1.5em}.pll-dir-rtl input[type=text],.pll-dir-rtl textarea{direction:rtl}.pll-dir-ltr input[type=text],.pll-dir-ltr textarea{direction:ltr}.pll-dir-ltr .tr_lang,.pll-dir-rtl .tr_lang{direction:inherit}#post-translations p{float:left}#post-translations table{table-layout:fixed;width:100%;clear:both}#post-translations .pll-column-icon,#post-translations .pll-language-column{width:20px}#post-translations .tr_lang{width:100%}#post-translations td{padding:2px}#post-translations .spinner,#term-translations .spinner{float:none;margin:0;background-position:center;width:auto}.pll-column-icon{text-align:center}#select-post-language .pll-select-flag{padding:4px;margin-right:32px}#select-media-language .pll-select-flag{padding:4px;margin-right:10px}.pll-media-edit-column{float:right}.pll-button{padding:0;height:20px;background:0 0;border:none;font-size:20px;cursor:pointer}.pll-button:not(.wp-ui-text-highlight){color:#DDD}#pll-duplicate{float:right;margin:13px 7px}.pll-translation-flag{margin-right:14px}#select-add-term-language .pll-select-flag{padding:11px;margin-right:13px}#select-edit-term-language .pll-select-flag{padding:11px;margin-right:4px}#term-translations p{font-weight:400;font-style:normal;padding:2px;color:#23282d}#add-term-translations,#edit-term-translations{width:95%}#term-translations .pll-language-column{line-height:28px;width:20%}#add-term-translations .pll-language-column,#term-translations .pll-edit-column{width:20px}#edit-term-translations .pll-language-column{padding:15px 10px;font-weight:400}.pll_icon_tick:before{content:"\f147"}.pll_icon_add:before{content:"\f132"}.pll_icon_edit:before{content:"\f464"}[class^=pll_icon_]{font:20px/1 dashicons;vertical-align:middle}#wpadminbar #wp-admin-bar-languages .ab-item img{margin:0 8px 0 2px}#wpadminbar #wp-admin-bar-languages #wp-admin-bar-all .ab-item .ab-icon{float:none;top:4px}#wpadminbar #wp-admin-bar-languages .ab-icon:before{content:"\f326";top:1px}.pll-notice.notice{padding-right:38px;position:relative}.bulk-translate-save .button{margin-right:20px}#wpbody-content #pll-translate fieldset{display:inline-block;width:300px}#pll-translate .pll-translation-flag{margin-right:.3em}#pll-translate .title{display:block;margin:.2em 0;line-height:2.5}@media screen and (max-width:782px){#wpbody-content .pll-settings .pll-configure>td{padding:20px}#wpbody-content .pll-settings #cb{padding:20px 9px}.pll-inline-block{width:auto}.pll-settings-url-col{display:block;width:100%}#wpbody-content .pll-settings #pll-licenses-table td{display:block}.pll-configure .pll-deactivate-license{margin:10px 0 5px}.stringstranslations .column-context,.stringstranslations .column-name{display:none}.translation label{display:block;width:95%;padding-left:0}.translation input{width:95%}#edit-term-translations .pll-language-name,#select-add-term-language .pll-select-flag,#select-edit-term-language .pll-select-flag{display:none}#edit-term-translations{width:100%}#add-term-translations .pll-language-column{line-height:38px}#edit-term-translations td{padding:8px 10px}#edit-term-translations .pll-edit-column,#edit-term-translations .pll-language-column{width:20px}.term-translations .pll-edit-column,.term-translations .pll-language-column,.term-translations .pll-translation-column{display:table-cell}.term-translations .hidden{display:none}#wpadminbar #wp-admin-bar-languages{display:block}#wpadminbar #wp-admin-bar-languages>.ab-item{width:50px;text-align:center}#wpadminbar #wp-admin-bar-languages>.ab-item .ab-icon:before{font:32px/1 dashicons;top:-1px}#wpadminbar #wp-admin-bar-languages>.ab-item img{margin:19px 0}#wpadminbar #wp-admin-bar-languages #wp-admin-bar-all .ab-item .ab-icon{margin-right:6px;font-size:20px!important;line-height:20px!important}}
|
frontend/choose-lang-content.php
CHANGED
@@ -6,7 +6,7 @@
|
|
6 |
*
|
7 |
* @since 1.2
|
8 |
*/
|
9 |
-
class PLL_Choose_Lang_Content extends
|
10 |
|
11 |
/**
|
12 |
* Defers the language choice to the 'wp' action (when the content is known)
|
6 |
*
|
7 |
* @since 1.2
|
8 |
*/
|
9 |
+
class PLL_Choose_Lang_Content extends PLL_Choose_Lang {
|
10 |
|
11 |
/**
|
12 |
* Defers the language choice to the 'wp' action (when the content is known)
|
frontend/choose-lang-url.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
*
|
8 |
* @since 1.2
|
9 |
*/
|
10 |
-
class PLL_Choose_Lang_Url extends
|
11 |
protected $index = 'index.php'; // Need this before $wp_rewrite is created, also hardcoded in wp-includes/rewrite.php
|
12 |
|
13 |
/**
|
@@ -31,25 +31,27 @@ class PLL_Choose_Lang_Url extends PLL_Choose_lang {
|
|
31 |
* @since 1.2
|
32 |
*/
|
33 |
public function set_language_from_url() {
|
34 |
-
$host
|
35 |
-
$home_path =
|
36 |
|
37 |
-
$
|
38 |
-
$
|
|
|
|
|
39 |
|
40 |
// Home is requested
|
41 |
-
if ( $requested_host
|
42 |
$this->home_language();
|
43 |
add_action( 'setup_theme', array( $this, 'home_requested' ) );
|
44 |
}
|
45 |
|
46 |
// Take care to post & page preview http://wordpress.org/support/topic/static-frontpage-url-parameter-url-language-information
|
47 |
-
elseif ( isset( $_GET['preview'] ) && ( ( isset( $_GET['p'] ) && $id = (int) $_GET['p'] ) || ( isset( $_GET['page_id'] ) && $id = (int) $_GET['page_id'] ) ) ) {
|
48 |
$curlang = ( $lg = $this->model->post->get_language( $id ) ) ? $lg : $this->model->get_language( $this->options['default_lang'] );
|
49 |
}
|
50 |
|
51 |
// Take care to ( unattached ) attachments
|
52 |
-
elseif ( isset( $_GET['attachment_id'] ) && $id = (int) $_GET['attachment_id'] ) {
|
53 |
$curlang = ( $lg = $this->model->post->get_language( $id ) ) ? $lg : $this->get_preferred_language();
|
54 |
}
|
55 |
|
7 |
*
|
8 |
* @since 1.2
|
9 |
*/
|
10 |
+
class PLL_Choose_Lang_Url extends PLL_Choose_Lang {
|
11 |
protected $index = 'index.php'; // Need this before $wp_rewrite is created, also hardcoded in wp-includes/rewrite.php
|
12 |
|
13 |
/**
|
31 |
* @since 1.2
|
32 |
*/
|
33 |
public function set_language_from_url() {
|
34 |
+
$host = str_replace( 'www.', '', wp_parse_url( $this->links_model->home, PHP_URL_HOST ) ); // Remove www. for the comparison
|
35 |
+
$home_path = (string) wp_parse_url( $this->links_model->home, PHP_URL_PATH );
|
36 |
|
37 |
+
$requested_url = pll_get_requested_url();
|
38 |
+
$requested_host = str_replace( 'www.', '', wp_parse_url( $requested_url, PHP_URL_HOST ) ); // Remove www. for the comparison
|
39 |
+
$requested_path = rtrim( str_replace( $this->index, '', wp_parse_url( $requested_url, PHP_URL_PATH ) ), '/' ); // Some PHP setups turn requests for / into /index.php in REQUEST_URI
|
40 |
+
$requested_query = wp_parse_url( $requested_url, PHP_URL_QUERY );
|
41 |
|
42 |
// Home is requested
|
43 |
+
if ( $requested_host === $host && $requested_path === $home_path && empty( $requested_query ) ) {
|
44 |
$this->home_language();
|
45 |
add_action( 'setup_theme', array( $this, 'home_requested' ) );
|
46 |
}
|
47 |
|
48 |
// Take care to post & page preview http://wordpress.org/support/topic/static-frontpage-url-parameter-url-language-information
|
49 |
+
elseif ( isset( $_GET['preview'] ) && ( ( isset( $_GET['p'] ) && $id = (int) $_GET['p'] ) || ( isset( $_GET['page_id'] ) && $id = (int) $_GET['page_id'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
50 |
$curlang = ( $lg = $this->model->post->get_language( $id ) ) ? $lg : $this->model->get_language( $this->options['default_lang'] );
|
51 |
}
|
52 |
|
53 |
// Take care to ( unattached ) attachments
|
54 |
+
elseif ( isset( $_GET['attachment_id'] ) && $id = (int) $_GET['attachment_id'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
55 |
$curlang = ( $lg = $this->model->post->get_language( $id ) ) ? $lg : $this->get_preferred_language();
|
56 |
}
|
57 |
|
frontend/choose-lang.php
CHANGED
@@ -32,8 +32,8 @@ abstract class PLL_Choose_Lang {
|
|
32 |
* @since 1.8
|
33 |
*/
|
34 |
public function init() {
|
35 |
-
if ( Polylang::is_ajax_on_front() ||
|
36 |
-
$this->set_language( empty( $_REQUEST['lang'] ) ? $this->get_preferred_language() : $this->model->get_language( $_REQUEST['lang'] ) );
|
37 |
}
|
38 |
|
39 |
add_action( 'pre_comment_on_post', array( $this, 'pre_comment_on_post' ) ); // sets the language of comment
|
@@ -101,7 +101,7 @@ abstract class PLL_Choose_Lang {
|
|
101 |
$this->curlang->slug,
|
102 |
time() + $expiration,
|
103 |
COOKIEPATH,
|
104 |
-
2 == $this->options['force_lang'] ?
|
105 |
is_ssl()
|
106 |
);
|
107 |
}
|
@@ -120,7 +120,11 @@ abstract class PLL_Choose_Lang {
|
|
120 |
|
121 |
if ( isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) {
|
122 |
// Break up string into pieces ( languages and q factors )
|
123 |
-
preg_match_all(
|
|
|
|
|
|
|
|
|
124 |
|
125 |
$k = $lang_parse[1];
|
126 |
$v = $lang_parse[4];
|
@@ -196,7 +200,7 @@ abstract class PLL_Choose_Lang {
|
|
196 |
public function get_preferred_language() {
|
197 |
// check first if the user was already browsing this site
|
198 |
if ( isset( $_COOKIE[ PLL_COOKIE ] ) ) {
|
199 |
-
return $this->model->get_language( $_COOKIE[ PLL_COOKIE ] );
|
200 |
}
|
201 |
|
202 |
/**
|
@@ -221,11 +225,11 @@ abstract class PLL_Choose_Lang {
|
|
221 |
* @since 1.2
|
222 |
*/
|
223 |
protected function home_language() {
|
224 |
-
//
|
225 |
-
//
|
226 |
-
$language = $this->options['hide_default'] && ( (
|
227 |
$this->model->get_language( $this->options['default_lang'] ) :
|
228 |
-
$this->get_preferred_language(); //
|
229 |
$this->set_language( $language );
|
230 |
}
|
231 |
|
@@ -252,9 +256,12 @@ abstract class PLL_Choose_Lang {
|
|
252 |
// Test to avoid crash if get_home_url returns something wrong
|
253 |
// FIXME why this happens? http://wordpress.org/support/topic/polylang-crashes-1
|
254 |
// Don't redirect if $_POST is not empty as it could break other plugins
|
255 |
-
|
256 |
-
|
257 |
-
$
|
|
|
|
|
|
|
258 |
|
259 |
/**
|
260 |
* When a visitor reaches the site home, Polylang redirects to the home page in the correct language.
|
@@ -267,7 +274,7 @@ abstract class PLL_Choose_Lang {
|
|
267 |
*/
|
268 |
if ( $redirect = apply_filters( 'pll_redirect_home', $redirect ) ) {
|
269 |
$this->maybe_setcookie();
|
270 |
-
|
271 |
exit;
|
272 |
}
|
273 |
}
|
32 |
* @since 1.8
|
33 |
*/
|
34 |
public function init() {
|
35 |
+
if ( Polylang::is_ajax_on_front() || ! wp_using_themes() ) {
|
36 |
+
$this->set_language( empty( $_REQUEST['lang'] ) ? $this->get_preferred_language() : $this->model->get_language( sanitize_key( $_REQUEST['lang'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
37 |
}
|
38 |
|
39 |
add_action( 'pre_comment_on_post', array( $this, 'pre_comment_on_post' ) ); // sets the language of comment
|
101 |
$this->curlang->slug,
|
102 |
time() + $expiration,
|
103 |
COOKIEPATH,
|
104 |
+
2 == $this->options['force_lang'] ? wp_parse_url( $this->links_model->home, PHP_URL_HOST ) : COOKIE_DOMAIN,
|
105 |
is_ssl()
|
106 |
);
|
107 |
}
|
120 |
|
121 |
if ( isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) {
|
122 |
// Break up string into pieces ( languages and q factors )
|
123 |
+
preg_match_all(
|
124 |
+
'/([a-z]{1,8}(-[a-z]{1,8})?)\s*(;\s*q\s*=\s*((?>1|0)(?>\.[0-9]+)?))?/i',
|
125 |
+
sanitize_text_field( wp_unslash( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ),
|
126 |
+
$lang_parse
|
127 |
+
);
|
128 |
|
129 |
$k = $lang_parse[1];
|
130 |
$v = $lang_parse[4];
|
200 |
public function get_preferred_language() {
|
201 |
// check first if the user was already browsing this site
|
202 |
if ( isset( $_COOKIE[ PLL_COOKIE ] ) ) {
|
203 |
+
return $this->model->get_language( sanitize_key( $_COOKIE[ PLL_COOKIE ] ) );
|
204 |
}
|
205 |
|
206 |
/**
|
225 |
* @since 1.2
|
226 |
*/
|
227 |
protected function home_language() {
|
228 |
+
// Test referer in case PLL_COOKIE is set to false. Since WP 3.6.1, wp_get_referer() validates the host which is exactly what we want
|
229 |
+
// Thanks to Ov3rfly http://wordpress.org/support/topic/enhance-feature-when-front-page-is-visited-set-language-according-to-browser
|
230 |
+
$language = $this->options['hide_default'] && ( wp_get_referer() || ! $this->options['browser'] ) ?
|
231 |
$this->model->get_language( $this->options['default_lang'] ) :
|
232 |
+
$this->get_preferred_language(); // Sets the language according to browser preference or default language
|
233 |
$this->set_language( $language );
|
234 |
}
|
235 |
|
256 |
// Test to avoid crash if get_home_url returns something wrong
|
257 |
// FIXME why this happens? http://wordpress.org/support/topic/polylang-crashes-1
|
258 |
// Don't redirect if $_POST is not empty as it could break other plugins
|
259 |
+
elseif ( is_string( $redirect = $this->curlang->home_url ) && empty( $_POST ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
260 |
+
// Don't forget the query string which may be added by plugins
|
261 |
+
$query_string = wp_parse_url( pll_get_requested_url(), PHP_URL_QUERY );
|
262 |
+
if ( ! empty( $query_string ) ) {
|
263 |
+
$redirect .= ( $this->links_model->using_permalinks ? '?' : '&' ) . $query_string;
|
264 |
+
}
|
265 |
|
266 |
/**
|
267 |
* When a visitor reaches the site home, Polylang redirects to the home page in the correct language.
|
274 |
*/
|
275 |
if ( $redirect = apply_filters( 'pll_redirect_home', $redirect ) ) {
|
276 |
$this->maybe_setcookie();
|
277 |
+
wp_safe_redirect( $redirect, 302, POLYLANG );
|
278 |
exit;
|
279 |
}
|
280 |
}
|
frontend/frontend-auto-translate.php
CHANGED
@@ -190,7 +190,7 @@ class PLL_Frontend_Auto_Translate {
|
|
190 |
if ( ! empty( $qv[ $key ] ) ) {
|
191 |
// post__in used by the 2 functions below
|
192 |
// Useless to filter them as output is already in the right language and would result in performance loss
|
193 |
-
foreach ( debug_backtrace() as $trace ) {
|
194 |
if ( in_array( $trace['function'], array( 'wp_nav_menu', 'gallery_shortcode' ) ) ) {
|
195 |
return;
|
196 |
}
|
190 |
if ( ! empty( $qv[ $key ] ) ) {
|
191 |
// post__in used by the 2 functions below
|
192 |
// Useless to filter them as output is already in the right language and would result in performance loss
|
193 |
+
foreach ( debug_backtrace() as $trace ) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
194 |
if ( in_array( $trace['function'], array( 'wp_nav_menu', 'gallery_shortcode' ) ) ) {
|
195 |
return;
|
196 |
}
|
frontend/frontend-filters-links.php
CHANGED
@@ -269,7 +269,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
|
|
269 |
);
|
270 |
}
|
271 |
|
272 |
-
$traces = version_compare( PHP_VERSION, '5.2.5', '>=' ) ? debug_backtrace( false ) : debug_backtrace();
|
273 |
unset( $traces[0], $traces[1] ); // We don't need the last 2 calls: this function + call_user_func_array (or apply_filters on PHP7+)
|
274 |
|
275 |
foreach ( $traces as $trace ) {
|
@@ -323,7 +323,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
|
|
323 |
}
|
324 |
|
325 |
// Don't redirect mysite.com/?attachment_id= to mysite.com/en/?attachment_id=
|
326 |
-
if ( 1 == $this->options['force_lang'] && is_attachment() && isset( $_GET['attachment_id'] ) ) {
|
327 |
return;
|
328 |
}
|
329 |
|
@@ -334,7 +334,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
|
|
334 |
}
|
335 |
|
336 |
if ( empty( $requested_url ) ) {
|
337 |
-
$requested_url = (
|
338 |
}
|
339 |
|
340 |
if ( is_single() || is_page() ) {
|
@@ -362,11 +362,12 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
|
|
362 |
}
|
363 |
|
364 |
if ( 3 === $this->options['force_lang'] ) {
|
|
|
365 |
foreach ( $this->options['domains'] as $lang => $domain ) {
|
366 |
-
$host =
|
367 |
-
if ( 'www.' . $
|
368 |
$language = $this->model->get_language( $lang );
|
369 |
-
$redirect_url = str_replace( '://' . $
|
370 |
}
|
371 |
}
|
372 |
}
|
@@ -398,7 +399,7 @@ class PLL_Frontend_Filters_Links extends PLL_Filters_Links {
|
|
398 |
|
399 |
// The language is not correctly set so let's redirect to the correct url for this object
|
400 |
if ( $do_redirect && $redirect_url && $requested_url != $redirect_url ) {
|
401 |
-
|
402 |
exit;
|
403 |
}
|
404 |
|
269 |
);
|
270 |
}
|
271 |
|
272 |
+
$traces = version_compare( PHP_VERSION, '5.2.5', '>=' ) ? debug_backtrace( false ) : debug_backtrace(); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
273 |
unset( $traces[0], $traces[1] ); // We don't need the last 2 calls: this function + call_user_func_array (or apply_filters on PHP7+)
|
274 |
|
275 |
foreach ( $traces as $trace ) {
|
323 |
}
|
324 |
|
325 |
// Don't redirect mysite.com/?attachment_id= to mysite.com/en/?attachment_id=
|
326 |
+
if ( 1 == $this->options['force_lang'] && is_attachment() && isset( $_GET['attachment_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
327 |
return;
|
328 |
}
|
329 |
|
334 |
}
|
335 |
|
336 |
if ( empty( $requested_url ) ) {
|
337 |
+
$requested_url = pll_get_requested_url();
|
338 |
}
|
339 |
|
340 |
if ( is_single() || is_page() ) {
|
362 |
}
|
363 |
|
364 |
if ( 3 === $this->options['force_lang'] ) {
|
365 |
+
$requested_host = wp_parse_url( $requested_url, PHP_URL_HOST );
|
366 |
foreach ( $this->options['domains'] as $lang => $domain ) {
|
367 |
+
$host = wp_parse_url( $domain, PHP_URL_HOST );
|
368 |
+
if ( 'www.' . $requested_host === $host || 'www.' . $host === $requested_host ) {
|
369 |
$language = $this->model->get_language( $lang );
|
370 |
+
$redirect_url = str_replace( '://' . $requested_host, '://' . $host, $requested_url );
|
371 |
}
|
372 |
}
|
373 |
}
|
399 |
|
400 |
// The language is not correctly set so let's redirect to the correct url for this object
|
401 |
if ( $do_redirect && $redirect_url && $requested_url != $redirect_url ) {
|
402 |
+
wp_safe_redirect( $redirect_url, 301, POLYLANG );
|
403 |
exit;
|
404 |
}
|
405 |
|
frontend/frontend-filters-search.php
CHANGED
@@ -80,8 +80,8 @@ class PLL_Frontend_Filters_Search {
|
|
80 |
public function admin_bar_search_menu( $wp_admin_bar ) {
|
81 |
$form = '<form action="' . esc_url( home_url( '/' ) ) . '" method="get" id="adminbarsearch">';
|
82 |
$form .= '<input class="adminbar-input" name="s" id="adminbar-search" type="text" value="" maxlength="150" />';
|
83 |
-
$form .= '<label for="adminbar-search" class="screen-reader-text">' . esc_html__( 'Search' ) . '</label>';
|
84 |
-
$form .= '<input type="submit" class="adminbar-button" value="' . esc_attr__( 'Search' ) . '"/>';
|
85 |
$form .= '</form>';
|
86 |
|
87 |
$wp_admin_bar->add_menu(
|
@@ -129,6 +129,6 @@ class PLL_Frontend_Filters_Search {
|
|
129 |
}
|
130 |
}
|
131 |
//]]>";
|
132 |
-
echo '<script type="text/javascript">' . $js . '</script>';
|
133 |
}
|
134 |
}
|
80 |
public function admin_bar_search_menu( $wp_admin_bar ) {
|
81 |
$form = '<form action="' . esc_url( home_url( '/' ) ) . '" method="get" id="adminbarsearch">';
|
82 |
$form .= '<input class="adminbar-input" name="s" id="adminbar-search" type="text" value="" maxlength="150" />';
|
83 |
+
$form .= '<label for="adminbar-search" class="screen-reader-text">' . esc_html__( 'Search', 'polylang' ) . '</label>';
|
84 |
+
$form .= '<input type="submit" class="adminbar-button" value="' . esc_attr__( 'Search', 'polylang' ) . '"/>';
|
85 |
$form .= '</form>';
|
86 |
|
87 |
$wp_admin_bar->add_menu(
|
129 |
}
|
130 |
}
|
131 |
//]]>";
|
132 |
+
echo '<script type="text/javascript">' . $js . '</script>'; // phpcs:ignore WordPress.Security.EscapeOutput
|
133 |
}
|
134 |
}
|
frontend/frontend-filters.php
CHANGED
@@ -48,7 +48,7 @@ class PLL_Frontend_Filters extends PLL_Filters {
|
|
48 |
|
49 |
// Support theme customizer
|
50 |
// FIXME of course does not work if 'transport' is set to 'postMessage'
|
51 |
-
if ( isset( $_POST['wp_customize'], $_POST['customized'] ) ) {
|
52 |
add_filter( 'pre_option_blogname', 'pll__', 20 );
|
53 |
add_filter( 'pre_option_blogdescription', 'pll__', 20 );
|
54 |
}
|
@@ -94,7 +94,7 @@ class PLL_Frontend_Filters extends PLL_Filters {
|
|
94 |
$_posts = array_fill_keys( $languages, array() ); // Init with empty arrays
|
95 |
$languages = implode( ',', $languages );
|
96 |
|
97 |
-
// PHPCS:ignore WordPress.DB.PreparedSQL
|
98 |
$relations = $wpdb->get_results( "SELECT object_id, term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id IN ({$posts}) AND term_taxonomy_id IN ({$languages})" );
|
99 |
|
100 |
foreach ( $relations as $relation ) {
|
@@ -167,7 +167,7 @@ class PLL_Frontend_Filters extends PLL_Filters {
|
|
167 |
return $sidebars_widgets;
|
168 |
}
|
169 |
|
170 |
-
$cache_key = md5(
|
171 |
$_sidebars_widgets = $this->cache->get( "sidebars_widgets_{$cache_key}" );
|
172 |
|
173 |
if ( false !== $_sidebars_widgets ) {
|
48 |
|
49 |
// Support theme customizer
|
50 |
// FIXME of course does not work if 'transport' is set to 'postMessage'
|
51 |
+
if ( isset( $_POST['wp_customize'], $_POST['customized'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
52 |
add_filter( 'pre_option_blogname', 'pll__', 20 );
|
53 |
add_filter( 'pre_option_blogdescription', 'pll__', 20 );
|
54 |
}
|
94 |
$_posts = array_fill_keys( $languages, array() ); // Init with empty arrays
|
95 |
$languages = implode( ',', $languages );
|
96 |
|
97 |
+
// PHPCS:ignore WordPress.DB.PreparedSQL
|
98 |
$relations = $wpdb->get_results( "SELECT object_id, term_taxonomy_id FROM {$wpdb->term_relationships} WHERE object_id IN ({$posts}) AND term_taxonomy_id IN ({$languages})" );
|
99 |
|
100 |
foreach ( $relations as $relation ) {
|
167 |
return $sidebars_widgets;
|
168 |
}
|
169 |
|
170 |
+
$cache_key = md5( maybe_serialize( $sidebars_widgets ) );
|
171 |
$_sidebars_widgets = $this->cache->get( "sidebars_widgets_{$cache_key}" );
|
172 |
|
173 |
if ( false !== $_sidebars_widgets ) {
|
frontend/frontend-links.php
CHANGED
@@ -58,12 +58,12 @@ class PLL_Frontend_Links extends PLL_Links {
|
|
58 |
$hide = $this->options['default_lang'] == $language->slug && $this->options['hide_default'];
|
59 |
|
60 |
// Post and attachment
|
61 |
-
if ( is_single() && ( $this->options['media_support'] || ! is_attachment() ) && ( $id = $this->model->post->get( $queried_object_id, $language ) ) && $this->current_user_can_read( $id ) ) {
|
62 |
$url = get_permalink( $id );
|
63 |
}
|
64 |
|
65 |
// Page
|
66 |
-
elseif ( is_page() && ( $id = $this->model->post->get( $queried_object_id, $language ) ) && $this->current_user_can_read( $id ) ) {
|
67 |
$url = get_page_link( $id );
|
68 |
}
|
69 |
|
@@ -181,7 +181,7 @@ class PLL_Frontend_Links extends PLL_Links {
|
|
181 |
* @return string
|
182 |
*/
|
183 |
public function get_archive_url( $language ) {
|
184 |
-
$url = (
|
185 |
$url = $this->links_model->switch_language_in_link( $url, $language );
|
186 |
$url = $this->links_model->remove_paged_from_link( $url );
|
187 |
|
58 |
$hide = $this->options['default_lang'] == $language->slug && $this->options['hide_default'];
|
59 |
|
60 |
// Post and attachment
|
61 |
+
if ( is_single() && ( $this->options['media_support'] || ! is_attachment() ) && ( $id = $this->model->post->get( $queried_object_id, $language ) ) && $this->model->post->current_user_can_read( $id ) ) {
|
62 |
$url = get_permalink( $id );
|
63 |
}
|
64 |
|
65 |
// Page
|
66 |
+
elseif ( is_page() && ( $id = $this->model->post->get( $queried_object_id, $language ) ) && $this->model->post->current_user_can_read( $id ) ) {
|
67 |
$url = get_page_link( $id );
|
68 |
}
|
69 |
|
181 |
* @return string
|
182 |
*/
|
183 |
public function get_archive_url( $language ) {
|
184 |
+
$url = pll_get_requested_url();
|
185 |
$url = $this->links_model->switch_language_in_link( $url, $language );
|
186 |
$url = $this->links_model->remove_paged_from_link( $url );
|
187 |
|
frontend/frontend-nav-menu.php
CHANGED
@@ -30,7 +30,7 @@ class PLL_Frontend_Nav_Menu extends PLL_Nav_Menu {
|
|
30 |
add_filter( 'wp_nav_menu_args', array( $this, 'wp_nav_menu_args' ) );
|
31 |
|
32 |
// The customizer
|
33 |
-
if ( isset( $_POST['wp_customize'], $_POST['customized'] ) ) {
|
34 |
add_filter( 'wp_nav_menu_args', array( $this, 'filter_args_before_customizer' ) );
|
35 |
add_filter( 'wp_nav_menu_args', array( $this, 'filter_args_after_customizer' ), 2000 );
|
36 |
}
|
@@ -105,7 +105,8 @@ class PLL_Frontend_Nav_Menu extends PLL_Nav_Menu {
|
|
105 |
|
106 |
// parent item for dropdown
|
107 |
if ( ! empty( $options['dropdown'] ) ) {
|
108 |
-
$
|
|
|
109 |
$item->attr_title = '';
|
110 |
$item->classes = array( 'pll-parent-menu-item' );
|
111 |
$new_items[] = $item;
|
@@ -223,20 +224,16 @@ class PLL_Frontend_Nav_Menu extends PLL_Nav_Menu {
|
|
223 |
}
|
224 |
|
225 |
// Support for theme customizer
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
if (
|
233 |
-
$
|
234 |
-
|
235 |
-
|
236 |
-
$menus[ $infos['location'] ] = $c;
|
237 |
-
} elseif ( $this->curlang->slug == $this->options['default_lang'] ) {
|
238 |
-
$menus[ $loc ] = $c;
|
239 |
-
}
|
240 |
}
|
241 |
}
|
242 |
}
|
30 |
add_filter( 'wp_nav_menu_args', array( $this, 'wp_nav_menu_args' ) );
|
31 |
|
32 |
// The customizer
|
33 |
+
if ( isset( $_POST['wp_customize'], $_POST['customized'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
34 |
add_filter( 'wp_nav_menu_args', array( $this, 'filter_args_before_customizer' ) );
|
35 |
add_filter( 'wp_nav_menu_args', array( $this, 'filter_args_after_customizer' ), 2000 );
|
36 |
}
|
105 |
|
106 |
// parent item for dropdown
|
107 |
if ( ! empty( $options['dropdown'] ) ) {
|
108 |
+
$name = isset( $options['display_names_as'] ) && 'slug' === $options['display_names_as'] ? $this->curlang->slug : $this->curlang->name;
|
109 |
+
$item->title = $this->get_item_title( $this->curlang->flag, $name, $options );
|
110 |
$item->attr_title = '';
|
111 |
$item->classes = array( 'pll-parent-menu-item' );
|
112 |
$new_items[] = $item;
|
224 |
}
|
225 |
|
226 |
// Support for theme customizer
|
227 |
+
if ( is_customize_preview() ) {
|
228 |
+
global $wp_customize;
|
229 |
+
foreach ( $wp_customize->unsanitized_post_values() as $key => $value ) {
|
230 |
+
if ( false !== strpos( $key, 'nav_menu_locations[' ) ) {
|
231 |
+
$loc = substr( trim( $key, ']' ), 19 );
|
232 |
+
$infos = $this->explode_location( $loc );
|
233 |
+
if ( $infos['lang'] === $this->curlang->slug ) {
|
234 |
+
$menus[ $infos['location'] ] = (int) $value;
|
235 |
+
} elseif ( $this->curlang->slug === $this->options['default_lang'] ) {
|
236 |
+
$menus[ $loc ] = (int) $value;
|
|
|
|
|
|
|
|
|
237 |
}
|
238 |
}
|
239 |
}
|
frontend/frontend-static-pages.php
CHANGED
@@ -47,7 +47,7 @@ class PLL_Frontend_Static_Pages extends PLL_Static_Pages {
|
|
47 |
add_filter( 'option_page_for_posts', array( $this, 'translate_page_for_posts' ) );
|
48 |
|
49 |
// Support theme customizer
|
50 |
-
if ( isset( $_POST['wp_customize'], $_POST['customized'] ) ) {
|
51 |
add_filter( 'pre_option_page_on_front', 'pll_get_post', 20 );
|
52 |
add_filter( 'pre_option_page_for_post', 'pll_get_post', 20 );
|
53 |
}
|
@@ -90,7 +90,7 @@ class PLL_Frontend_Static_Pages extends PLL_Static_Pages {
|
|
90 |
$url = is_paged() ? $this->links_model->add_paged_to_link( $this->links->get_home_url(), $wp_query->query_vars['page'] ) : $this->links->get_home_url();
|
91 |
|
92 |
// Don't forget additional query vars
|
93 |
-
$query =
|
94 |
if ( ! empty( $query ) ) {
|
95 |
parse_str( $query, $query_vars );
|
96 |
$query_vars = rawurlencode_deep( $query_vars ); // WP encodes query vars values
|
@@ -138,7 +138,7 @@ class PLL_Frontend_Static_Pages extends PLL_Static_Pages {
|
|
138 |
* @return bool|string
|
139 |
*/
|
140 |
public function pll_check_canonical_url( $redirect_url ) {
|
141 |
-
return $this->options['redirect_lang'] && ! empty( $this->curlang->page_on_front ) && is_page( $this->curlang->page_on_front ) ? false : $redirect_url;
|
142 |
}
|
143 |
|
144 |
/**
|
@@ -175,10 +175,15 @@ class PLL_Frontend_Static_Pages extends PLL_Static_Pages {
|
|
175 |
|
176 |
// Redirect the language page to the homepage when using a static front page
|
177 |
elseif ( ( $this->options['redirect_lang'] || $this->options['hide_default'] ) && $this->is_front_page( $query ) && $lang = $this->model->get_language( get_query_var( 'lang' ) ) ) {
|
178 |
-
$query->set( 'page_id', $lang->page_on_front );
|
179 |
-
$query->is_singular = $query->is_page = true;
|
180 |
$query->is_archive = $query->is_tax = false;
|
181 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
182 |
}
|
183 |
|
184 |
// Fix paged static front page in plain permalinks when Settings > Reading doesn't match the default language
|
47 |
add_filter( 'option_page_for_posts', array( $this, 'translate_page_for_posts' ) );
|
48 |
|
49 |
// Support theme customizer
|
50 |
+
if ( isset( $_POST['wp_customize'], $_POST['customized'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
51 |
add_filter( 'pre_option_page_on_front', 'pll_get_post', 20 );
|
52 |
add_filter( 'pre_option_page_for_post', 'pll_get_post', 20 );
|
53 |
}
|
90 |
$url = is_paged() ? $this->links_model->add_paged_to_link( $this->links->get_home_url(), $wp_query->query_vars['page'] ) : $this->links->get_home_url();
|
91 |
|
92 |
// Don't forget additional query vars
|
93 |
+
$query = wp_parse_url( $redirect_url, PHP_URL_QUERY );
|
94 |
if ( ! empty( $query ) ) {
|
95 |
parse_str( $query, $query_vars );
|
96 |
$query_vars = rawurlencode_deep( $query_vars ); // WP encodes query vars values
|
138 |
* @return bool|string
|
139 |
*/
|
140 |
public function pll_check_canonical_url( $redirect_url ) {
|
141 |
+
return $this->options['redirect_lang'] && ! $this->options['force_lang'] && ! empty( $this->curlang->page_on_front ) && is_page( $this->curlang->page_on_front ) ? false : $redirect_url;
|
142 |
}
|
143 |
|
144 |
/**
|
175 |
|
176 |
// Redirect the language page to the homepage when using a static front page
|
177 |
elseif ( ( $this->options['redirect_lang'] || $this->options['hide_default'] ) && $this->is_front_page( $query ) && $lang = $this->model->get_language( get_query_var( 'lang' ) ) ) {
|
|
|
|
|
178 |
$query->is_archive = $query->is_tax = false;
|
179 |
+
if ( ! empty( $lang->page_on_front ) ) {
|
180 |
+
$query->set( 'page_id', $lang->page_on_front );
|
181 |
+
$query->is_singular = $query->is_page = true;
|
182 |
+
unset( $query->query_vars['lang'], $query->queried_object ); // Reset queried object
|
183 |
+
} else {
|
184 |
+
// Handle case where the static front page hasn't be translated to avoid a possible infinite redirect loop.
|
185 |
+
$query->is_home = true;
|
186 |
+
}
|
187 |
}
|
188 |
|
189 |
// Fix paged static front page in plain permalinks when Settings > Reading doesn't match the default language
|
frontend/frontend.php
CHANGED
@@ -10,7 +10,7 @@
|
|
10 |
* links_model => inherited, reference to PLL_Links_Model object
|
11 |
* links => reference to PLL_Links object
|
12 |
* static_pages => reference to PLL_Frontend_Static_Pages object
|
13 |
-
* choose_lang => reference to
|
14 |
* curlang => current language
|
15 |
* filters => reference to PLL_Frontend_Filters object
|
16 |
* filters_links => reference to PLL_Frontend_Filters_Links object
|
@@ -51,54 +51,51 @@ class PLL_Frontend extends PLL_Base {
|
|
51 |
}
|
52 |
}
|
53 |
|
54 |
-
/**
|
55 |
-
* Is the current request a REST API request?
|
56 |
-
* Inspired by WP::parse_request()
|
57 |
-
* Needed because at this point, the constant REST_REQUEST is not defined yet
|
58 |
-
*
|
59 |
-
* @since 2.4.1
|
60 |
-
*
|
61 |
-
* @return bool
|
62 |
-
*/
|
63 |
-
public function is_rest_request() {
|
64 |
-
$home_path = trim( parse_url( home_url(), PHP_URL_PATH ), '/' );
|
65 |
-
$home_path_regex = sprintf( '|^%s|i', preg_quote( $home_path, '|' ) );
|
66 |
-
|
67 |
-
$req_uri = trim( $_SERVER['REQUEST_URI'], '/' );
|
68 |
-
$req_uri = preg_replace( $home_path_regex, '', $req_uri );
|
69 |
-
$req_uri = trim( $req_uri, '/' );
|
70 |
-
$req_uri = str_replace( 'index.php', '', $req_uri );
|
71 |
-
$req_uri = trim( $req_uri, '/' );
|
72 |
-
|
73 |
-
return 0 === strpos( $req_uri, rest_get_url_prefix() . '/' );
|
74 |
-
}
|
75 |
-
|
76 |
/**
|
77 |
* Setups the language chooser based on options
|
78 |
*
|
79 |
* @since 1.2
|
80 |
*/
|
81 |
public function init() {
|
|
|
|
|
82 |
$this->links = new PLL_Frontend_Links( $this );
|
83 |
|
84 |
-
//
|
85 |
-
if (
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
}
|
|
|
93 |
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
|
|
99 |
|
100 |
-
//
|
101 |
-
$this->
|
|
|
|
|
|
|
|
|
102 |
}
|
103 |
}
|
104 |
|
@@ -163,7 +160,7 @@ class PLL_Frontend extends PLL_Base {
|
|
163 |
|
164 |
// Remove pages query when the language is set unless we do a search
|
165 |
// Take care not to break the single page, attachment and taxonomies queries!
|
166 |
-
if ( empty( $qv['post_type'] ) && ! $query->is_search && ! $query->
|
167 |
$query->set( 'post_type', 'post' );
|
168 |
}
|
169 |
|
10 |
* links_model => inherited, reference to PLL_Links_Model object
|
11 |
* links => reference to PLL_Links object
|
12 |
* static_pages => reference to PLL_Frontend_Static_Pages object
|
13 |
+
* choose_lang => reference to PLL_Choose_Lang object
|
14 |
* curlang => current language
|
15 |
* filters => reference to PLL_Frontend_Filters object
|
16 |
* filters_links => reference to PLL_Frontend_Filters_Links object
|
51 |
}
|
52 |
}
|
53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
54 |
/**
|
55 |
* Setups the language chooser based on options
|
56 |
*
|
57 |
* @since 1.2
|
58 |
*/
|
59 |
public function init() {
|
60 |
+
parent::init();
|
61 |
+
|
62 |
$this->links = new PLL_Frontend_Links( $this );
|
63 |
|
64 |
+
// Static front page and page for posts
|
65 |
+
if ( 'page' === get_option( 'show_on_front' ) ) {
|
66 |
+
$this->static_pages = new PLL_Frontend_Static_Pages( $this );
|
67 |
+
}
|
68 |
+
|
69 |
+
// Setup the language chooser
|
70 |
+
$c = array( 'Content', 'Url', 'Url', 'Domain' );
|
71 |
+
$class = 'PLL_Choose_Lang_' . $c[ $this->options['force_lang'] ];
|
72 |
+
$this->choose_lang = new $class( $this );
|
73 |
+
$this->choose_lang->init();
|
74 |
+
|
75 |
+
// Need to load nav menu class early to correctly define the locations in the customizer when the language is set from the content
|
76 |
+
$this->nav_menu = new PLL_Frontend_Nav_Menu( $this );
|
77 |
+
|
78 |
+
// Cross domain
|
79 |
+
if ( PLL_COOKIE ) {
|
80 |
+
$class = array( 2 => 'PLL_Xdata_Subdomain', 3 => 'PLL_Xdata_Domain' );
|
81 |
+
if ( isset( $class[ $this->options['force_lang'] ] ) && class_exists( $class[ $this->options['force_lang'] ] ) ) {
|
82 |
+
$this->xdata = new $class[ $this->options['force_lang'] ]( $this );
|
83 |
}
|
84 |
+
}
|
85 |
|
86 |
+
if ( get_option( 'permalink_structure' ) ) {
|
87 |
+
// Translate slugs
|
88 |
+
if ( class_exists( 'PLL_Frontend_Translate_Slugs' ) ) {
|
89 |
+
$slugs_model = new PLL_Translate_Slugs_Model( $this );
|
90 |
+
$this->translate_slugs = new PLL_Frontend_Translate_Slugs( $slugs_model, $this->curlang );
|
91 |
+
}
|
92 |
|
93 |
+
// Share term slugs
|
94 |
+
if ( $this->options['force_lang'] && class_exists( 'PLL_Share_Term_Slug' ) ) {
|
95 |
+
$this->share_term_slug = version_compare( $GLOBALS['wp_version'], '4.8', '<' ) ?
|
96 |
+
new PLL_Frontend_Share_Term_Slug( $this ) :
|
97 |
+
new PLL_Share_Term_Slug( $this );
|
98 |
+
}
|
99 |
}
|
100 |
}
|
101 |
|
160 |
|
161 |
// Remove pages query when the language is set unless we do a search
|
162 |
// Take care not to break the single page, attachment and taxonomies queries!
|
163 |
+
if ( empty( $qv['post_type'] ) && ! $query->is_search && ! $query->is_singular && empty( $taxonomies ) ) {
|
164 |
$query->set( 'post_type', 'post' );
|
165 |
}
|
166 |
|
include/api.php
CHANGED
@@ -123,7 +123,7 @@ function pll_register_string( $name, $string, $context = 'polylang', $multiline
|
|
123 |
* @return string the string translation in the current language
|
124 |
*/
|
125 |
function pll__( $string ) {
|
126 |
-
return is_scalar( $string ) ? __( $string, 'pll_string' ) : $string; // PHPCS:ignore WordPress.WP.I18n
|
127 |
}
|
128 |
|
129 |
/**
|
@@ -152,13 +152,14 @@ function pll_esc_attr__( $string ) {
|
|
152 |
|
153 |
/**
|
154 |
* Echoes a translated string ( previously registered with pll_register_string )
|
|
|
155 |
*
|
156 |
* @since 0.6
|
157 |
*
|
158 |
* @param string $string The string to translate
|
159 |
*/
|
160 |
function pll_e( $string ) {
|
161 |
-
echo pll__( $string );
|
162 |
}
|
163 |
|
164 |
/**
|
@@ -169,7 +170,7 @@ function pll_e( $string ) {
|
|
169 |
* @param string $string The string to translate
|
170 |
*/
|
171 |
function pll_esc_html_e( $string ) {
|
172 |
-
echo pll_esc_html__( $string );
|
173 |
}
|
174 |
|
175 |
/**
|
@@ -180,7 +181,7 @@ function pll_esc_html_e( $string ) {
|
|
180 |
* @param string $string The string to translate
|
181 |
*/
|
182 |
function pll_esc_attr_e( $string ) {
|
183 |
-
echo pll_esc_attr__( $string );
|
184 |
}
|
185 |
|
186 |
/**
|
123 |
* @return string the string translation in the current language
|
124 |
*/
|
125 |
function pll__( $string ) {
|
126 |
+
return is_scalar( $string ) ? __( $string, 'pll_string' ) : $string; // PHPCS:ignore WordPress.WP.I18n
|
127 |
}
|
128 |
|
129 |
/**
|
152 |
|
153 |
/**
|
154 |
* Echoes a translated string ( previously registered with pll_register_string )
|
155 |
+
* It is an equivalent of _e() and is not escaped.
|
156 |
*
|
157 |
* @since 0.6
|
158 |
*
|
159 |
* @param string $string The string to translate
|
160 |
*/
|
161 |
function pll_e( $string ) {
|
162 |
+
echo pll__( $string ); // phpcs:ignore
|
163 |
}
|
164 |
|
165 |
/**
|
170 |
* @param string $string The string to translate
|
171 |
*/
|
172 |
function pll_esc_html_e( $string ) {
|
173 |
+
echo pll_esc_html__( $string ); // phpcs:ignore WordPress.Security.EscapeOutput
|
174 |
}
|
175 |
|
176 |
/**
|
181 |
* @param string $string The string to translate
|
182 |
*/
|
183 |
function pll_esc_attr_e( $string ) {
|
184 |
+
echo pll_esc_attr__( $string ); // phpcs:ignore WordPress.Security.EscapeOutput
|
185 |
}
|
186 |
|
187 |
/**
|
include/base.php
CHANGED
@@ -32,6 +32,30 @@ abstract class PLL_Base {
|
|
32 |
add_action( 'switch_blog', array( $this, 'switch_blog' ), 10, 2 );
|
33 |
}
|
34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
/**
|
36 |
* Registers our widgets
|
37 |
*
|
@@ -110,15 +134,15 @@ abstract class PLL_Base {
|
|
110 |
foreach ( $this as $prop => &$obj ) {
|
111 |
if ( is_object( $obj ) && method_exists( $obj, $func ) ) {
|
112 |
if ( WP_DEBUG ) {
|
113 |
-
$debug = debug_backtrace();
|
114 |
$i = 1 + empty( $debug[1]['line'] ); // The file and line are in $debug[2] if the function was called using call_user_func
|
115 |
-
trigger_error(
|
116 |
sprintf(
|
117 |
'%1$s was called incorrectly in %3$s on line %4$s: the call to $polylang->%1$s() has been deprecated in Polylang 1.2, use PLL()->%2$s->%1$s() instead.' . "\nError handler",
|
118 |
-
$func,
|
119 |
-
$prop,
|
120 |
-
$debug[ $i ]['file'],
|
121 |
-
$debug[ $i ]['line']
|
122 |
)
|
123 |
);
|
124 |
}
|
@@ -126,7 +150,15 @@ abstract class PLL_Base {
|
|
126 |
}
|
127 |
}
|
128 |
|
129 |
-
$debug = debug_backtrace();
|
130 |
-
trigger_error(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
}
|
132 |
}
|
32 |
add_action( 'switch_blog', array( $this, 'switch_blog' ), 10, 2 );
|
33 |
}
|
34 |
|
35 |
+
/**
|
36 |
+
* Instantiate classes always needed
|
37 |
+
*
|
38 |
+
* @since 2.6
|
39 |
+
*/
|
40 |
+
public function init() {
|
41 |
+
// REST API
|
42 |
+
if ( class_exists( 'PLL_REST_API' ) ) {
|
43 |
+
$this->rest_api = new PLL_REST_API( $this );
|
44 |
+
}
|
45 |
+
|
46 |
+
if ( $this->model->get_languages_list() ) {
|
47 |
+
// Active languages
|
48 |
+
if ( class_exists( 'PLL_Active_Languages' ) ) {
|
49 |
+
$this->active_languages = new PLL_Active_Languages( $this );
|
50 |
+
}
|
51 |
+
|
52 |
+
// Share post slugs
|
53 |
+
if ( get_option( 'permalink_structure' ) && $this->options['force_lang'] && class_exists( 'PLL_Share_Post_Slug' ) ) {
|
54 |
+
$this->share_post_slug = new PLL_Share_Post_Slug( $this );
|
55 |
+
}
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
/**
|
60 |
* Registers our widgets
|
61 |
*
|
134 |
foreach ( $this as $prop => &$obj ) {
|
135 |
if ( is_object( $obj ) && method_exists( $obj, $func ) ) {
|
136 |
if ( WP_DEBUG ) {
|
137 |
+
$debug = debug_backtrace(); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
138 |
$i = 1 + empty( $debug[1]['line'] ); // The file and line are in $debug[2] if the function was called using call_user_func
|
139 |
+
trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
140 |
sprintf(
|
141 |
'%1$s was called incorrectly in %3$s on line %4$s: the call to $polylang->%1$s() has been deprecated in Polylang 1.2, use PLL()->%2$s->%1$s() instead.' . "\nError handler",
|
142 |
+
esc_html( $func ),
|
143 |
+
esc_html( $prop ),
|
144 |
+
esc_html( $debug[ $i ]['file'] ),
|
145 |
+
absint( $debug[ $i ]['line'] )
|
146 |
)
|
147 |
);
|
148 |
}
|
150 |
}
|
151 |
}
|
152 |
|
153 |
+
$debug = debug_backtrace(); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
154 |
+
trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
155 |
+
sprintf(
|
156 |
+
'Call to undefined function PLL()->%1$s() in %2$s on line %3$s' . "\nError handler",
|
157 |
+
esc_html( $func ),
|
158 |
+
esc_html( $debug[0]['file'] ),
|
159 |
+
absint( $debug[0]['line'] )
|
160 |
+
),
|
161 |
+
E_USER_ERROR
|
162 |
+
);
|
163 |
}
|
164 |
}
|
include/class-polylang.php
CHANGED
@@ -68,18 +68,32 @@ class Polylang {
|
|
68 |
}
|
69 |
|
70 |
$class = str_replace( '_', '-', strtolower( substr( $class, 4 ) ) );
|
71 |
-
$
|
72 |
-
$
|
73 |
-
|
74 |
-
$
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
);
|
84 |
|
85 |
foreach ( $dirs as $dir ) {
|
@@ -100,8 +114,8 @@ class Polylang {
|
|
100 |
public static function is_ajax_on_front() {
|
101 |
// Special test for plupload which does not use jquery ajax and thus does not pass our ajax prefilter
|
102 |
// Special test for customize_save done in frontend but for which we want to load the admin
|
103 |
-
$in = isset( $_REQUEST['action'] ) && in_array( $_REQUEST['action'], array( 'upload-attachment', 'customize_save' ) );
|
104 |
-
$is_ajax_on_front = wp_doing_ajax() && empty( $_REQUEST['pll_ajax_backend'] ) && ! $in;
|
105 |
|
106 |
/**
|
107 |
* Filters whether the current request is an ajax request on front.
|
@@ -113,6 +127,28 @@ class Polylang {
|
|
113 |
return apply_filters( 'pll_is_ajax_on_front', $is_ajax_on_front );
|
114 |
}
|
115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
/**
|
117 |
* Defines constants
|
118 |
* May be overridden by a plugin if set before plugins_loaded, 1
|
@@ -132,12 +168,12 @@ class Polylang {
|
|
132 |
|
133 |
// Admin
|
134 |
if ( ! defined( 'PLL_ADMIN' ) ) {
|
135 |
-
define( 'PLL_ADMIN',
|
136 |
}
|
137 |
|
138 |
// Settings page whatever the tab
|
139 |
if ( ! defined( 'PLL_SETTINGS' ) ) {
|
140 |
-
define( 'PLL_SETTINGS', is_admin() && ( ( isset( $_GET['page'] ) && 0 === strpos( $_GET['page'], 'mlang' ) ) || ! empty( $_REQUEST['pll_ajax_settings'] ) ) );
|
141 |
}
|
142 |
}
|
143 |
|
@@ -176,17 +212,6 @@ class Polylang {
|
|
176 |
$model = new $class( $options );
|
177 |
$links_model = $model->get_links_model();
|
178 |
|
179 |
-
if ( PLL_SETTINGS ) {
|
180 |
-
$polylang = new PLL_Settings( $links_model );
|
181 |
-
}
|
182 |
-
elseif ( PLL_ADMIN ) {
|
183 |
-
$polylang = new PLL_Admin( $links_model );
|
184 |
-
}
|
185 |
-
// Do nothing on frontend if no language is defined
|
186 |
-
elseif ( $model->get_languages_list() && empty( $_GET['deactivate-polylang'] ) ) {
|
187 |
-
$polylang = new PLL_Frontend( $links_model );
|
188 |
-
}
|
189 |
-
|
190 |
if ( ! $model->get_languages_list() ) {
|
191 |
/**
|
192 |
* Fires when no language has been defined yet
|
@@ -197,7 +222,30 @@ class Polylang {
|
|
197 |
do_action( 'pll_no_language_defined' );
|
198 |
}
|
199 |
|
200 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
/**
|
202 |
* Fires after the $polylang object is created and before the API is loaded
|
203 |
*
|
@@ -227,5 +275,3 @@ class Polylang {
|
|
227 |
}
|
228 |
}
|
229 |
}
|
230 |
-
|
231 |
-
new Polylang();
|
68 |
}
|
69 |
|
70 |
$class = str_replace( '_', '-', strtolower( substr( $class, 4 ) ) );
|
71 |
+
$dirs = array();
|
72 |
+
$parts = explode( '-', $class );
|
73 |
+
$parts = array_values( array_diff( $parts, array( 'frontend', 'admin', 'settings', 'advanced' ) ) );
|
74 |
+
if ( isset( $parts[0] ) ) {
|
75 |
+
$dirs[] = PLL_MODULES_INC . "/{$parts[0]}";
|
76 |
+
if ( isset( $parts[1] ) ) {
|
77 |
+
$dirs[] = PLL_MODULES_INC . "/{$parts[0]}-{$parts[1]}";
|
78 |
+
if ( isset( $parts[2] ) && in_array( $parts[1], array( 'post', 'term' ) ) ) {
|
79 |
+
$dirs[] = PLL_MODULES_INC . "/{$parts[0]}-{$parts[2]}";
|
80 |
+
}
|
81 |
+
}
|
82 |
+
}
|
83 |
+
|
84 |
+
$dirs = array_merge(
|
85 |
+
array(
|
86 |
+
PLL_FRONT_INC,
|
87 |
+
PLL_MODULES_INC,
|
88 |
+
),
|
89 |
+
$dirs,
|
90 |
+
array(
|
91 |
+
PLL_MODULES_INC . '/plugins',
|
92 |
+
PLL_INSTALL_INC,
|
93 |
+
PLL_ADMIN_INC,
|
94 |
+
PLL_SETTINGS_INC,
|
95 |
+
PLL_INC,
|
96 |
+
)
|
97 |
);
|
98 |
|
99 |
foreach ( $dirs as $dir ) {
|
114 |
public static function is_ajax_on_front() {
|
115 |
// Special test for plupload which does not use jquery ajax and thus does not pass our ajax prefilter
|
116 |
// Special test for customize_save done in frontend but for which we want to load the admin
|
117 |
+
$in = isset( $_REQUEST['action'] ) && in_array( sanitize_key( $_REQUEST['action'] ), array( 'upload-attachment', 'customize_save' ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
118 |
+
$is_ajax_on_front = wp_doing_ajax() && empty( $_REQUEST['pll_ajax_backend'] ) && ! $in; // phpcs:ignore WordPress.Security.NonceVerification
|
119 |
|
120 |
/**
|
121 |
* Filters whether the current request is an ajax request on front.
|
127 |
return apply_filters( 'pll_is_ajax_on_front', $is_ajax_on_front );
|
128 |
}
|
129 |
|
130 |
+
/**
|
131 |
+
* Is the current request a REST API request?
|
132 |
+
* Inspired by WP::parse_request()
|
133 |
+
* Needed because at this point, the constant REST_REQUEST is not defined yet
|
134 |
+
*
|
135 |
+
* @since 2.4.1
|
136 |
+
*
|
137 |
+
* @return bool
|
138 |
+
*/
|
139 |
+
public static function is_rest_request() {
|
140 |
+
$home_path = trim( wp_parse_url( home_url(), PHP_URL_PATH ), '/' );
|
141 |
+
$home_path_regex = sprintf( '|^%s|i', preg_quote( $home_path, '|' ) );
|
142 |
+
|
143 |
+
$req_uri = trim( wp_parse_url( pll_get_requested_url(), PHP_URL_PATH ), '/' );
|
144 |
+
$req_uri = preg_replace( $home_path_regex, '', $req_uri );
|
145 |
+
$req_uri = trim( $req_uri, '/' );
|
146 |
+
$req_uri = str_replace( 'index.php', '', $req_uri );
|
147 |
+
$req_uri = trim( $req_uri, '/' );
|
148 |
+
|
149 |
+
return 0 === strpos( $req_uri, rest_get_url_prefix() . '/' );
|
150 |
+
}
|
151 |
+
|
152 |
/**
|
153 |
* Defines constants
|
154 |
* May be overridden by a plugin if set before plugins_loaded, 1
|
168 |
|
169 |
// Admin
|
170 |
if ( ! defined( 'PLL_ADMIN' ) ) {
|
171 |
+
define( 'PLL_ADMIN', wp_doing_cron() || ( defined( 'WP_CLI' ) && WP_CLI ) || ( is_admin() && ! PLL_AJAX_ON_FRONT ) );
|
172 |
}
|
173 |
|
174 |
// Settings page whatever the tab
|
175 |
if ( ! defined( 'PLL_SETTINGS' ) ) {
|
176 |
+
define( 'PLL_SETTINGS', is_admin() && ( ( isset( $_GET['page'] ) && 0 === strpos( sanitize_key( $_GET['page'] ), 'mlang' ) ) || ! empty( $_REQUEST['pll_ajax_settings'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
177 |
}
|
178 |
}
|
179 |
|
212 |
$model = new $class( $options );
|
213 |
$links_model = $model->get_links_model();
|
214 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
if ( ! $model->get_languages_list() ) {
|
216 |
/**
|
217 |
* Fires when no language has been defined yet
|
222 |
do_action( 'pll_no_language_defined' );
|
223 |
}
|
224 |
|
225 |
+
$class = '';
|
226 |
+
|
227 |
+
if ( PLL_SETTINGS ) {
|
228 |
+
$class = 'PLL_Settings';
|
229 |
+
} elseif ( PLL_ADMIN ) {
|
230 |
+
$class = 'PLL_Admin';
|
231 |
+
} elseif ( self::is_rest_request() ) {
|
232 |
+
$class = 'PLL_REST_Request';
|
233 |
+
} elseif ( $model->get_languages_list() && empty( $_GET['deactivate-polylang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
234 |
+
$class = 'PLL_Frontend';
|
235 |
+
}
|
236 |
+
|
237 |
+
/**
|
238 |
+
* Filters the class to use to instantiate the $polylang object
|
239 |
+
*
|
240 |
+
* @since 2.6
|
241 |
+
*
|
242 |
+
* @param string $class A class name.
|
243 |
+
*/
|
244 |
+
$class = apply_filters( 'pll_context', $class );
|
245 |
+
|
246 |
+
if ( ! empty( $class ) ) {
|
247 |
+
$polylang = new $class( $links_model );
|
248 |
+
|
249 |
/**
|
250 |
* Fires after the $polylang object is created and before the API is loaded
|
251 |
*
|
275 |
}
|
276 |
}
|
277 |
}
|
|
|
|
include/crud-posts.php
CHANGED
@@ -42,10 +42,10 @@ class PLL_CRUD_Posts {
|
|
42 |
*/
|
43 |
public function set_default_language( $post_id ) {
|
44 |
if ( ! $this->model->post->get_language( $post_id ) ) {
|
45 |
-
if ( ! empty( $_GET['new_lang'] ) && $lang = $this->model->get_language( $_GET['new_lang'] ) ) {
|
46 |
// Defined only on admin.
|
47 |
$this->model->post->set_language( $post_id, $lang );
|
48 |
-
} elseif ( ! isset( $this->pref_lang ) && ! empty( $_REQUEST['lang'] ) && $lang = $this->model->get_language( $_REQUEST['lang'] ) ) {
|
49 |
// Testing $this->pref_lang makes this test pass only on admin.
|
50 |
$this->model->post->set_language( $post_id, $lang );
|
51 |
} elseif ( ( $parent_id = wp_get_post_parent_id( $post_id ) ) && $parent_lang = $this->model->post->get_language( $parent_id ) ) {
|
@@ -260,13 +260,13 @@ class PLL_CRUD_Posts {
|
|
260 |
$post->ID = null; // Will force the creation
|
261 |
$post->post_parent = ( $post->post_parent && $tr_parent = $this->model->post->get_translation( $post->post_parent, $lang->slug ) ) ? $tr_parent : 0;
|
262 |
$post->tax_input = array( 'language' => array( $lang->slug ) ); // Assigns the language
|
263 |
-
$tr_id = wp_insert_attachment( $post );
|
264 |
remove_filter( 'pll_enable_duplicate_media', '__return_false', 99 ); // Restore automatic duplicate at upload
|
265 |
|
266 |
// Copy metadata, attached file and alternative text
|
267 |
foreach ( array( '_wp_attachment_metadata', '_wp_attached_file', '_wp_attachment_image_alt' ) as $key ) {
|
268 |
if ( $meta = get_post_meta( $post_id, $key, true ) ) {
|
269 |
-
add_post_meta( $tr_id, $key, $meta );
|
270 |
}
|
271 |
}
|
272 |
|
42 |
*/
|
43 |
public function set_default_language( $post_id ) {
|
44 |
if ( ! $this->model->post->get_language( $post_id ) ) {
|
45 |
+
if ( ! empty( $_GET['new_lang'] ) && $lang = $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
46 |
// Defined only on admin.
|
47 |
$this->model->post->set_language( $post_id, $lang );
|
48 |
+
} elseif ( ! isset( $this->pref_lang ) && ! empty( $_REQUEST['lang'] ) && $lang = $this->model->get_language( sanitize_key( $_REQUEST['lang'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
49 |
// Testing $this->pref_lang makes this test pass only on admin.
|
50 |
$this->model->post->set_language( $post_id, $lang );
|
51 |
} elseif ( ( $parent_id = wp_get_post_parent_id( $post_id ) ) && $parent_lang = $this->model->post->get_language( $parent_id ) ) {
|
260 |
$post->ID = null; // Will force the creation
|
261 |
$post->post_parent = ( $post->post_parent && $tr_parent = $this->model->post->get_translation( $post->post_parent, $lang->slug ) ) ? $tr_parent : 0;
|
262 |
$post->tax_input = array( 'language' => array( $lang->slug ) ); // Assigns the language
|
263 |
+
$tr_id = wp_insert_attachment( wp_slash( (array) $post ) );
|
264 |
remove_filter( 'pll_enable_duplicate_media', '__return_false', 99 ); // Restore automatic duplicate at upload
|
265 |
|
266 |
// Copy metadata, attached file and alternative text
|
267 |
foreach ( array( '_wp_attachment_metadata', '_wp_attached_file', '_wp_attachment_image_alt' ) as $key ) {
|
268 |
if ( $meta = get_post_meta( $post_id, $key, true ) ) {
|
269 |
+
add_post_meta( $tr_id, $key, wp_slash( $meta ) );
|
270 |
}
|
271 |
}
|
272 |
|
include/crud-terms.php
CHANGED
@@ -49,7 +49,7 @@ class PLL_CRUD_Terms {
|
|
49 |
*/
|
50 |
protected function set_default_language( $term_id, $taxonomy ) {
|
51 |
if ( ! $this->model->term->get_language( $term_id ) ) {
|
52 |
-
if ( ! isset( $this->pref_lang ) && ! empty( $_REQUEST['lang'] ) && $lang = $this->model->get_language( $_REQUEST['lang'] ) ) {
|
53 |
// Testing $this->pref_lang makes this test pass only on frontend.
|
54 |
$this->model->term->set_language( $term_id, $lang );
|
55 |
} elseif ( ( $term = get_term( $term_id, $taxonomy ) ) && ! empty( $term->parent ) && $parent_lang = $this->model->term->get_language( $term->parent ) ) {
|
49 |
*/
|
50 |
protected function set_default_language( $term_id, $taxonomy ) {
|
51 |
if ( ! $this->model->term->get_language( $term_id ) ) {
|
52 |
+
if ( ! isset( $this->pref_lang ) && ! empty( $_REQUEST['lang'] ) && $lang = $this->model->get_language( sanitize_key( $_REQUEST['lang'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
53 |
// Testing $this->pref_lang makes this test pass only on frontend.
|
54 |
$this->model->term->set_language( $term_id, $lang );
|
55 |
} elseif ( ( $term = get_term( $term_id, $taxonomy ) ) && ! empty( $term->parent ) && $parent_lang = $this->model->term->get_language( $term->parent ) ) {
|
include/filters.php
CHANGED
@@ -353,7 +353,7 @@ class PLL_Filters {
|
|
353 |
if ( ! empty( $user_data_to_export ) ) {
|
354 |
$data_to_export[] = array(
|
355 |
'group_id' => 'user',
|
356 |
-
'group_label' => __( 'User' ),
|
357 |
'item_id' => "user-{$user->ID}",
|
358 |
'data' => $user_data_to_export,
|
359 |
);
|
353 |
if ( ! empty( $user_data_to_export ) ) {
|
354 |
$data_to_export[] = array(
|
355 |
'group_id' => 'user',
|
356 |
+
'group_label' => __( 'User', 'polylang' ),
|
357 |
'item_id' => "user-{$user->ID}",
|
358 |
'data' => $user_data_to_export,
|
359 |
);
|
include/functions.php
CHANGED
@@ -84,6 +84,36 @@ if ( ! function_exists( 'wp_doing_ajax' ) ) {
|
|
84 |
}
|
85 |
}
|
86 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
/**
|
88 |
* Determines whether we should load the cache compatibility
|
89 |
*
|
@@ -102,3 +132,41 @@ function pll_is_cache_active() {
|
|
102 |
*/
|
103 |
return apply_filters( 'pll_is_cache_active', ( defined( 'WP_CACHE' ) && WP_CACHE ) || defined( 'WPFC_MAIN_PATH' ) );
|
104 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
84 |
}
|
85 |
}
|
86 |
|
87 |
+
if ( ! function_exists( 'wp_doing_cron' ) ) {
|
88 |
+
/**
|
89 |
+
* Determines whether the current request is a WordPress cron request.
|
90 |
+
* Backward compatibility function for WP < 4.8
|
91 |
+
*
|
92 |
+
* @since 2.6
|
93 |
+
*
|
94 |
+
* @return bool True if it's a WordPress cron request, false otherwise.
|
95 |
+
*/
|
96 |
+
function wp_doing_cron() {
|
97 |
+
/** This filter is documented in wp-includes/load.php */
|
98 |
+
return apply_filters( 'wp_doing_cron', defined( 'DOING_CRON' ) && DOING_CRON );
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
if ( ! function_exists( 'wp_using_themes' ) ) {
|
103 |
+
/**
|
104 |
+
* Determines whether the current request should use themes.
|
105 |
+
* Backward compatibility function for WP < 5.1
|
106 |
+
*
|
107 |
+
* @since 2.6
|
108 |
+
*
|
109 |
+
* @return bool True if themes should be used, false otherwise.
|
110 |
+
*/
|
111 |
+
function wp_using_themes() {
|
112 |
+
/** This filter is documented in wp-includes/load.php */
|
113 |
+
return apply_filters( 'wp_using_themes', defined( 'WP_USE_THEMES' ) && WP_USE_THEMES );
|
114 |
+
}
|
115 |
+
}
|
116 |
+
|
117 |
/**
|
118 |
* Determines whether we should load the cache compatibility
|
119 |
*
|
132 |
*/
|
133 |
return apply_filters( 'pll_is_cache_active', ( defined( 'WP_CACHE' ) && WP_CACHE ) || defined( 'WPFC_MAIN_PATH' ) );
|
134 |
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Get the the current requested url
|
138 |
+
*
|
139 |
+
* @since 2.6
|
140 |
+
*
|
141 |
+
* @return string Requested url
|
142 |
+
*/
|
143 |
+
function pll_get_requested_url() {
|
144 |
+
if ( isset( $_SERVER['HTTP_HOST'], $_SERVER['REQUEST_URI'] ) ) {
|
145 |
+
return set_url_scheme( esc_url_raw( wp_unslash( 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] ) ) );
|
146 |
+
}
|
147 |
+
|
148 |
+
if ( WP_DEBUG ) {
|
149 |
+
// phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
150 |
+
trigger_error( '$_SERVER[\'HTTP_HOST\'] or $_SERVER[\'REQUEST_URI\'] are required but not set.' );
|
151 |
+
}
|
152 |
+
|
153 |
+
return '';
|
154 |
+
}
|
155 |
+
|
156 |
+
/**
|
157 |
+
* Determines whether we should load the block editor plugin or the legacy languages metabox.
|
158 |
+
*
|
159 |
+
* @since 2.6.0
|
160 |
+
*
|
161 |
+
* return bool True to use the block editor plugin.
|
162 |
+
*/
|
163 |
+
function pll_use_block_editor_plugin() {
|
164 |
+
/**
|
165 |
+
* Filters whether we should load the block editor plugin or the legacy languages metabox.
|
166 |
+
*
|
167 |
+
* @since 2.6.0
|
168 |
+
*
|
169 |
+
* @param bool $use_plugin True when loading the block editor plugin.
|
170 |
+
*/
|
171 |
+
return class_exists( 'PLL_Block_Editor_Plugin' ) && apply_filters( 'pll_use_block_editor_plugin', ! defined( 'PLL_USE_BLOCK_EDITOR_PLUGIN' ) || PLL_USE_BLOCK_EDITOR_PLUGIN );
|
172 |
+
}
|
include/language.php
CHANGED
@@ -81,7 +81,7 @@ class PLL_Language {
|
|
81 |
|
82 |
$this->mo_id = PLL_MO::get_id( $this );
|
83 |
|
84 |
-
include PLL_SETTINGS_INC . '/languages.php';
|
85 |
$this->w3c = isset( $languages[ $this->locale ]['w3c'] ) ? $languages[ $this->locale ]['w3c'] : str_replace( '_', '-', $this->locale );
|
86 |
if ( isset( $languages[ $this->locale ]['facebook'] ) ) {
|
87 |
$this->facebook = $languages[ $this->locale ]['facebook'];
|
@@ -90,16 +90,23 @@ class PLL_Language {
|
|
90 |
}
|
91 |
|
92 |
/**
|
93 |
-
*
|
|
|
|
|
|
|
|
|
94 |
*
|
95 |
-
* @since
|
|
|
|
|
|
|
96 |
*/
|
97 |
-
public function
|
98 |
-
$
|
99 |
|
100 |
// Polylang builtin flags
|
101 |
-
if ( ! empty( $
|
102 |
-
$
|
103 |
}
|
104 |
|
105 |
/**
|
@@ -114,18 +121,31 @@ class PLL_Language {
|
|
114 |
* @param array $flag Information about the flag
|
115 |
* @param string $code Flag code
|
116 |
*/
|
117 |
-
$
|
118 |
|
119 |
-
if ( empty( $
|
120 |
// If using predefined flags and base64 encoded flags are preferred
|
121 |
-
if ( isset( $_url ) && $
|
122 |
-
$
|
|
|
|
|
123 |
} else {
|
124 |
-
$
|
125 |
}
|
126 |
}
|
127 |
|
128 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
|
130 |
// Custom flags ?
|
131 |
$directories = array(
|
81 |
|
82 |
$this->mo_id = PLL_MO::get_id( $this );
|
83 |
|
84 |
+
$languages = include PLL_SETTINGS_INC . '/languages.php';
|
85 |
$this->w3c = isset( $languages[ $this->locale ]['w3c'] ) ? $languages[ $this->locale ]['w3c'] : str_replace( '_', '-', $this->locale );
|
86 |
if ( isset( $languages[ $this->locale ]['facebook'] ) ) {
|
87 |
$this->facebook = $languages[ $this->locale ]['facebook'];
|
90 |
}
|
91 |
|
92 |
/**
|
93 |
+
* Get the flag informations
|
94 |
+
* 'url' => Flag url
|
95 |
+
* 'src' => Optional, src attribute value if different of the url, for example if base64 encoded
|
96 |
+
* 'width' => Optional, flag width in pixels
|
97 |
+
* 'height' => Optional, flag height in pixels
|
98 |
*
|
99 |
+
* @since 2.6
|
100 |
+
*
|
101 |
+
* @param string $code Flag code.
|
102 |
+
* @return array Flag informations.
|
103 |
*/
|
104 |
+
public static function get_flag_informations( $code ) {
|
105 |
+
$flag['url'] = '';
|
106 |
|
107 |
// Polylang builtin flags
|
108 |
+
if ( ! empty( $code ) && file_exists( POLYLANG_DIR . ( $file = '/flags/' . $code . '.png' ) ) ) {
|
109 |
+
$flag['url'] = $_url = plugins_url( $file, POLYLANG_FILE );
|
110 |
}
|
111 |
|
112 |
/**
|
121 |
* @param array $flag Information about the flag
|
122 |
* @param string $code Flag code
|
123 |
*/
|
124 |
+
$flag = apply_filters( 'pll_flag', $flag, $code );
|
125 |
|
126 |
+
if ( empty( $flag['src'] ) ) {
|
127 |
// If using predefined flags and base64 encoded flags are preferred
|
128 |
+
if ( isset( $_url ) && $flag['url'] === $_url && ( ! defined( 'PLL_ENCODED_FLAGS' ) || PLL_ENCODED_FLAGS ) ) {
|
129 |
+
list( $flag['width'], $flag['height'] ) = getimagesize( POLYLANG_DIR . $file );
|
130 |
+
$file_contents = file_get_contents( POLYLANG_DIR . $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
|
131 |
+
$flag['src'] = 'data:image/png;base64,' . base64_encode( $file_contents ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
|
132 |
} else {
|
133 |
+
$flag['src'] = esc_url( set_url_scheme( $flag['url'], 'relative' ) );
|
134 |
}
|
135 |
}
|
136 |
|
137 |
+
$flag['url'] = esc_url_raw( $flag['url'] );
|
138 |
+
|
139 |
+
return $flag;
|
140 |
+
}
|
141 |
+
|
142 |
+
/**
|
143 |
+
* Sets flag_url and flag properties
|
144 |
+
*
|
145 |
+
* @since 1.2
|
146 |
+
*/
|
147 |
+
public function set_flag() {
|
148 |
+
$flags['flag'] = self::get_flag_informations( $this->flag_code );
|
149 |
|
150 |
// Custom flags ?
|
151 |
$directories = array(
|
include/links-abstract-domain.php
CHANGED
@@ -36,7 +36,11 @@ abstract class PLL_Links_Abstract_Domain extends PLL_Links_Permalinks {
|
|
36 |
* @return string language slug
|
37 |
*/
|
38 |
public function get_language_from_url( $url = '' ) {
|
39 |
-
|
|
|
|
|
|
|
|
|
40 |
return ( $lang = array_search( $host, $this->get_hosts() ) ) ? $lang : '';
|
41 |
}
|
42 |
|
36 |
* @return string language slug
|
37 |
*/
|
38 |
public function get_language_from_url( $url = '' ) {
|
39 |
+
if ( empty( $url ) ) {
|
40 |
+
$url = pll_get_requested_url();
|
41 |
+
}
|
42 |
+
|
43 |
+
$host = wp_parse_url( $url, PHP_URL_HOST );
|
44 |
return ( $lang = array_search( $host, $this->get_hosts() ) ) ? $lang : '';
|
45 |
}
|
46 |
|
include/links-default.php
CHANGED
@@ -75,7 +75,7 @@ class PLL_Links_Default extends PLL_Links_Model {
|
|
75 |
*/
|
76 |
public function get_language_from_url( $url = '' ) {
|
77 |
if ( empty( $url ) ) {
|
78 |
-
$url =
|
79 |
}
|
80 |
|
81 |
$pattern = '#lang=(' . implode( '|', $this->model->get_languages_list( array( 'fields' => 'slug' ) ) ) . ')#';
|
75 |
*/
|
76 |
public function get_language_from_url( $url = '' ) {
|
77 |
if ( empty( $url ) ) {
|
78 |
+
$url = pll_get_requested_url();
|
79 |
}
|
80 |
|
81 |
$pattern = '#lang=(' . implode( '|', $this->model->get_languages_list( array( 'fields' => 'slug' ) ) ) . ')#';
|
include/links-directory.php
CHANGED
@@ -59,7 +59,7 @@ class PLL_Links_Directory extends PLL_Links_Permalinks {
|
|
59 |
if ( ! empty( $lang ) ) {
|
60 |
$base = $this->options['rewrite'] ? '' : 'language/';
|
61 |
$slug = $this->options['default_lang'] == $lang->slug && $this->options['hide_default'] ? '' : $base . $lang->slug . '/';
|
62 |
-
$root = ( false === strpos( $url, '://' ) ) ? $this->home_relative . $this->root : $this->home . '/' . $this->root;
|
63 |
|
64 |
if ( false === strpos( $url, $new = $root . $slug ) ) {
|
65 |
$pattern = str_replace( '/', '\/', $root );
|
@@ -87,7 +87,7 @@ class PLL_Links_Directory extends PLL_Links_Permalinks {
|
|
87 |
}
|
88 |
|
89 |
if ( ! empty( $languages ) ) {
|
90 |
-
$root = ( false === strpos( $url, '://' ) ) ? $this->home_relative . $this->root : $this->home . '/' . $this->root;
|
91 |
|
92 |
$pattern = str_replace( '/', '\/', $root );
|
93 |
$pattern = '#' . $pattern . ( $this->options['rewrite'] ? '' : 'language\/' ) . '(' . implode( '|', $languages ) . ')(\/|$)#';
|
@@ -108,14 +108,13 @@ class PLL_Links_Directory extends PLL_Links_Permalinks {
|
|
108 |
*/
|
109 |
public function get_language_from_url( $url = '' ) {
|
110 |
if ( empty( $url ) ) {
|
111 |
-
$
|
112 |
-
} else {
|
113 |
-
$path = parse_url( $url, PHP_URL_PATH );
|
114 |
}
|
115 |
|
|
|
116 |
$root = ( false === strpos( $url, '://' ) ) ? $this->home_relative . $this->root : $this->home . '/' . $this->root;
|
117 |
|
118 |
-
$pattern =
|
119 |
$pattern = str_replace( '/', '\/', $pattern );
|
120 |
$pattern = '#' . $pattern . '(' . implode( '|', $this->model->get_languages_list( array( 'fields' => 'slug' ) ) ) . ')(\/|$)#';
|
121 |
return preg_match( $pattern, trailingslashit( $path ), $matches ) ? $matches[1] : ''; // $matches[1] is the slug of the requested language
|
59 |
if ( ! empty( $lang ) ) {
|
60 |
$base = $this->options['rewrite'] ? '' : 'language/';
|
61 |
$slug = $this->options['default_lang'] == $lang->slug && $this->options['hide_default'] ? '' : $base . $lang->slug . '/';
|
62 |
+
$root = ( false === strpos( $url, '://' ) ) ? $this->home_relative . $this->root : preg_replace( '/^https?:\/\//', '://', $this->home . '/' . $this->root );
|
63 |
|
64 |
if ( false === strpos( $url, $new = $root . $slug ) ) {
|
65 |
$pattern = str_replace( '/', '\/', $root );
|
87 |
}
|
88 |
|
89 |
if ( ! empty( $languages ) ) {
|
90 |
+
$root = ( false === strpos( $url, '://' ) ) ? $this->home_relative . $this->root : preg_replace( '/^https?:\/\//', '://', $this->home . '/' . $this->root );
|
91 |
|
92 |
$pattern = str_replace( '/', '\/', $root );
|
93 |
$pattern = '#' . $pattern . ( $this->options['rewrite'] ? '' : 'language\/' ) . '(' . implode( '|', $languages ) . ')(\/|$)#';
|
108 |
*/
|
109 |
public function get_language_from_url( $url = '' ) {
|
110 |
if ( empty( $url ) ) {
|
111 |
+
$url = pll_get_requested_url();
|
|
|
|
|
112 |
}
|
113 |
|
114 |
+
$path = wp_parse_url( $url, PHP_URL_PATH );
|
115 |
$root = ( false === strpos( $url, '://' ) ) ? $this->home_relative . $this->root : $this->home . '/' . $this->root;
|
116 |
|
117 |
+
$pattern = wp_parse_url( $root . ( $this->options['rewrite'] ? '' : 'language/' ), PHP_URL_PATH );
|
118 |
$pattern = str_replace( '/', '\/', $pattern );
|
119 |
$pattern = '#' . $pattern . '(' . implode( '|', $this->model->get_languages_list( array( 'fields' => 'slug' ) ) ) . ')(\/|$)#';
|
120 |
return preg_match( $pattern, trailingslashit( $path ), $matches ) ? $matches[1] : ''; // $matches[1] is the slug of the requested language
|
include/links-domain.php
CHANGED
@@ -38,7 +38,7 @@ class PLL_Links_Domain extends PLL_Links_Abstract_Domain {
|
|
38 |
*/
|
39 |
public function add_language_to_link( $url, $lang ) {
|
40 |
if ( ! empty( $lang ) && ! empty( $this->hosts[ $lang->slug ] ) ) {
|
41 |
-
$url = preg_replace( '#:\/\/(' .
|
42 |
}
|
43 |
return $url;
|
44 |
}
|
@@ -54,7 +54,7 @@ class PLL_Links_Domain extends PLL_Links_Abstract_Domain {
|
|
54 |
*/
|
55 |
public function remove_language_from_link( $url ) {
|
56 |
if ( ! empty( $this->hosts ) ) {
|
57 |
-
$url = preg_replace( '#:\/\/(' . implode( '|', $this->hosts ) . ')($|\/.*)#', '://' .
|
58 |
}
|
59 |
return $url;
|
60 |
}
|
@@ -82,8 +82,16 @@ class PLL_Links_Domain extends PLL_Links_Abstract_Domain {
|
|
82 |
public function get_hosts() {
|
83 |
$hosts = array();
|
84 |
foreach ( $this->options['domains'] as $lang => $domain ) {
|
85 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
}
|
|
|
87 |
return $hosts;
|
88 |
}
|
89 |
}
|
38 |
*/
|
39 |
public function add_language_to_link( $url, $lang ) {
|
40 |
if ( ! empty( $lang ) && ! empty( $this->hosts[ $lang->slug ] ) ) {
|
41 |
+
$url = preg_replace( '#:\/\/(' . wp_parse_url( $this->home, PHP_URL_HOST ) . ')($|\/.*)#', '://' . $this->hosts[ $lang->slug ] . '$2', $url );
|
42 |
}
|
43 |
return $url;
|
44 |
}
|
54 |
*/
|
55 |
public function remove_language_from_link( $url ) {
|
56 |
if ( ! empty( $this->hosts ) ) {
|
57 |
+
$url = preg_replace( '#:\/\/(' . implode( '|', $this->hosts ) . ')($|\/.*)#', '://' . wp_parse_url( $this->home, PHP_URL_HOST ) . '$2', $url );
|
58 |
}
|
59 |
return $url;
|
60 |
}
|
82 |
public function get_hosts() {
|
83 |
$hosts = array();
|
84 |
foreach ( $this->options['domains'] as $lang => $domain ) {
|
85 |
+
$host = wp_parse_url( $domain, PHP_URL_HOST );
|
86 |
+
// idn_to_ascii is much faster than the WordPress method.
|
87 |
+
if ( function_exists( 'idn_to_ascii' ) ) {
|
88 |
+
// The use of the constant is mandatory in PHP 7.2 and PHP 7.3 to avoid a deprecated notice.
|
89 |
+
$hosts[ $lang ] = defined( 'INTL_IDNA_VARIANT_UTS46' ) ? idn_to_ascii( $host, 0, INTL_IDNA_VARIANT_UTS46 ) : idn_to_ascii( $host );
|
90 |
+
} else {
|
91 |
+
$hosts[ $lang ] = Requests_IDNAEncoder::encode( $host );
|
92 |
+
}
|
93 |
}
|
94 |
+
|
95 |
return $hosts;
|
96 |
}
|
97 |
}
|
include/links-model.php
CHANGED
@@ -52,7 +52,7 @@ abstract class PLL_Links_Model {
|
|
52 |
* @return array list of hosts
|
53 |
*/
|
54 |
public function get_hosts() {
|
55 |
-
return array(
|
56 |
}
|
57 |
|
58 |
/**
|
52 |
* @return array list of hosts
|
53 |
*/
|
54 |
public function get_hosts() {
|
55 |
+
return array( wp_parse_url( $this->home, PHP_URL_HOST ) );
|
56 |
}
|
57 |
|
58 |
/**
|
include/links-subdomain.php
CHANGED
@@ -72,7 +72,7 @@ class PLL_Links_Subdomain extends PLL_Links_Abstract_Domain {
|
|
72 |
public function get_hosts() {
|
73 |
$hosts = array();
|
74 |
foreach ( $this->model->get_languages_list() as $lang ) {
|
75 |
-
$hosts[ $lang->slug ] =
|
76 |
}
|
77 |
return $hosts;
|
78 |
}
|
72 |
public function get_hosts() {
|
73 |
$hosts = array();
|
74 |
foreach ( $this->model->get_languages_list() as $lang ) {
|
75 |
+
$hosts[ $lang->slug ] = wp_parse_url( $this->home_url( $lang ), PHP_URL_HOST );
|
76 |
}
|
77 |
return $hosts;
|
78 |
}
|
include/links.php
CHANGED
@@ -33,33 +33,4 @@ class PLL_Links {
|
|
33 |
$language = is_object( $language ) ? $language : $this->model->get_language( $language );
|
34 |
return $is_search ? $language->search_url : $language->home_url;
|
35 |
}
|
36 |
-
|
37 |
-
/**
|
38 |
-
* Checks if the current user can read the post
|
39 |
-
*
|
40 |
-
* @since 1.5
|
41 |
-
*
|
42 |
-
* @param int $post_id
|
43 |
-
* @return bool
|
44 |
-
*/
|
45 |
-
public function current_user_can_read( $post_id ) {
|
46 |
-
$post = get_post( $post_id );
|
47 |
-
|
48 |
-
if ( 'inherit' === $post->post_status && $post->post_parent ) {
|
49 |
-
$post = get_post( $post->post_parent );
|
50 |
-
}
|
51 |
-
|
52 |
-
if ( 'inherit' === $post->post_status || in_array( $post->post_status, get_post_stati( array( 'public' => true ) ) ) ) {
|
53 |
-
return true;
|
54 |
-
}
|
55 |
-
|
56 |
-
// Follow WP practices, which shows links to private posts ( when readable ), but not for draft posts ( ex: get_adjacent_post_link() )
|
57 |
-
if ( in_array( $post->post_status, get_post_stati( array( 'private' => true ) ) ) ) {
|
58 |
-
$post_type_object = get_post_type_object( $post->post_type );
|
59 |
-
$user = wp_get_current_user();
|
60 |
-
return is_user_logged_in() && ( current_user_can( $post_type_object->cap->read_private_posts ) || $user->ID == $post->post_author ); // Comparison must not be strict!
|
61 |
-
}
|
62 |
-
|
63 |
-
return false;
|
64 |
-
}
|
65 |
}
|
33 |
$language = is_object( $language ) ? $language : $this->model->get_language( $language );
|
34 |
return $is_search ? $language->search_url : $language->home_url;
|
35 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
}
|
include/model.php
CHANGED
@@ -385,7 +385,7 @@ class PLL_Model {
|
|
385 |
|
386 |
// create a new category
|
387 |
// FIXME this is translated in admin language when we would like it in $lang
|
388 |
-
$cat_name = __( 'Uncategorized' );
|
389 |
$cat_slug = sanitize_title( $cat_name . '-' . $lang->slug );
|
390 |
$cat = wp_insert_term( $cat_name, 'category', array( 'slug' => $cat_slug ) );
|
391 |
|
@@ -443,12 +443,12 @@ class PLL_Model {
|
|
443 |
}
|
444 |
|
445 |
/**
|
446 |
-
* Gets the number of posts per language in a date, author or post type archive
|
447 |
*
|
448 |
* @since 1.2
|
449 |
*
|
450 |
-
* @param object $lang
|
451 |
-
* @param array $q
|
452 |
* @return int
|
453 |
*/
|
454 |
public function count_posts( $lang, $q = array() ) {
|
@@ -467,11 +467,11 @@ class PLL_Model {
|
|
467 |
}
|
468 |
|
469 |
if ( empty( $q['post_type'] ) ) {
|
470 |
-
$q['post_type'] = array( 'post' ); //
|
471 |
}
|
472 |
|
473 |
-
$cache_key = md5(
|
474 |
-
$counts = wp_cache_get( $cache_key, '
|
475 |
|
476 |
if ( false === $counts ) {
|
477 |
$select = "SELECT pll_tr.term_taxonomy_id, COUNT( * ) AS num_posts FROM {$wpdb->posts}";
|
@@ -515,7 +515,7 @@ class PLL_Model {
|
|
515 |
$where .= $wpdb->prepare( " AND {$wpdb->posts}.post_author = %d", $q['author'] );
|
516 |
}
|
517 |
|
518 |
-
//
|
519 |
foreach ( $this->get_filtered_taxonomies_query_vars() as $tax_qv ) {
|
520 |
|
521 |
if ( ! empty( $q[ $tax_qv ] ) ) {
|
@@ -532,7 +532,7 @@ class PLL_Model {
|
|
532 |
$counts[ $row['term_taxonomy_id'] ] = $row['num_posts'];
|
533 |
}
|
534 |
|
535 |
-
wp_cache_set( $cache_key, $counts, '
|
536 |
}
|
537 |
|
538 |
return empty( $counts[ $lang->term_taxonomy_id ] ) ? 0 : $counts[ $lang->term_taxonomy_id ];
|
@@ -610,24 +610,32 @@ class PLL_Model {
|
|
610 |
|
611 |
if ( ! empty( $o ) && is_object( $this->$o ) && method_exists( $this->$o, $f ) ) {
|
612 |
if ( WP_DEBUG ) {
|
613 |
-
$debug = debug_backtrace();
|
614 |
$i = 1 + empty( $debug[1]['line'] ); // the file and line are in $debug[2] if the function was called using call_user_func
|
615 |
|
616 |
-
trigger_error(
|
617 |
sprintf(
|
618 |
'%1$s was called incorrectly in %4$s on line %5$s: the call to $polylang->model->%1$s() has been deprecated in Polylang 1.8, use PLL()->model->%2$s->%3$s() instead.' . "\nError handler",
|
619 |
-
$func,
|
620 |
-
$o,
|
621 |
-
$f,
|
622 |
-
$debug[ $i ]['file'],
|
623 |
-
$debug[ $i ]['line']
|
624 |
)
|
625 |
);
|
626 |
}
|
627 |
return call_user_func_array( array( $this->$o, $f ), $args );
|
628 |
}
|
629 |
|
630 |
-
$debug = debug_backtrace();
|
631 |
-
trigger_error(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
632 |
}
|
633 |
}
|
385 |
|
386 |
// create a new category
|
387 |
// FIXME this is translated in admin language when we would like it in $lang
|
388 |
+
$cat_name = __( 'Uncategorized', 'polylang' );
|
389 |
$cat_slug = sanitize_title( $cat_name . '-' . $lang->slug );
|
390 |
$cat = wp_insert_term( $cat_name, 'category', array( 'slug' => $cat_slug ) );
|
391 |
|
443 |
}
|
444 |
|
445 |
/**
|
446 |
+
* Gets the number of posts per language in a date, author or post type archive.
|
447 |
*
|
448 |
* @since 1.2
|
449 |
*
|
450 |
+
* @param object $lang PLL_Language instance.
|
451 |
+
* @param array $q WP_Query arguments ( accepted: post_type, m, year, monthnum, day, author, author_name, post_format ).
|
452 |
* @return int
|
453 |
*/
|
454 |
public function count_posts( $lang, $q = array() ) {
|
467 |
}
|
468 |
|
469 |
if ( empty( $q['post_type'] ) ) {
|
470 |
+
$q['post_type'] = array( 'post' ); // We *need* a post type.
|
471 |
}
|
472 |
|
473 |
+
$cache_key = 'pll_count_posts_' . md5( maybe_serialize( $q ) );
|
474 |
+
$counts = wp_cache_get( $cache_key, 'counts' );
|
475 |
|
476 |
if ( false === $counts ) {
|
477 |
$select = "SELECT pll_tr.term_taxonomy_id, COUNT( * ) AS num_posts FROM {$wpdb->posts}";
|
515 |
$where .= $wpdb->prepare( " AND {$wpdb->posts}.post_author = %d", $q['author'] );
|
516 |
}
|
517 |
|
518 |
+
// Filtered taxonomies ( post_format ).
|
519 |
foreach ( $this->get_filtered_taxonomies_query_vars() as $tax_qv ) {
|
520 |
|
521 |
if ( ! empty( $q[ $tax_qv ] ) ) {
|
532 |
$counts[ $row['term_taxonomy_id'] ] = $row['num_posts'];
|
533 |
}
|
534 |
|
535 |
+
wp_cache_set( $cache_key, $counts, 'counts' );
|
536 |
}
|
537 |
|
538 |
return empty( $counts[ $lang->term_taxonomy_id ] ) ? 0 : $counts[ $lang->term_taxonomy_id ];
|
610 |
|
611 |
if ( ! empty( $o ) && is_object( $this->$o ) && method_exists( $this->$o, $f ) ) {
|
612 |
if ( WP_DEBUG ) {
|
613 |
+
$debug = debug_backtrace(); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
614 |
$i = 1 + empty( $debug[1]['line'] ); // the file and line are in $debug[2] if the function was called using call_user_func
|
615 |
|
616 |
+
trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
617 |
sprintf(
|
618 |
'%1$s was called incorrectly in %4$s on line %5$s: the call to $polylang->model->%1$s() has been deprecated in Polylang 1.8, use PLL()->model->%2$s->%3$s() instead.' . "\nError handler",
|
619 |
+
esc_html( $func ),
|
620 |
+
esc_html( $o ),
|
621 |
+
esc_html( $f ),
|
622 |
+
esc_html( $debug[ $i ]['file'] ),
|
623 |
+
absint( $debug[ $i ]['line'] )
|
624 |
)
|
625 |
);
|
626 |
}
|
627 |
return call_user_func_array( array( $this->$o, $f ), $args );
|
628 |
}
|
629 |
|
630 |
+
$debug = debug_backtrace(); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
631 |
+
trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
632 |
+
sprintf(
|
633 |
+
'Call to undefined function PLL()->model->%1$s() in %2$s on line %3$s' . "\nError handler",
|
634 |
+
esc_html( $func ),
|
635 |
+
esc_html( $debug[0]['file'] ),
|
636 |
+
absint( $debug[0]['line'] )
|
637 |
+
),
|
638 |
+
E_USER_ERROR
|
639 |
+
);
|
640 |
}
|
641 |
}
|
include/nav-menu.php
CHANGED
@@ -20,8 +20,31 @@ class PLL_Nav_Menu {
|
|
20 |
$this->model = &$polylang->model;
|
21 |
$this->options = &$polylang->options;
|
22 |
|
|
|
|
|
|
|
|
|
23 |
// Integration with WP customizer
|
24 |
add_action( 'customize_register', array( $this, 'create_nav_menu_locations' ), 5 );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
}
|
26 |
|
27 |
/**
|
@@ -76,4 +99,48 @@ class PLL_Nav_Menu {
|
|
76 |
}
|
77 |
return array_combine( array( 'location', 'lang' ), $infos );
|
78 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
}
|
20 |
$this->model = &$polylang->model;
|
21 |
$this->options = &$polylang->options;
|
22 |
|
23 |
+
$this->theme = get_option( 'stylesheet' );
|
24 |
+
|
25 |
+
add_filter( 'wp_setup_nav_menu_item', array( $this, 'wp_setup_nav_menu_item' ) );
|
26 |
+
|
27 |
// Integration with WP customizer
|
28 |
add_action( 'customize_register', array( $this, 'create_nav_menu_locations' ), 5 );
|
29 |
+
|
30 |
+
// Filter _wp_auto_add_pages_to_menu by language
|
31 |
+
add_action( 'transition_post_status', array( $this, 'auto_add_pages_to_menu' ), 5, 3 ); // before _wp_auto_add_pages_to_menu
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Assigns the title and label to the language switcher menu items
|
36 |
+
*
|
37 |
+
* @since 2.6
|
38 |
+
*
|
39 |
+
* @param object $item Menu item.
|
40 |
+
* @return object
|
41 |
+
*/
|
42 |
+
public function wp_setup_nav_menu_item( $item ) {
|
43 |
+
if ( '#pll_switcher' === $item->url ) {
|
44 |
+
$item->post_title = __( 'Languages', 'polylang' );
|
45 |
+
$item->type_label = __( 'Language switcher', 'polylang' );
|
46 |
+
}
|
47 |
+
return $item;
|
48 |
}
|
49 |
|
50 |
/**
|
99 |
}
|
100 |
return array_combine( array( 'location', 'lang' ), $infos );
|
101 |
}
|
102 |
+
|
103 |
+
/**
|
104 |
+
* Filters the option nav_menu_options for auto added pages to menu
|
105 |
+
*
|
106 |
+
* @since 0.9.4
|
107 |
+
*
|
108 |
+
* @param array $options
|
109 |
+
* @return array Modified options
|
110 |
+
*/
|
111 |
+
public function nav_menu_options( $options ) {
|
112 |
+
$options['auto_add'] = array_intersect( $options['auto_add'], $this->auto_add_menus );
|
113 |
+
return $options;
|
114 |
+
}
|
115 |
+
|
116 |
+
/**
|
117 |
+
* Filters _wp_auto_add_pages_to_menu by language
|
118 |
+
*
|
119 |
+
* @since 0.9.4
|
120 |
+
*
|
121 |
+
* @param string $new_status Transition to this post status.
|
122 |
+
* @param string $old_status Previous post status.
|
123 |
+
* @param object $post Post data.
|
124 |
+
*/
|
125 |
+
public function auto_add_pages_to_menu( $new_status, $old_status, $post ) {
|
126 |
+
if ( 'publish' != $new_status || 'publish' == $old_status || 'page' != $post->post_type || ! empty( $post->post_parent ) ) {
|
127 |
+
return;
|
128 |
+
}
|
129 |
+
|
130 |
+
if ( ! empty( $this->options['nav_menus'][ $this->theme ] ) ) {
|
131 |
+
$this->auto_add_menus = array();
|
132 |
+
|
133 |
+
$lang = $this->model->post->get_language( $post->ID );
|
134 |
+
$lang = empty( $lang ) ? $this->options['default_lang'] : $lang->slug; // If the page has no language yet, the default language will be assigned
|
135 |
+
|
136 |
+
// Get all the menus in the page language
|
137 |
+
foreach ( $this->options['nav_menus'][ $this->theme ] as $loc ) {
|
138 |
+
if ( ! empty( $loc[ $lang ] ) ) {
|
139 |
+
$this->auto_add_menus[] = $loc[ $lang ];
|
140 |
+
}
|
141 |
+
}
|
142 |
+
|
143 |
+
add_filter( 'option_nav_menu_options', array( $this, 'nav_menu_options' ) );
|
144 |
+
}
|
145 |
+
}
|
146 |
}
|
include/olt-manager.php
CHANGED
@@ -10,7 +10,7 @@
|
|
10 |
* @since 1.2
|
11 |
*/
|
12 |
class PLL_OLT_Manager {
|
13 |
-
static
|
14 |
protected $default_locale;
|
15 |
protected $list_textdomains = array(); // All text domains
|
16 |
public $labels = array(); // Post types and taxonomies labels to translate
|
10 |
* @since 1.2
|
11 |
*/
|
12 |
class PLL_OLT_Manager {
|
13 |
+
protected static $instance; // For singleton
|
14 |
protected $default_locale;
|
15 |
protected $list_textdomains = array(); // All text domains
|
16 |
public $labels = array(); // Post types and taxonomies labels to translate
|
include/pointer.php
CHANGED
@@ -33,7 +33,7 @@ class PLL_Pointer {
|
|
33 |
* @param array $args
|
34 |
*/
|
35 |
public function __construct( $args ) {
|
36 |
-
trigger_error( 'The class PLL_Pointer has been deprecated since Polylang 2.3.9 and will be removed in a future version.', E_USER_ERROR );
|
37 |
|
38 |
$this->args = $args;
|
39 |
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
@@ -108,6 +108,6 @@ class PLL_Pointer {
|
|
108 |
empty( $this->args['width'] ) ? '' : sprintf( 'pointerWidth: %d,', $this->args['width'] ),
|
109 |
empty( $b ) ? '' : $b
|
110 |
);
|
111 |
-
echo '<script type="text/javascript">' . $js . '</script>';
|
112 |
}
|
113 |
}
|
33 |
* @param array $args
|
34 |
*/
|
35 |
public function __construct( $args ) {
|
36 |
+
trigger_error( 'The class PLL_Pointer has been deprecated since Polylang 2.3.9 and will be removed in a future version.', E_USER_ERROR ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
37 |
|
38 |
$this->args = $args;
|
39 |
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
|
108 |
empty( $this->args['width'] ) ? '' : sprintf( 'pointerWidth: %d,', $this->args['width'] ),
|
109 |
empty( $b ) ? '' : $b
|
110 |
);
|
111 |
+
echo '<script type="text/javascript">' . $js . '</script>'; // phpcs:ignore WordPress.Security.EscapeOutput
|
112 |
}
|
113 |
}
|
include/query.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
*/
|
8 |
class PLL_Query {
|
9 |
|
10 |
-
static
|
11 |
'p',
|
12 |
'post_parent',
|
13 |
'attachment',
|
7 |
*/
|
8 |
class PLL_Query {
|
9 |
|
10 |
+
protected static $excludes = array(
|
11 |
'p',
|
12 |
'post_parent',
|
13 |
'attachment',
|
include/rest-request.php
ADDED
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* REST API controller
|
5 |
+
* accessible as $polylang global object
|
6 |
+
*
|
7 |
+
* Properties:
|
8 |
+
* options => inherited, reference to Polylang options array
|
9 |
+
* model => inherited, reference to PLL_Model object
|
10 |
+
* links_model => inherited, reference to PLL_Links_Model object
|
11 |
+
* links => reference to PLL_Admin_Links object
|
12 |
+
* static_pages => reference to PLL_Static_Pages object
|
13 |
+
* filters_links => reference to PLL_Filters_Links object
|
14 |
+
* posts => reference to PLL_CRUD_Posts object
|
15 |
+
* terms => reference to PLL_CRUD_Terms object
|
16 |
+
* sync => reference to PLL_Sync object
|
17 |
+
*
|
18 |
+
* @since 2.6
|
19 |
+
*/
|
20 |
+
class PLL_REST_Request extends PLL_Base {
|
21 |
+
public $links, $posts, $terms, $filters_links, $sync;
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Setup filters
|
25 |
+
*
|
26 |
+
* @since 2.6
|
27 |
+
*/
|
28 |
+
public function init() {
|
29 |
+
parent::init();
|
30 |
+
|
31 |
+
if ( $this->model->get_languages_list() ) {
|
32 |
+
$this->filters_links = new PLL_Filters_Links( $this );
|
33 |
+
|
34 |
+
// Static front page and page for posts
|
35 |
+
if ( 'page' === get_option( 'show_on_front' ) ) {
|
36 |
+
$this->static_pages = new PLL_Static_Pages( $this );
|
37 |
+
}
|
38 |
+
|
39 |
+
$this->links = new PLL_Admin_Links( $this );
|
40 |
+
$this->posts = new PLL_CRUD_Posts( $this );
|
41 |
+
$this->terms = new PLL_CRUD_Terms( $this );
|
42 |
+
$this->sync = new PLL_Sync( $this );
|
43 |
+
|
44 |
+
$this->nav_menu = new PLL_Nav_Menu( $this ); // For auto added pages to menu
|
45 |
+
|
46 |
+
// Share term slugs
|
47 |
+
if ( get_option( 'permalink_structure' ) && $this->options['force_lang'] && class_exists( 'PLL_Share_Term_Slug' ) ) {
|
48 |
+
$this->share_term_slug = version_compare( $GLOBALS['wp_version'], '4.8', '<' ) ?
|
49 |
+
new PLL_Frontend_Share_Term_Slug( $this ) :
|
50 |
+
new PLL_Share_Term_Slug( $this );
|
51 |
+
}
|
52 |
+
|
53 |
+
// Translate slugs, only for pretty permalinks
|
54 |
+
if ( get_option( 'permalink_structure' ) && class_exists( 'PLL_Translate_Slugs' ) ) {
|
55 |
+
$curlang = null;
|
56 |
+
$slugs_model = new PLL_Translate_Slugs_Model( $this );
|
57 |
+
$this->translate_slugs = new PLL_Translate_Slugs( $slugs_model, $curlang );
|
58 |
+
}
|
59 |
+
|
60 |
+
if ( class_exists( 'PLL_Sync_Content' ) ) {
|
61 |
+
$this->sync_content = new PLL_Sync_Content( $this );
|
62 |
+
}
|
63 |
+
|
64 |
+
if ( class_exists( 'PLL_Sync_Post_REST' ) ) {
|
65 |
+
$this->sync_post = new PLL_Sync_Post_REST( $this );
|
66 |
+
}
|
67 |
+
|
68 |
+
if ( class_exists( 'PLL_Duplicate_REST' ) ) {
|
69 |
+
$this->duplicate_rest = new PLL_Duplicate_REST();
|
70 |
+
}
|
71 |
+
}
|
72 |
+
}
|
73 |
+
}
|
include/static-pages.php
CHANGED
@@ -5,7 +5,7 @@
|
|
5 |
*
|
6 |
* @since 1.8
|
7 |
*/
|
8 |
-
|
9 |
public $model, $options;
|
10 |
public $page_on_front, $page_for_posts;
|
11 |
|
@@ -17,7 +17,7 @@ abstract class PLL_Static_Pages {
|
|
17 |
* @param object $polylang
|
18 |
*/
|
19 |
public function __construct( &$polylang ) {
|
20 |
-
$this->model
|
21 |
$this->options = &$polylang->options;
|
22 |
$this->curlang = &$polylang->curlang;
|
23 |
|
@@ -33,6 +33,9 @@ abstract class PLL_Static_Pages {
|
|
33 |
|
34 |
// Refresh rewrite rules when the page on front is modified
|
35 |
add_action( 'update_option_page_on_front', 'flush_rewrite_rules' );
|
|
|
|
|
|
|
36 |
}
|
37 |
|
38 |
/**
|
@@ -44,9 +47,7 @@ abstract class PLL_Static_Pages {
|
|
44 |
if ( 'page' == get_option( 'show_on_front' ) ) {
|
45 |
$this->page_on_front = get_option( 'page_on_front' );
|
46 |
$this->page_for_posts = get_option( 'page_for_posts' );
|
47 |
-
}
|
48 |
-
|
49 |
-
else {
|
50 |
$this->page_on_front = 0;
|
51 |
$this->page_for_posts = 0;
|
52 |
}
|
@@ -62,7 +63,9 @@ abstract class PLL_Static_Pages {
|
|
62 |
* @return string modified link
|
63 |
*/
|
64 |
public function page_link( $link, $id ) {
|
65 |
-
|
|
|
|
|
66 |
return $lang->home_url;
|
67 |
}
|
68 |
return $link;
|
@@ -99,4 +102,22 @@ abstract class PLL_Static_Pages {
|
|
99 |
// Don't attempt to translate in a 'switch_blog' action as there is a risk to call this function while initializing the languages cache
|
100 |
return isset( $this->curlang->page_for_posts ) && ! doing_action( 'switch_blog' ) ? $this->curlang->page_for_posts : $v;
|
101 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
102 |
}
|
5 |
*
|
6 |
* @since 1.8
|
7 |
*/
|
8 |
+
class PLL_Static_Pages {
|
9 |
public $model, $options;
|
10 |
public $page_on_front, $page_for_posts;
|
11 |
|
17 |
* @param object $polylang
|
18 |
*/
|
19 |
public function __construct( &$polylang ) {
|
20 |
+
$this->model = &$polylang->model;
|
21 |
$this->options = &$polylang->options;
|
22 |
$this->curlang = &$polylang->curlang;
|
23 |
|
33 |
|
34 |
// Refresh rewrite rules when the page on front is modified
|
35 |
add_action( 'update_option_page_on_front', 'flush_rewrite_rules' );
|
36 |
+
|
37 |
+
// OEmbed
|
38 |
+
add_filter( 'oembed_request_post_id', array( $this, 'oembed_request_post_id' ), 10, 2 );
|
39 |
}
|
40 |
|
41 |
/**
|
47 |
if ( 'page' == get_option( 'show_on_front' ) ) {
|
48 |
$this->page_on_front = get_option( 'page_on_front' );
|
49 |
$this->page_for_posts = get_option( 'page_for_posts' );
|
50 |
+
} else {
|
|
|
|
|
51 |
$this->page_on_front = 0;
|
52 |
$this->page_for_posts = 0;
|
53 |
}
|
63 |
* @return string modified link
|
64 |
*/
|
65 |
public function page_link( $link, $id ) {
|
66 |
+
$lang = $this->model->post->get_language( $id );
|
67 |
+
|
68 |
+
if ( $lang && $id == $lang->page_on_front ) {
|
69 |
return $lang->home_url;
|
70 |
}
|
71 |
return $link;
|
102 |
// Don't attempt to translate in a 'switch_blog' action as there is a risk to call this function while initializing the languages cache
|
103 |
return isset( $this->curlang->page_for_posts ) && ! doing_action( 'switch_blog' ) ? $this->curlang->page_for_posts : $v;
|
104 |
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Fixes the oembed for the translated static front page
|
108 |
+
* when the language page is redirected to the front page
|
109 |
+
*
|
110 |
+
* @since 2.6
|
111 |
+
*
|
112 |
+
* @param int $post_id The post ID.
|
113 |
+
* @param string $url The requested URL.
|
114 |
+
*/
|
115 |
+
public function oembed_request_post_id( $post_id, $url ) {
|
116 |
+
foreach ( $this->model->get_languages_list() as $lang ) {
|
117 |
+
if ( trailingslashit( $url ) === trailingslashit( $lang->home_url ) ) {
|
118 |
+
$post_id = $lang->page_on_front;
|
119 |
+
}
|
120 |
+
}
|
121 |
+
return $post_id;
|
122 |
+
}
|
123 |
}
|
include/switcher.php
CHANGED
@@ -19,7 +19,7 @@ class PLL_Switcher {
|
|
19 |
*/
|
20 |
public static function get_switcher_options( $type = 'widget', $key = 'string' ) {
|
21 |
$options = array(
|
22 |
-
'dropdown' => array( 'string' => __( 'Displays as dropdown', 'polylang' ), 'default' => 0 ),
|
23 |
'show_names' => array( 'string' => __( 'Displays language names', 'polylang' ), 'default' => 1 ),
|
24 |
'show_flags' => array( 'string' => __( 'Displays flags', 'polylang' ), 'default' => 0 ),
|
25 |
'force_home' => array( 'string' => __( 'Forces link to front page', 'polylang' ), 'default' => 0 ),
|
@@ -67,7 +67,7 @@ class PLL_Switcher {
|
|
67 |
}
|
68 |
}
|
69 |
|
70 |
-
if ( null !== $args['post_id'] && ( $tr_id = $links->model->post->get( $args['post_id'], $language ) ) && $links->current_user_can_read( $tr_id ) ) {
|
71 |
$url = get_permalink( $tr_id );
|
72 |
} elseif ( null === $args['post_id'] ) {
|
73 |
$url = $links->get_translation_url( $language );
|
@@ -204,13 +204,13 @@ class PLL_Switcher {
|
|
204 |
//]]>
|
205 |
</script>',
|
206 |
'urls_' . preg_replace( '#[^a-zA-Z0-9]#', '', $args['dropdown'] ),
|
207 |
-
|
208 |
esc_js( $args['name'] )
|
209 |
);
|
210 |
}
|
211 |
|
212 |
if ( $args['echo'] ) {
|
213 |
-
echo $out;
|
214 |
}
|
215 |
return $out;
|
216 |
}
|
19 |
*/
|
20 |
public static function get_switcher_options( $type = 'widget', $key = 'string' ) {
|
21 |
$options = array(
|
22 |
+
'dropdown' => array( 'string' => __( 'Displays as a dropdown', 'polylang' ), 'default' => 0 ),
|
23 |
'show_names' => array( 'string' => __( 'Displays language names', 'polylang' ), 'default' => 1 ),
|
24 |
'show_flags' => array( 'string' => __( 'Displays flags', 'polylang' ), 'default' => 0 ),
|
25 |
'force_home' => array( 'string' => __( 'Forces link to front page', 'polylang' ), 'default' => 0 ),
|
67 |
}
|
68 |
}
|
69 |
|
70 |
+
if ( null !== $args['post_id'] && ( $tr_id = $links->model->post->get( $args['post_id'], $language ) ) && $links->model->post->current_user_can_read( $tr_id ) ) {
|
71 |
$url = get_permalink( $tr_id );
|
72 |
} elseif ( null === $args['post_id'] ) {
|
73 |
$url = $links->get_translation_url( $language );
|
204 |
//]]>
|
205 |
</script>',
|
206 |
'urls_' . preg_replace( '#[^a-zA-Z0-9]#', '', $args['dropdown'] ),
|
207 |
+
wp_json_encode( $urls ),
|
208 |
esc_js( $args['name'] )
|
209 |
);
|
210 |
}
|
211 |
|
212 |
if ( $args['echo'] ) {
|
213 |
+
echo $out; // phpcs:ignore WordPress.Security.EscapeOutput
|
214 |
}
|
215 |
return $out;
|
216 |
}
|
include/translated-object.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
*/
|
8 |
abstract class PLL_Translated_Object {
|
9 |
public $model;
|
10 |
-
protected $object_type, $tax_language, $tax_translations, $tax_tt;
|
11 |
|
12 |
/**
|
13 |
* Constructor
|
@@ -115,14 +115,14 @@ abstract class PLL_Translated_Object {
|
|
115 |
|
116 |
// create a new term if necessary
|
117 |
if ( empty( $term ) ) {
|
118 |
-
wp_insert_term( $group = uniqid( 'pll_' ), $this->tax_translations, array( 'description' =>
|
119 |
}
|
120 |
else {
|
121 |
// take care not to overwrite extra data stored in description field, if any
|
122 |
-
$d =
|
123 |
$d = is_array( $d ) ? array_diff_key( $d, $old_translations ) : array(); // remove old translations
|
124 |
$d = array_merge( $d, $translations ); // add new one
|
125 |
-
wp_update_term( $group = (int) $term->term_id, $this->tax_translations, array( 'description' =>
|
126 |
}
|
127 |
|
128 |
// link all translations to the new term
|
@@ -153,7 +153,7 @@ abstract class PLL_Translated_Object {
|
|
153 |
$term = $this->get_object_term( $id, $this->tax_translations );
|
154 |
|
155 |
if ( ! empty( $term ) ) {
|
156 |
-
$d =
|
157 |
$slug = array_search( $id, $this->get_translations( $id ) ); // in case some plugin stores the same value with different key
|
158 |
unset( $d[ $slug ] );
|
159 |
|
@@ -161,7 +161,7 @@ abstract class PLL_Translated_Object {
|
|
161 |
wp_delete_term( (int) $term->term_id, $this->tax_translations );
|
162 |
}
|
163 |
else {
|
164 |
-
wp_update_term( (int) $term->term_id, $this->tax_translations, array( 'description' =>
|
165 |
}
|
166 |
}
|
167 |
}
|
@@ -176,7 +176,7 @@ abstract class PLL_Translated_Object {
|
|
176 |
*/
|
177 |
public function get_translations( $id ) {
|
178 |
$term = $this->get_object_term( $id, $this->tax_translations );
|
179 |
-
$translations = empty( $term ) ? array() :
|
180 |
|
181 |
// make sure we return only translations ( thus we allow plugins to store other information in the array )
|
182 |
if ( is_array( $translations ) ) {
|
@@ -272,4 +272,42 @@ abstract class PLL_Translated_Object {
|
|
272 |
$tt_id = $this->tax_tt;
|
273 |
return $wpdb->get_col( $wpdb->prepare( "SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $lang->$tt_id ) );
|
274 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
}
|
7 |
*/
|
8 |
abstract class PLL_Translated_Object {
|
9 |
public $model;
|
10 |
+
protected $object_type, $type, $tax_language, $tax_translations, $tax_tt;
|
11 |
|
12 |
/**
|
13 |
* Constructor
|
115 |
|
116 |
// create a new term if necessary
|
117 |
if ( empty( $term ) ) {
|
118 |
+
wp_insert_term( $group = uniqid( 'pll_' ), $this->tax_translations, array( 'description' => maybe_serialize( $translations ) ) );
|
119 |
}
|
120 |
else {
|
121 |
// take care not to overwrite extra data stored in description field, if any
|
122 |
+
$d = maybe_unserialize( $term->description );
|
123 |
$d = is_array( $d ) ? array_diff_key( $d, $old_translations ) : array(); // remove old translations
|
124 |
$d = array_merge( $d, $translations ); // add new one
|
125 |
+
wp_update_term( $group = (int) $term->term_id, $this->tax_translations, array( 'description' => maybe_serialize( $d ) ) );
|
126 |
}
|
127 |
|
128 |
// link all translations to the new term
|
153 |
$term = $this->get_object_term( $id, $this->tax_translations );
|
154 |
|
155 |
if ( ! empty( $term ) ) {
|
156 |
+
$d = maybe_unserialize( $term->description );
|
157 |
$slug = array_search( $id, $this->get_translations( $id ) ); // in case some plugin stores the same value with different key
|
158 |
unset( $d[ $slug ] );
|
159 |
|
161 |
wp_delete_term( (int) $term->term_id, $this->tax_translations );
|
162 |
}
|
163 |
else {
|
164 |
+
wp_update_term( (int) $term->term_id, $this->tax_translations, array( 'description' => maybe_serialize( $d ) ) );
|
165 |
}
|
166 |
}
|
167 |
}
|
176 |
*/
|
177 |
public function get_translations( $id ) {
|
178 |
$term = $this->get_object_term( $id, $this->tax_translations );
|
179 |
+
$translations = empty( $term ) ? array() : maybe_unserialize( $term->description );
|
180 |
|
181 |
// make sure we return only translations ( thus we allow plugins to store other information in the array )
|
182 |
if ( is_array( $translations ) ) {
|
272 |
$tt_id = $this->tax_tt;
|
273 |
return $wpdb->get_col( $wpdb->prepare( "SELECT object_id FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d", $lang->$tt_id ) );
|
274 |
}
|
275 |
+
|
276 |
+
/**
|
277 |
+
* Check if a user can synchronize translations
|
278 |
+
*
|
279 |
+
* @since 2.6
|
280 |
+
*
|
281 |
+
* @param int $id Object id
|
282 |
+
* @return bool
|
283 |
+
*/
|
284 |
+
public function current_user_can_synchronize( $id ) {
|
285 |
+
/**
|
286 |
+
* Filters whether a synchronization capability check should take place
|
287 |
+
*
|
288 |
+
* @since 2.6
|
289 |
+
*
|
290 |
+
* @param $check null to enable the capability check,
|
291 |
+
* true to always allow the synchronization,
|
292 |
+
* false to always disallow the synchronization.
|
293 |
+
* Defaults to true.
|
294 |
+
* @param $id The synchronization source object id
|
295 |
+
*/
|
296 |
+
$check = apply_filters( "pll_pre_current_user_can_synchronize_{$this->type}", true, $id );
|
297 |
+
if ( null !== $check ) {
|
298 |
+
return $check;
|
299 |
+
}
|
300 |
+
|
301 |
+
if ( ! current_user_can( "edit_{$this->type}", $id ) ) {
|
302 |
+
return false;
|
303 |
+
}
|
304 |
+
|
305 |
+
foreach ( $this->get_translations( $id ) as $tr_id ) {
|
306 |
+
if ( $tr_id !== $id && ! current_user_can( "edit_{$this->type}", $tr_id ) ) {
|
307 |
+
return false;
|
308 |
+
}
|
309 |
+
}
|
310 |
+
|
311 |
+
return true;
|
312 |
+
}
|
313 |
}
|
include/translated-post.php
CHANGED
@@ -16,7 +16,8 @@ class PLL_Translated_Post extends PLL_Translated_Object {
|
|
16 |
*/
|
17 |
public function __construct( &$model ) {
|
18 |
// init properties
|
19 |
-
$this->object_type = null;
|
|
|
20 |
$this->tax_language = 'language';
|
21 |
$this->tax_translations = 'post_translations';
|
22 |
$this->tax_tt = 'term_taxonomy_id';
|
@@ -146,4 +147,93 @@ class PLL_Translated_Post extends PLL_Translated_Object {
|
|
146 |
$query->query_vars['update_post_term_cache'] = true;
|
147 |
}
|
148 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
}
|
16 |
*/
|
17 |
public function __construct( &$model ) {
|
18 |
// init properties
|
19 |
+
$this->object_type = null; // For taxonomies
|
20 |
+
$this->type = 'post'; // For capabilities
|
21 |
$this->tax_language = 'language';
|
22 |
$this->tax_translations = 'post_translations';
|
23 |
$this->tax_tt = 'term_taxonomy_id';
|
147 |
$query->query_vars['update_post_term_cache'] = true;
|
148 |
}
|
149 |
}
|
150 |
+
|
151 |
+
/**
|
152 |
+
* Checks if the current user can read the post
|
153 |
+
*
|
154 |
+
* @since 1.5
|
155 |
+
*
|
156 |
+
* @param int $post_id Post ID
|
157 |
+
* @param string $context Optional, 'edit' or 'view', defaults to 'view'.
|
158 |
+
* @return bool
|
159 |
+
*/
|
160 |
+
public function current_user_can_read( $post_id, $context = 'view' ) {
|
161 |
+
$post = get_post( $post_id );
|
162 |
+
|
163 |
+
if ( 'inherit' === $post->post_status && $post->post_parent ) {
|
164 |
+
$post = get_post( $post->post_parent );
|
165 |
+
}
|
166 |
+
|
167 |
+
if ( 'inherit' === $post->post_status || in_array( $post->post_status, get_post_stati( array( 'public' => true ) ) ) ) {
|
168 |
+
return true;
|
169 |
+
}
|
170 |
+
|
171 |
+
// Follow WP practices, which shows links to private posts ( when readable ), but not for draft posts ( ex: get_adjacent_post_link() )
|
172 |
+
if ( in_array( $post->post_status, get_post_stati( array( 'private' => true ) ) ) ) {
|
173 |
+
$post_type_object = get_post_type_object( $post->post_type );
|
174 |
+
$user = wp_get_current_user();
|
175 |
+
return is_user_logged_in() && ( current_user_can( $post_type_object->cap->read_private_posts ) || $user->ID == $post->post_author ); // Comparison must not be strict!
|
176 |
+
}
|
177 |
+
|
178 |
+
if ( 'edit' === $context && 'draft' === $post->post_status ) {
|
179 |
+
$user = wp_get_current_user();
|
180 |
+
return is_user_logged_in() && ( current_user_can( 'edit_posts' ) || $user->ID == $post->post_author ); // Comparison must not be strict!
|
181 |
+
}
|
182 |
+
|
183 |
+
return false;
|
184 |
+
}
|
185 |
+
|
186 |
+
/**
|
187 |
+
* Returns a list of posts in a language ( $lang )
|
188 |
+
* not translated in another language ( $untranslated_in )
|
189 |
+
*
|
190 |
+
* @since 2.6
|
191 |
+
*
|
192 |
+
* @param string $type Post type
|
193 |
+
* @param string $untranslated_in The posts must not be translated in this language
|
194 |
+
* @param string $lang Language of the search posts
|
195 |
+
* @param string $search Limit results to posts matching this string
|
196 |
+
* @return array Array of posts
|
197 |
+
*/
|
198 |
+
public function get_untranslated( $type, $untranslated_in, $lang, $search = '' ) {
|
199 |
+
$return = array();
|
200 |
+
|
201 |
+
// Don't order by title: see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
|
202 |
+
$args = array(
|
203 |
+
's' => $search,
|
204 |
+
'suppress_filters' => 0, // To make the post_fields filter work
|
205 |
+
'lang' => 0, // Avoid admin language filter
|
206 |
+
'numberposts' => 20, // Limit to 20 posts
|
207 |
+
'post_status' => 'any',
|
208 |
+
'post_type' => $type,
|
209 |
+
'tax_query' => array(
|
210 |
+
array(
|
211 |
+
'taxonomy' => 'language',
|
212 |
+
'field' => 'term_taxonomy_id', // WP 3.5+
|
213 |
+
'terms' => $lang->term_taxonomy_id,
|
214 |
+
),
|
215 |
+
),
|
216 |
+
);
|
217 |
+
|
218 |
+
/**
|
219 |
+
* Filter the query args when auto suggesting untranslated posts in the Languages metabox
|
220 |
+
* This should help plugins to fix some edge cases
|
221 |
+
*
|
222 |
+
* @see https://wordpress.org/support/topic/find-translated-post-when-10-is-not-enough
|
223 |
+
*
|
224 |
+
* @since 1.7
|
225 |
+
*
|
226 |
+
* @param array $args WP_Query arguments
|
227 |
+
*/
|
228 |
+
$args = apply_filters( 'pll_ajax_posts_not_translated_args', $args );
|
229 |
+
$posts = get_posts( $args );
|
230 |
+
|
231 |
+
foreach ( $posts as $post ) {
|
232 |
+
if ( ! $this->get_translation( $post->ID, $untranslated_in ) && $this->current_user_can_read( $post->ID, 'edit' ) ) {
|
233 |
+
$return[] = $post;
|
234 |
+
}
|
235 |
+
}
|
236 |
+
|
237 |
+
return $return;
|
238 |
+
}
|
239 |
}
|
include/translated-term.php
CHANGED
@@ -15,7 +15,8 @@ class PLL_Translated_Term extends PLL_Translated_Object {
|
|
15 |
* @param object $model
|
16 |
*/
|
17 |
public function __construct( &$model ) {
|
18 |
-
$this->object_type = 'term';
|
|
|
19 |
$this->tax_language = 'term_language';
|
20 |
$this->tax_translations = 'term_translations';
|
21 |
$this->tax_tt = 'tl_term_taxonomy_id';
|
@@ -128,7 +129,7 @@ class PLL_Translated_Term extends PLL_Translated_Object {
|
|
128 |
if ( ! doing_action( 'pre_delete_term' ) && $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( * ) FROM $wpdb->terms WHERE term_id = %d;", $id ) ) ) {
|
129 |
// Always keep a group for terms to allow relationships remap when importing from a WXR file
|
130 |
$translations[ $slug ] = $id;
|
131 |
-
wp_insert_term( $group = uniqid( 'pll_' ), 'term_translations', array( 'description' =>
|
132 |
wp_set_object_terms( $id, $group, 'term_translations' );
|
133 |
}
|
134 |
}
|
@@ -137,12 +138,14 @@ class PLL_Translated_Term extends PLL_Translated_Object {
|
|
137 |
* A join clause to add to sql queries when filtering by language is needed directly in query
|
138 |
*
|
139 |
* @since 1.2
|
|
|
140 |
*
|
|
|
141 |
* @return string join clause
|
142 |
*/
|
143 |
-
public function join_clause() {
|
144 |
global $wpdb;
|
145 |
-
return " INNER JOIN $wpdb->term_relationships AS pll_tr ON pll_tr.object_id =
|
146 |
}
|
147 |
|
148 |
/**
|
15 |
* @param object $model
|
16 |
*/
|
17 |
public function __construct( &$model ) {
|
18 |
+
$this->object_type = 'term'; // For taxonomies
|
19 |
+
$this->type = 'term'; // For capabilities
|
20 |
$this->tax_language = 'term_language';
|
21 |
$this->tax_translations = 'term_translations';
|
22 |
$this->tax_tt = 'tl_term_taxonomy_id';
|
129 |
if ( ! doing_action( 'pre_delete_term' ) && $wpdb->get_var( $wpdb->prepare( "SELECT COUNT( * ) FROM $wpdb->terms WHERE term_id = %d;", $id ) ) ) {
|
130 |
// Always keep a group for terms to allow relationships remap when importing from a WXR file
|
131 |
$translations[ $slug ] = $id;
|
132 |
+
wp_insert_term( $group = uniqid( 'pll_' ), 'term_translations', array( 'description' => maybe_serialize( $translations ) ) );
|
133 |
wp_set_object_terms( $id, $group, 'term_translations' );
|
134 |
}
|
135 |
}
|
138 |
* A join clause to add to sql queries when filtering by language is needed directly in query
|
139 |
*
|
140 |
* @since 1.2
|
141 |
+
* @since 2.6 The `$alias` parameter was added.
|
142 |
*
|
143 |
+
* @param string $alias Alias for $wpdb->terms table
|
144 |
* @return string join clause
|
145 |
*/
|
146 |
+
public function join_clause( $alias = 't' ) {
|
147 |
global $wpdb;
|
148 |
+
return " INNER JOIN $wpdb->term_relationships AS pll_tr ON pll_tr.object_id = $alias.term_id";
|
149 |
}
|
150 |
|
151 |
/**
|
include/walker-dropdown.php
CHANGED
@@ -25,7 +25,7 @@ class PLL_Walker_Dropdown extends Walker {
|
|
25 |
"\t" . '<option value="%1$s"%2$s%3$s>%4$s</option>' . "\n",
|
26 |
esc_attr( $element->$value ),
|
27 |
method_exists( $element, 'get_locale' ) ? sprintf( ' lang="%s"', esc_attr( $element->get_locale( 'display' ) ) ) : '',
|
28 |
-
isset( $args['selected'] ) && $args['selected'] === $element->$value
|
29 |
esc_html( $element->name )
|
30 |
);
|
31 |
}
|
@@ -85,7 +85,7 @@ class PLL_Walker_Dropdown extends Walker {
|
|
85 |
$name = esc_attr( $args['name'] ),
|
86 |
isset( $args['id'] ) && ! $args['id'] ? '' : ' id="' . ( empty( $args['id'] ) ? $name : esc_attr( $args['id'] ) ) . '"',
|
87 |
empty( $args['class'] ) ? '' : ' class="' . esc_attr( $args['class'] ) . '"',
|
88 |
-
empty( $args['disabled'] )
|
89 |
parent::walk( $elements, -1, $args )
|
90 |
);
|
91 |
|
25 |
"\t" . '<option value="%1$s"%2$s%3$s>%4$s</option>' . "\n",
|
26 |
esc_attr( $element->$value ),
|
27 |
method_exists( $element, 'get_locale' ) ? sprintf( ' lang="%s"', esc_attr( $element->get_locale( 'display' ) ) ) : '',
|
28 |
+
selected( isset( $args['selected'] ) && $args['selected'] === $element->$value, true, false ),
|
29 |
esc_html( $element->name )
|
30 |
);
|
31 |
}
|
85 |
$name = esc_attr( $args['name'] ),
|
86 |
isset( $args['id'] ) && ! $args['id'] ? '' : ' id="' . ( empty( $args['id'] ) ? $name : esc_attr( $args['id'] ) ) . '"',
|
87 |
empty( $args['class'] ) ? '' : ' class="' . esc_attr( $args['class'] ) . '"',
|
88 |
+
disabled( empty( $args['disabled'] ), false, false ),
|
89 |
parent::walk( $elements, -1, $args )
|
90 |
);
|
91 |
|
include/widget-languages.php
CHANGED
@@ -15,7 +15,7 @@ class PLL_Widget_Languages extends WP_Widget {
|
|
15 |
public function __construct() {
|
16 |
parent::__construct(
|
17 |
'polylang',
|
18 |
-
__( 'Language
|
19 |
array(
|
20 |
'description' => __( 'Displays a language switcher', 'polylang' ),
|
21 |
'customize_selective_refresh' => true,
|
@@ -40,17 +40,17 @@ class PLL_Widget_Languages extends WP_Widget {
|
|
40 |
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
|
41 |
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
|
42 |
|
43 |
-
echo $args['before_widget'];
|
44 |
if ( $title ) {
|
45 |
-
echo $args['before_title'] . $title . $args['after_title'];
|
46 |
}
|
47 |
if ( $instance['dropdown'] ) {
|
48 |
echo '<label class="screen-reader-text" for="' . esc_attr( 'lang_choice_' . $instance['dropdown'] ) . '">' . esc_html__( 'Choose a language', 'polylang' ) . '</label>';
|
49 |
-
echo $list;
|
50 |
} else {
|
51 |
-
echo "<ul>\n" . $list . "</ul>\n";
|
52 |
}
|
53 |
-
echo $args['after_widget'];
|
54 |
}
|
55 |
}
|
56 |
|
@@ -64,7 +64,7 @@ class PLL_Widget_Languages extends WP_Widget {
|
|
64 |
* @return array Settings to save or bool false to cancel saving
|
65 |
*/
|
66 |
public function update( $new_instance, $old_instance ) {
|
67 |
-
$instance['title'] =
|
68 |
foreach ( array_keys( PLL_Switcher::get_switcher_options( 'widget' ) ) as $key ) {
|
69 |
$instance[ $key ] = ! empty( $new_instance[ $key ] ) ? 1 : 0;
|
70 |
}
|
@@ -86,28 +86,25 @@ class PLL_Widget_Languages extends WP_Widget {
|
|
86 |
// Title
|
87 |
printf(
|
88 |
'<p><label for="%1$s">%2$s</label><input class="widefat" id="%1$s" name="%3$s" type="text" value="%4$s" /></p>',
|
89 |
-
$this->get_field_id( 'title' ),
|
90 |
esc_html__( 'Title:', 'polylang' ),
|
91 |
-
$this->get_field_name( 'title' ),
|
92 |
esc_attr( $instance['title'] )
|
93 |
);
|
94 |
|
95 |
-
$fields = '';
|
96 |
foreach ( PLL_Switcher::get_switcher_options( 'widget' ) as $key => $str ) {
|
97 |
-
|
98 |
'<div%5$s%6$s><input type="checkbox" class="checkbox %7$s" id="%1$s" name="%2$s"%3$s /><label for="%1$s">%4$s</label></div>',
|
99 |
-
$this->get_field_id( $key ),
|
100 |
-
$this->get_field_name( $key ),
|
101 |
-
$instance[ $key ]
|
102 |
esc_html( $str ),
|
103 |
-
in_array( $key, array( 'show_names', 'show_flags', 'hide_current' ) ) ? ' class="no-dropdown
|
104 |
-
! empty( $instance['dropdown'] ) && in_array( $key, array( 'show_names', 'show_flags', 'hide_current' ) ) ? ' style="display:none;"' : '',
|
105 |
-
'pll-' . $key
|
106 |
);
|
107 |
}
|
108 |
|
109 |
-
echo $fields;
|
110 |
-
|
111 |
// FIXME echoing script in form is not very clean
|
112 |
// but it does not work if enqueued properly :
|
113 |
// clicking save on a widget makes this code unreachable for the just saved widget ( ?! )
|
15 |
public function __construct() {
|
16 |
parent::__construct(
|
17 |
'polylang',
|
18 |
+
__( 'Language switcher', 'polylang' ),
|
19 |
array(
|
20 |
'description' => __( 'Displays a language switcher', 'polylang' ),
|
21 |
'customize_selective_refresh' => true,
|
40 |
/** This filter is documented in wp-includes/widgets/class-wp-widget-pages.php */
|
41 |
$title = apply_filters( 'widget_title', $title, $instance, $this->id_base );
|
42 |
|
43 |
+
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput
|
44 |
if ( $title ) {
|
45 |
+
echo $args['before_title'] . $title . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput
|
46 |
}
|
47 |
if ( $instance['dropdown'] ) {
|
48 |
echo '<label class="screen-reader-text" for="' . esc_attr( 'lang_choice_' . $instance['dropdown'] ) . '">' . esc_html__( 'Choose a language', 'polylang' ) . '</label>';
|
49 |
+
echo $list; // phpcs:ignore WordPress.Security.EscapeOutput
|
50 |
} else {
|
51 |
+
echo "<ul>\n" . $list . "</ul>\n"; // phpcs:ignore WordPress.Security.EscapeOutput
|
52 |
}
|
53 |
+
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput
|
54 |
}
|
55 |
}
|
56 |
|
64 |
* @return array Settings to save or bool false to cancel saving
|
65 |
*/
|
66 |
public function update( $new_instance, $old_instance ) {
|
67 |
+
$instance['title'] = sanitize_text_field( $new_instance['title'] );
|
68 |
foreach ( array_keys( PLL_Switcher::get_switcher_options( 'widget' ) ) as $key ) {
|
69 |
$instance[ $key ] = ! empty( $new_instance[ $key ] ) ? 1 : 0;
|
70 |
}
|
86 |
// Title
|
87 |
printf(
|
88 |
'<p><label for="%1$s">%2$s</label><input class="widefat" id="%1$s" name="%3$s" type="text" value="%4$s" /></p>',
|
89 |
+
esc_attr( $this->get_field_id( 'title' ) ),
|
90 |
esc_html__( 'Title:', 'polylang' ),
|
91 |
+
esc_attr( $this->get_field_name( 'title' ) ),
|
92 |
esc_attr( $instance['title'] )
|
93 |
);
|
94 |
|
|
|
95 |
foreach ( PLL_Switcher::get_switcher_options( 'widget' ) as $key => $str ) {
|
96 |
+
printf(
|
97 |
'<div%5$s%6$s><input type="checkbox" class="checkbox %7$s" id="%1$s" name="%2$s"%3$s /><label for="%1$s">%4$s</label></div>',
|
98 |
+
esc_attr( $this->get_field_id( $key ) ),
|
99 |
+
esc_attr( $this->get_field_name( $key ) ),
|
100 |
+
checked( $instance[ $key ], true, false ),
|
101 |
esc_html( $str ),
|
102 |
+
in_array( $key, array( 'show_names', 'show_flags', 'hide_current' ) ) ? sprintf( ' class="no-dropdown-%s"', esc_attr( $this->id ) ) : '',
|
103 |
+
( ! empty( $instance['dropdown'] ) && in_array( $key, array( 'show_names', 'show_flags', 'hide_current' ) ) ? ' style="display:none;"' : '' ),
|
104 |
+
esc_attr( 'pll-' . $key )
|
105 |
);
|
106 |
}
|
107 |
|
|
|
|
|
108 |
// FIXME echoing script in form is not very clean
|
109 |
// but it does not work if enqueued properly :
|
110 |
// clicking save on a widget makes this code unreachable for the just saved widget ( ?! )
|
install/install-base.php
CHANGED
@@ -34,7 +34,7 @@ class PLL_Install_Base {
|
|
34 |
* @return bool true if the plugin is currently beeing deactivated
|
35 |
*/
|
36 |
public function is_deactivation() {
|
37 |
-
return isset( $_GET['action'], $_GET['plugin'] ) && 'deactivate'
|
38 |
}
|
39 |
|
40 |
/**
|
34 |
* @return bool true if the plugin is currently beeing deactivated
|
35 |
*/
|
36 |
public function is_deactivation() {
|
37 |
+
return isset( $_GET['action'], $_GET['plugin'] ) && 'deactivate' === $_GET['action'] && $this->plugin_basename === $_GET['plugin']; // phpcs:ignore WordPress.Security.NonceVerification
|
38 |
}
|
39 |
|
40 |
/**
|
install/install.php
CHANGED
@@ -29,7 +29,7 @@ class PLL_Install extends PLL_Install_Base {
|
|
29 |
/* translators: %1$s and %2$s are WordPress version numbers */
|
30 |
esc_html__( 'You are using WordPress %1$s. Polylang requires at least WordPress %2$s.', 'polylang' ),
|
31 |
esc_html( $wp_version ),
|
32 |
-
PLL_MIN_WP_VERSION
|
33 |
)
|
34 |
)
|
35 |
);
|
29 |
/* translators: %1$s and %2$s are WordPress version numbers */
|
30 |
esc_html__( 'You are using WordPress %1$s. Polylang requires at least WordPress %2$s.', 'polylang' ),
|
31 |
esc_html( $wp_version ),
|
32 |
+
PLL_MIN_WP_VERSION // phpcs:ignore WordPress.Security.EscapeOutput
|
33 |
)
|
34 |
)
|
35 |
);
|
install/plugin-updater.php
CHANGED
@@ -10,7 +10,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
10 |
* Modified version with 'polylang' text domain and comments for translators
|
11 |
*
|
12 |
* @author Easy Digital Downloads
|
13 |
-
* @version 1.6.
|
14 |
*/
|
15 |
class PLL_Plugin_Updater {
|
16 |
|
@@ -22,6 +22,8 @@ class PLL_Plugin_Updater {
|
|
22 |
private $wp_override = false;
|
23 |
private $cache_key = '';
|
24 |
|
|
|
|
|
25 |
/**
|
26 |
* Class constructor.
|
27 |
*
|
@@ -122,6 +124,9 @@ class PLL_Plugin_Updater {
|
|
122 |
|
123 |
$_transient_data->response[ $this->name ] = $version_info;
|
124 |
|
|
|
|
|
|
|
125 |
}
|
126 |
|
127 |
$_transient_data->last_checked = time();
|
@@ -170,6 +175,19 @@ class PLL_Plugin_Updater {
|
|
170 |
if ( false === $version_info ) {
|
171 |
$version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug, 'beta' => $this->beta ) );
|
172 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
$this->set_version_info_cache( $version_info );
|
174 |
}
|
175 |
|
@@ -265,7 +283,8 @@ class PLL_Plugin_Updater {
|
|
265 |
'is_ssl' => is_ssl(),
|
266 |
'fields' => array(
|
267 |
'banners' => array(),
|
268 |
-
'reviews' => false
|
|
|
269 |
)
|
270 |
);
|
271 |
|
@@ -292,27 +311,47 @@ class PLL_Plugin_Updater {
|
|
292 |
|
293 |
// Convert sections into an associative array, since we're getting an object, but Core expects an array.
|
294 |
if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
|
295 |
-
$
|
296 |
-
foreach ( $_data->sections as $key => $value ) {
|
297 |
-
$new_sections[ $key ] = $value;
|
298 |
-
}
|
299 |
-
|
300 |
-
$_data->sections = $new_sections;
|
301 |
}
|
302 |
|
303 |
// Convert banners into an associative array, since we're getting an object, but Core expects an array.
|
304 |
if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
|
305 |
-
$
|
306 |
-
|
307 |
-
$new_banners[ $key ] = $value;
|
308 |
-
}
|
309 |
|
310 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
311 |
}
|
312 |
|
313 |
return $_data;
|
314 |
}
|
315 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
316 |
/**
|
317 |
* Disable SSL verification in order to prevent download update failures
|
318 |
*
|
@@ -343,7 +382,31 @@ class PLL_Plugin_Updater {
|
|
343 |
*/
|
344 |
private function api_request( $_action, $_data ) {
|
345 |
|
346 |
-
global $wp_version;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
347 |
|
348 |
$data = array_merge( $this->api_data, $_data );
|
349 |
|
@@ -351,7 +414,7 @@ class PLL_Plugin_Updater {
|
|
351 |
return;
|
352 |
}
|
353 |
|
354 |
-
if( $this->api_url == trailingslashit (home_url() ) ) {
|
355 |
return false; // Don't allow a plugin to ping itself
|
356 |
}
|
357 |
|
@@ -367,7 +430,6 @@ class PLL_Plugin_Updater {
|
|
367 |
'beta' => ! empty( $data['beta'] ),
|
368 |
);
|
369 |
|
370 |
-
$verify_ssl = $this->verify_ssl();
|
371 |
$request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
|
372 |
|
373 |
if ( ! is_wp_error( $request ) ) {
|
@@ -384,6 +446,10 @@ class PLL_Plugin_Updater {
|
|
384 |
$request->banners = maybe_unserialize( $request->banners );
|
385 |
}
|
386 |
|
|
|
|
|
|
|
|
|
387 |
if( ! empty( $request->sections ) ) {
|
388 |
foreach( $request->sections as $key => $section ) {
|
389 |
$request->$key = (array) $section;
|
@@ -473,7 +539,13 @@ class PLL_Plugin_Updater {
|
|
473 |
return false; // Cache is expired
|
474 |
}
|
475 |
|
476 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
477 |
|
478 |
}
|
479 |
|
10 |
* Modified version with 'polylang' text domain and comments for translators
|
11 |
*
|
12 |
* @author Easy Digital Downloads
|
13 |
+
* @version 1.6.18
|
14 |
*/
|
15 |
class PLL_Plugin_Updater {
|
16 |
|
22 |
private $wp_override = false;
|
23 |
private $cache_key = '';
|
24 |
|
25 |
+
private $health_check_timeout = 5;
|
26 |
+
|
27 |
/**
|
28 |
* Class constructor.
|
29 |
*
|
124 |
|
125 |
$_transient_data->response[ $this->name ] = $version_info;
|
126 |
|
127 |
+
// Make sure the plugin property is set to the plugin's name/location. See issue 1463 on Software Licensing's GitHub repo.
|
128 |
+
$_transient_data->response[ $this->name ]->plugin = $this->name;
|
129 |
+
|
130 |
}
|
131 |
|
132 |
$_transient_data->last_checked = time();
|
175 |
if ( false === $version_info ) {
|
176 |
$version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug, 'beta' => $this->beta ) );
|
177 |
|
178 |
+
// Since we disabled our filter for the transient, we aren't running our object conversion on banners, sections, or icons. Do this now:
|
179 |
+
if ( isset( $version_info->banners ) && ! is_array( $version_info->banners ) ) {
|
180 |
+
$version_info->banners = $this->convert_object_to_array( $version_info->banners );
|
181 |
+
}
|
182 |
+
|
183 |
+
if ( isset( $version_info->sections ) && ! is_array( $version_info->sections ) ) {
|
184 |
+
$version_info->sections = $this->convert_object_to_array( $version_info->sections );
|
185 |
+
}
|
186 |
+
|
187 |
+
if ( isset( $version_info->icons ) && ! is_array( $version_info->icons ) ) {
|
188 |
+
$version_info->icons = $this->convert_object_to_array( $version_info->icons );
|
189 |
+
}
|
190 |
+
|
191 |
$this->set_version_info_cache( $version_info );
|
192 |
}
|
193 |
|
283 |
'is_ssl' => is_ssl(),
|
284 |
'fields' => array(
|
285 |
'banners' => array(),
|
286 |
+
'reviews' => false,
|
287 |
+
'icons' => array(),
|
288 |
)
|
289 |
);
|
290 |
|
311 |
|
312 |
// Convert sections into an associative array, since we're getting an object, but Core expects an array.
|
313 |
if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
|
314 |
+
$_data->sections = $this->convert_object_to_array( $_data->sections );
|
|
|
|
|
|
|
|
|
|
|
315 |
}
|
316 |
|
317 |
// Convert banners into an associative array, since we're getting an object, but Core expects an array.
|
318 |
if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
|
319 |
+
$_data->banners = $this->convert_object_to_array( $_data->banners );
|
320 |
+
}
|
|
|
|
|
321 |
|
322 |
+
// Convert icons into an associative array, since we're getting an object, but Core expects an array.
|
323 |
+
if ( isset( $_data->icons ) && ! is_array( $_data->icons ) ) {
|
324 |
+
$_data->icons = $this->convert_object_to_array( $_data->icons );
|
325 |
+
}
|
326 |
+
|
327 |
+
if( ! isset( $_data->plugin ) ) {
|
328 |
+
$_data->plugin = $this->name;
|
329 |
}
|
330 |
|
331 |
return $_data;
|
332 |
}
|
333 |
|
334 |
+
/**
|
335 |
+
* Convert some objects to arrays when injecting data into the update API
|
336 |
+
*
|
337 |
+
* Some data like sections, banners, and icons are expected to be an associative array, however due to the JSON
|
338 |
+
* decoding, they are objects. This method allows us to pass in the object and return an associative array.
|
339 |
+
*
|
340 |
+
* @since 3.6.5
|
341 |
+
*
|
342 |
+
* @param stdClass $data
|
343 |
+
*
|
344 |
+
* @return array
|
345 |
+
*/
|
346 |
+
private function convert_object_to_array( $data ) {
|
347 |
+
$new_data = array();
|
348 |
+
foreach ( $data as $key => $value ) {
|
349 |
+
$new_data[ $key ] = $value;
|
350 |
+
}
|
351 |
+
|
352 |
+
return $new_data;
|
353 |
+
}
|
354 |
+
|
355 |
/**
|
356 |
* Disable SSL verification in order to prevent download update failures
|
357 |
*
|
382 |
*/
|
383 |
private function api_request( $_action, $_data ) {
|
384 |
|
385 |
+
global $wp_version, $edd_plugin_url_available;
|
386 |
+
|
387 |
+
$verify_ssl = $this->verify_ssl();
|
388 |
+
|
389 |
+
// Do a quick status check on this domain if we haven't already checked it.
|
390 |
+
$store_hash = md5( $this->api_url );
|
391 |
+
if ( ! is_array( $edd_plugin_url_available ) || ! isset( $edd_plugin_url_available[ $store_hash ] ) ) {
|
392 |
+
$test_url_parts = parse_url( $this->api_url );
|
393 |
+
|
394 |
+
$scheme = ! empty( $test_url_parts['scheme'] ) ? $test_url_parts['scheme'] : 'http';
|
395 |
+
$host = ! empty( $test_url_parts['host'] ) ? $test_url_parts['host'] : '';
|
396 |
+
$port = ! empty( $test_url_parts['port'] ) ? ':' . $test_url_parts['port'] : '';
|
397 |
+
|
398 |
+
if ( empty( $host ) ) {
|
399 |
+
$edd_plugin_url_available[ $store_hash ] = false;
|
400 |
+
} else {
|
401 |
+
$test_url = $scheme . '://' . $host . $port;
|
402 |
+
$response = wp_remote_get( $test_url, array( 'timeout' => $this->health_check_timeout, 'sslverify' => $verify_ssl ) );
|
403 |
+
$edd_plugin_url_available[ $store_hash ] = is_wp_error( $response ) ? false : true;
|
404 |
+
}
|
405 |
+
}
|
406 |
+
|
407 |
+
if ( false === $edd_plugin_url_available[ $store_hash ] ) {
|
408 |
+
return;
|
409 |
+
}
|
410 |
|
411 |
$data = array_merge( $this->api_data, $_data );
|
412 |
|
414 |
return;
|
415 |
}
|
416 |
|
417 |
+
if( $this->api_url == trailingslashit ( home_url() ) ) {
|
418 |
return false; // Don't allow a plugin to ping itself
|
419 |
}
|
420 |
|
430 |
'beta' => ! empty( $data['beta'] ),
|
431 |
);
|
432 |
|
|
|
433 |
$request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
|
434 |
|
435 |
if ( ! is_wp_error( $request ) ) {
|
446 |
$request->banners = maybe_unserialize( $request->banners );
|
447 |
}
|
448 |
|
449 |
+
if ( $request && isset( $request->icons ) ) {
|
450 |
+
$request->icons = maybe_unserialize( $request->icons );
|
451 |
+
}
|
452 |
+
|
453 |
if( ! empty( $request->sections ) ) {
|
454 |
foreach( $request->sections as $key => $section ) {
|
455 |
$request->$key = (array) $section;
|
539 |
return false; // Cache is expired
|
540 |
}
|
541 |
|
542 |
+
// We need to turn the icons into an array, thanks to WP Core forcing these into an object at some point.
|
543 |
+
$cache['value'] = json_decode( $cache['value'] );
|
544 |
+
if ( ! empty( $cache['value']->icons ) ) {
|
545 |
+
$cache['value']->icons = (array) $cache['value']->icons;
|
546 |
+
}
|
547 |
+
|
548 |
+
return $cache['value'];
|
549 |
|
550 |
}
|
551 |
|
install/t15s.php
ADDED
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Allows to download translations from TranslationsPress
|
5 |
+
* This is a modified version of the library available at https://github.com/WP-Translations/t15s-registry
|
6 |
+
* This version aims to be compatible with PHP 5.2, and supports only plugins.
|
7 |
+
*
|
8 |
+
* @since 2.6
|
9 |
+
*/
|
10 |
+
class PLL_T15S {
|
11 |
+
|
12 |
+
const TRANSIENT_KEY_PLUGIN = 't15s-registry-plugins';
|
13 |
+
|
14 |
+
private $type = 'plugin';
|
15 |
+
private $slug = '';
|
16 |
+
private $api_url = '';
|
17 |
+
|
18 |
+
/**
|
19 |
+
* Adds a new project to load translations for.
|
20 |
+
*
|
21 |
+
* @since 2.6
|
22 |
+
*
|
23 |
+
* @param string $slug Project directory slug.
|
24 |
+
* @param string $api_url Full GlotPress API URL for the project.
|
25 |
+
*/
|
26 |
+
public function __construct( $slug, $api_url ) {
|
27 |
+
$this->slug = $slug;
|
28 |
+
$this->api_url = $api_url;
|
29 |
+
|
30 |
+
add_action( 'init', array( __CLASS__, 'register_clean_translations_cache' ), 9999 );
|
31 |
+
add_filter( 'translations_api', array( $this, 'translations_api' ), 10, 3 );
|
32 |
+
add_filter( 'site_transient_update_' . $this->type . 's', array( $this, 'site_transient_update_plugins' ) );
|
33 |
+
}
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Short-circuits translations API requests for private projects.
|
37 |
+
*
|
38 |
+
* @since 2.6
|
39 |
+
*
|
40 |
+
* @param bool|array $result The result object. Default false.
|
41 |
+
* @param string $requested_type The type of translations being requested.
|
42 |
+
* @param object $args Translation API arguments.
|
43 |
+
* @return bool|array
|
44 |
+
*/
|
45 |
+
public function translations_api( $result, $requested_type, $args ) {
|
46 |
+
if ( $this->type . 's' === $requested_type && $this->slug === $args['slug'] ) {
|
47 |
+
return self::get_translations( $this->type, $args['slug'], $this->api_url );
|
48 |
+
}
|
49 |
+
|
50 |
+
return $result;
|
51 |
+
}
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Filters the translations transients to include the private plugin or theme.
|
55 |
+
*
|
56 |
+
* @see wp_get_translation_updates()
|
57 |
+
*
|
58 |
+
* @since 2.6
|
59 |
+
*
|
60 |
+
* @param bool|array $value The transient value.
|
61 |
+
*/
|
62 |
+
public function site_transient_update_plugins( $value ) {
|
63 |
+
if ( ! $value ) {
|
64 |
+
$value = new stdClass();
|
65 |
+
}
|
66 |
+
|
67 |
+
if ( ! isset( $value->translations ) ) {
|
68 |
+
$value->translations = array();
|
69 |
+
}
|
70 |
+
|
71 |
+
$translations = self::get_translations( $this->type, $this->slug, $this->api_url );
|
72 |
+
|
73 |
+
if ( ! isset( $translations['translations'] ) ) {
|
74 |
+
return $value;
|
75 |
+
}
|
76 |
+
|
77 |
+
$installed_translations = wp_get_installed_translations( $this->type . 's' );
|
78 |
+
|
79 |
+
foreach ( (array) $translations['translations'] as $translation ) {
|
80 |
+
if ( in_array( $translation['language'], get_available_languages() ) ) {
|
81 |
+
if ( isset( $installed_translations[ $this->slug ][ $translation['language'] ] ) && $translation['updated'] ) {
|
82 |
+
$local = new DateTime( $installed_translations[ $this->slug ][ $translation['language'] ]['PO-Revision-Date'] );
|
83 |
+
$remote = new DateTime( $translation['updated'] );
|
84 |
+
|
85 |
+
if ( $local >= $remote ) {
|
86 |
+
continue;
|
87 |
+
}
|
88 |
+
}
|
89 |
+
|
90 |
+
$translation['type'] = $this->type;
|
91 |
+
$translation['slug'] = $this->slug;
|
92 |
+
|
93 |
+
$value->translations[] = $translation;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
|
97 |
+
return $value;
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Registers actions for clearing translation caches.
|
102 |
+
*
|
103 |
+
* @since 2.6
|
104 |
+
*/
|
105 |
+
public static function register_clean_translations_cache() {
|
106 |
+
add_action( 'set_site_transient_update_plugins', array( __CLASS__, 'clean_translations_cache' ) );
|
107 |
+
add_action( 'delete_site_transient_update_plugins', array( __CLASS__, 'clean_translations_cache' ) );
|
108 |
+
}
|
109 |
+
|
110 |
+
/**
|
111 |
+
* Clears existing translation cache.
|
112 |
+
*
|
113 |
+
* @since 2.6
|
114 |
+
*/
|
115 |
+
public static function clean_translations_cache() {
|
116 |
+
$translations = get_site_transient( self::TRANSIENT_KEY_PLUGIN );
|
117 |
+
|
118 |
+
if ( ! is_object( $translations ) ) {
|
119 |
+
return;
|
120 |
+
}
|
121 |
+
|
122 |
+
/*
|
123 |
+
* Don't delete the cache if the transient gets changed multiple times
|
124 |
+
* during a single request. Set cache lifetime to maximum 15 seconds.
|
125 |
+
*/
|
126 |
+
$cache_lifespan = 15;
|
127 |
+
$time_not_changed = isset( $translations->_last_checked ) && ( time() - $translations->_last_checked ) > $cache_lifespan;
|
128 |
+
|
129 |
+
if ( ! $time_not_changed ) {
|
130 |
+
return;
|
131 |
+
}
|
132 |
+
|
133 |
+
delete_site_transient( self::TRANSIENT_KEY_PLUGIN );
|
134 |
+
}
|
135 |
+
|
136 |
+
/**
|
137 |
+
* Gets the translations for a given project.
|
138 |
+
*
|
139 |
+
* @since 2.6
|
140 |
+
*
|
141 |
+
* @param string $type Project type. Either plugin or theme.
|
142 |
+
* @param string $slug Project directory slug.
|
143 |
+
* @param string $url Full GlotPress API URL for the project.
|
144 |
+
* @return array Translation data.
|
145 |
+
*/
|
146 |
+
private static function get_translations( $type, $slug, $url ) {
|
147 |
+
$translations = get_site_transient( self::TRANSIENT_KEY_PLUGIN );
|
148 |
+
|
149 |
+
if ( ! is_object( $translations ) ) {
|
150 |
+
$translations = new stdClass();
|
151 |
+
}
|
152 |
+
|
153 |
+
if ( isset( $translations->{$slug} ) && is_array( $translations->{$slug} ) ) {
|
154 |
+
return $translations->{$slug};
|
155 |
+
}
|
156 |
+
|
157 |
+
$result = json_decode( wp_remote_retrieve_body( wp_remote_get( $url, array( 'timeout' => 2 ) ) ), true );
|
158 |
+
if ( is_array( $result ) ) {
|
159 |
+
$translations->{$slug} = $result;
|
160 |
+
$translations->_last_checked = time();
|
161 |
+
|
162 |
+
set_site_transient( self::TRANSIENT_KEY_PLUGIN, $translations );
|
163 |
+
return $result;
|
164 |
+
}
|
165 |
+
|
166 |
+
// Nothing found.
|
167 |
+
return array();
|
168 |
+
}
|
169 |
+
}
|
install/upgrade.php
CHANGED
@@ -28,7 +28,7 @@ class PLL_Upgrade {
|
|
28 |
if ( ! $this->can_upgrade() ) {
|
29 |
ob_start();
|
30 |
$this->admin_notices(); // FIXME the error message is displayed two times
|
31 |
-
die( ob_get_contents() );
|
32 |
}
|
33 |
}
|
34 |
|
@@ -76,9 +76,9 @@ class PLL_Upgrade {
|
|
76 |
esc_html__( 'Polylang has been deactivated because you upgraded from a too old version.', 'polylang' ),
|
77 |
sprintf(
|
78 |
/* translators: %1$s and %2$s are Polylang version numbers */
|
79 |
-
esc_html__( '
|
80 |
'<strong>0.9.8</strong>',
|
81 |
-
POLYLANG_VERSION
|
82 |
)
|
83 |
);
|
84 |
}
|
@@ -184,7 +184,7 @@ class PLL_Upgrade {
|
|
184 |
foreach ( $languages as $lang ) {
|
185 |
// First update language with new storage for locale and text direction
|
186 |
$text_direction = get_metadata( 'term', $lang->term_id, '_rtl', true );
|
187 |
-
$desc =
|
188 |
wp_update_term( (int) $lang->term_id, 'language', array( 'description' => $desc ) );
|
189 |
|
190 |
// Add language to new 'term_language' taxonomy
|
@@ -212,7 +212,7 @@ class PLL_Upgrade {
|
|
212 |
$terms = $slugs = $tts = $trs = array();
|
213 |
|
214 |
// Get all translated objects
|
215 |
-
// PHPCS:ignore WordPress.DB.PreparedSQL
|
216 |
$objects = $wpdb->get_col( "SELECT DISTINCT meta_value FROM {$wpdb->$table} WHERE meta_key = '_translations'" );
|
217 |
|
218 |
if ( empty( $objects ) ) {
|
@@ -223,8 +223,8 @@ class PLL_Upgrade {
|
|
223 |
$term = uniqid( 'pll_' ); // The term name
|
224 |
$terms[] = $wpdb->prepare( '( %s, %s )', $term, $term );
|
225 |
$slugs[] = $wpdb->prepare( '%s', $term );
|
226 |
-
$translations = maybe_unserialize( maybe_unserialize( $obj ) ); // 2
|
227 |
-
$description[ $term ] =
|
228 |
}
|
229 |
|
230 |
$terms = array_unique( $terms );
|
@@ -257,7 +257,7 @@ class PLL_Upgrade {
|
|
257 |
|
258 |
// Prepare objects relationships
|
259 |
foreach ( $terms as $term ) {
|
260 |
-
$translations =
|
261 |
foreach ( $translations as $object_id ) {
|
262 |
if ( ! empty( $object_id ) ) {
|
263 |
$trs[] = $wpdb->prepare( '( %d, %d )', $object_id, $term->term_taxonomy_id );
|
@@ -549,7 +549,7 @@ class PLL_Upgrade {
|
|
549 |
*/
|
550 |
protected function upgrade_1_8() {
|
551 |
// Adds the flag code in languages stored in DB
|
552 |
-
include PLL_SETTINGS_INC . '/languages.php';
|
553 |
|
554 |
$terms = get_terms( 'language', array( 'hide_empty' => 0 ) );
|
555 |
|
@@ -557,7 +557,7 @@ class PLL_Upgrade {
|
|
557 |
$description = maybe_unserialize( $lang->description );
|
558 |
if ( isset( $languages[ $description['locale'] ] ) ) {
|
559 |
$description['flag_code'] = $languages[ $description['locale'] ]['flag'];
|
560 |
-
$description =
|
561 |
wp_update_term( (int) $lang->term_id, 'language', array( 'description' => $description ) );
|
562 |
}
|
563 |
}
|
@@ -589,7 +589,7 @@ class PLL_Upgrade {
|
|
589 |
|
590 |
if ( empty( $meta ) ) {
|
591 |
$post = get_post( $mo_id, OBJECT );
|
592 |
-
$strings =
|
593 |
if ( is_array( $strings ) ) {
|
594 |
update_post_meta( $mo_id, '_pll_strings_translations', $strings );
|
595 |
}
|
28 |
if ( ! $this->can_upgrade() ) {
|
29 |
ob_start();
|
30 |
$this->admin_notices(); // FIXME the error message is displayed two times
|
31 |
+
die( ob_get_contents() ); // phpcs:ignore WordPress.Security.EscapeOutput
|
32 |
}
|
33 |
}
|
34 |
|
76 |
esc_html__( 'Polylang has been deactivated because you upgraded from a too old version.', 'polylang' ),
|
77 |
sprintf(
|
78 |
/* translators: %1$s and %2$s are Polylang version numbers */
|
79 |
+
esc_html__( 'Before upgrading to %2$s, please upgrade to %1$s.', 'polylang' ),
|
80 |
'<strong>0.9.8</strong>',
|
81 |
+
POLYLANG_VERSION // phpcs:ignore WordPress.Security.EscapeOutput
|
82 |
)
|
83 |
);
|
84 |
}
|
184 |
foreach ( $languages as $lang ) {
|
185 |
// First update language with new storage for locale and text direction
|
186 |
$text_direction = get_metadata( 'term', $lang->term_id, '_rtl', true );
|
187 |
+
$desc = maybe_serialize( array( 'locale' => $lang->description, 'rtl' => $text_direction ) );
|
188 |
wp_update_term( (int) $lang->term_id, 'language', array( 'description' => $desc ) );
|
189 |
|
190 |
// Add language to new 'term_language' taxonomy
|
212 |
$terms = $slugs = $tts = $trs = array();
|
213 |
|
214 |
// Get all translated objects
|
215 |
+
// PHPCS:ignore WordPress.DB.PreparedSQL
|
216 |
$objects = $wpdb->get_col( "SELECT DISTINCT meta_value FROM {$wpdb->$table} WHERE meta_key = '_translations'" );
|
217 |
|
218 |
if ( empty( $objects ) ) {
|
223 |
$term = uniqid( 'pll_' ); // The term name
|
224 |
$terms[] = $wpdb->prepare( '( %s, %s )', $term, $term );
|
225 |
$slugs[] = $wpdb->prepare( '%s', $term );
|
226 |
+
$translations = maybe_unserialize( maybe_unserialize( $obj ) ); // 2 maybe_unserialize due to an old storage bug
|
227 |
+
$description[ $term ] = maybe_serialize( $translations );
|
228 |
}
|
229 |
|
230 |
$terms = array_unique( $terms );
|
257 |
|
258 |
// Prepare objects relationships
|
259 |
foreach ( $terms as $term ) {
|
260 |
+
$translations = maybe_unserialize( $term->description );
|
261 |
foreach ( $translations as $object_id ) {
|
262 |
if ( ! empty( $object_id ) ) {
|
263 |
$trs[] = $wpdb->prepare( '( %d, %d )', $object_id, $term->term_taxonomy_id );
|
549 |
*/
|
550 |
protected function upgrade_1_8() {
|
551 |
// Adds the flag code in languages stored in DB
|
552 |
+
$languages = include PLL_SETTINGS_INC . '/languages.php';
|
553 |
|
554 |
$terms = get_terms( 'language', array( 'hide_empty' => 0 ) );
|
555 |
|
557 |
$description = maybe_unserialize( $lang->description );
|
558 |
if ( isset( $languages[ $description['locale'] ] ) ) {
|
559 |
$description['flag_code'] = $languages[ $description['locale'] ]['flag'];
|
560 |
+
$description = maybe_serialize( $description );
|
561 |
wp_update_term( (int) $lang->term_id, 'language', array( 'description' => $description ) );
|
562 |
}
|
563 |
}
|
589 |
|
590 |
if ( empty( $meta ) ) {
|
591 |
$post = get_post( $mo_id, OBJECT );
|
592 |
+
$strings = maybe_unserialize( $post->post_content );
|
593 |
if ( is_array( $strings ) ) {
|
594 |
update_post_meta( $mo_id, '_pll_strings_translations', $strings );
|
595 |
}
|
js/block-editor.js
CHANGED
@@ -29,7 +29,7 @@ function getCurrentLanguage() {
|
|
29 |
}
|
30 |
|
31 |
/**
|
32 |
-
*
|
33 |
*
|
34 |
* @since 2.5
|
35 |
*/
|
@@ -90,3 +90,95 @@ jQuery( document ).ready(function( $ ) {
|
|
90 |
} );
|
91 |
} );
|
92 |
} );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
}
|
30 |
|
31 |
/**
|
32 |
+
* Save post after lang choice is done and redirect to the same page for refreshing all the data
|
33 |
*
|
34 |
* @since 2.5
|
35 |
*/
|
90 |
} );
|
91 |
} );
|
92 |
} );
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Handles internals of the metabox:
|
96 |
+
* Language select, autocomplete input field and buttons.
|
97 |
+
*
|
98 |
+
* @since 1.5
|
99 |
+
*/
|
100 |
+
jQuery( document ).ready(function( $ ) {
|
101 |
+
// Ajax for changing the post's language in the languages metabox
|
102 |
+
$( '.post_lang_choice' ).change(function() {
|
103 |
+
var data = {
|
104 |
+
action: 'post_lang_choice',
|
105 |
+
lang: $( this ).val(),
|
106 |
+
post_type: $( '#post_type' ).val(),
|
107 |
+
post_id: $( '#post_ID' ).val(),
|
108 |
+
_pll_nonce: $( '#_pll_nonce' ).val()
|
109 |
+
}
|
110 |
+
|
111 |
+
$.post( ajaxurl, data , function( response ) {
|
112 |
+
var res = wpAjax.parseAjaxResponse( response, 'ajax-response' );
|
113 |
+
$.each( res.responses, function() {
|
114 |
+
switch ( this.what ) {
|
115 |
+
case 'translations': // Translations fields
|
116 |
+
$( '.translations' ).html( this.data );
|
117 |
+
init_translations();
|
118 |
+
break;
|
119 |
+
case 'flag': // Flag in front of the select dropdown
|
120 |
+
$( '.pll-select-flag' ).html( this.data );
|
121 |
+
break;
|
122 |
+
}
|
123 |
+
});
|
124 |
+
});
|
125 |
+
});
|
126 |
+
|
127 |
+
// Translations autocomplete input box
|
128 |
+
function init_translations() {
|
129 |
+
$( '.tr_lang' ).each(function(){
|
130 |
+
var tr_lang = $( this ).attr( 'id' ).substring( 8 );
|
131 |
+
var td = $( this ).parent().parent().siblings( '.pll-edit-column' );
|
132 |
+
|
133 |
+
$( this ).autocomplete({
|
134 |
+
minLength: 0,
|
135 |
+
|
136 |
+
source: ajaxurl + '?action=pll_posts_not_translated' +
|
137 |
+
'&post_language=' + $( '.post_lang_choice' ).val() +
|
138 |
+
'&translation_language=' + tr_lang +
|
139 |
+
'&post_type=' + $( '#post_type' ).val() +
|
140 |
+
'&_pll_nonce=' + $( '#_pll_nonce' ).val(),
|
141 |
+
|
142 |
+
select: function( event, ui ) {
|
143 |
+
$( '#htr_lang_' + tr_lang ).val( ui.item.id );
|
144 |
+
td.html( ui.item.link );
|
145 |
+
},
|
146 |
+
});
|
147 |
+
|
148 |
+
// When the input box is emptied
|
149 |
+
$( this ).blur(function() {
|
150 |
+
if ( ! $( this ).val() ) {
|
151 |
+
$( '#htr_lang_' + tr_lang ).val( 0 );
|
152 |
+
td.html( td.siblings( '.hidden' ).children().clone() );
|
153 |
+
}
|
154 |
+
});
|
155 |
+
});
|
156 |
+
}
|
157 |
+
|
158 |
+
init_translations();
|
159 |
+
|
160 |
+
// Handle the response to a click on a Languages metabox button
|
161 |
+
$( '#ml_box' ).on( 'click', '.pll-button', function(){
|
162 |
+
var value = $( this ).hasClass( 'wp-ui-text-highlight' );
|
163 |
+
var id = $( this ).attr( 'id' );
|
164 |
+
var post_id = $( '#htr_lang_' + id.replace( 'pll_sync_post[', '' ).replace( ']', '' ) ).val();
|
165 |
+
|
166 |
+
if ( 'undefined' == typeof( post_id ) || 0 == post_id || value || confirm( confirm_text ) ) {
|
167 |
+
var data = {
|
168 |
+
action: 'toggle_' + id,
|
169 |
+
value: value,
|
170 |
+
post_type: $( '#post_type' ).val(),
|
171 |
+
_pll_nonce: $( '#_pll_nonce' ).val()
|
172 |
+
}
|
173 |
+
|
174 |
+
$.post( ajaxurl, data , function( response ){
|
175 |
+
var res = wpAjax.parseAjaxResponse( response, 'ajax-response' );
|
176 |
+
$.each( res.responses, function() {
|
177 |
+
id = id.replace( '[', '\\[' ).replace( ']', '\\]' );
|
178 |
+
$( '#' + id ).toggleClass( 'wp-ui-text-highlight' ).attr( 'title', this.data ).children( 'span' ).html( this.data );
|
179 |
+
$( 'input[name="' + id + '"]' ).val( ! data['value'] );
|
180 |
+
});
|
181 |
+
});
|
182 |
+
}
|
183 |
+
});
|
184 |
+
});
|
js/block-editor.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
wp.apiFetch.use(function(options,next){if('undefined'===typeof options.url){if('undefined'===typeof options.data){options.path+=((options.path.indexOf('?')>=0)?'&lang=':'?lang=')+getCurrentLanguage()}else{options.data.lang=getCurrentLanguage()}}return next(options)});function getCurrentLanguage(){return document.querySelector('[name=post_lang_choice]').value}jQuery(document).ready(function($){$('.post_lang_choice').change(function(){const select=wp.data.select;const dispatch=wp.data.dispatch;const subscribe=wp.data.subscribe;let unsubscribe=null;const savePostIsDone=new Promise(function(resolve,reject){unsubscribe=subscribe(function(){const isSavePostSucceeded=select('core/editor').didPostSaveRequestSucceed();const isSavePostFailed=select('core/editor').didPostSaveRequestFail();if(isSavePostSucceeded||isSavePostFailed){if(isSavePostFailed){reject()}else{resolve()}}})});if(location.pathname.match(/post-new.php/gi)){const title=select('core/editor').getEditedPostAttribute('title');const content=select('core/editor').getEditedPostAttribute('content');const excerpt=select('core/editor').getEditedPostAttribute('excerpt');if(''===title&&''===content&&''===excerpt){if(-1!=location.search.indexOf('new_lang')){window.location.search=window.location.search.replace(/(?:new_lang=[^&]*)(&)?(.*)/,'new_lang='+this.value+'$1$2');}else{window.location.search=window.location.search+((-1!=window.location.search.indexOf('?'))?'&':'?')+'new_lang='+this.value}}}dispatch('core/editor').savePost();savePostIsDone.then(function(){unsubscribe();window.location.reload()},function(){unsubscribe()}).catch(function(){unsubscribe()})})});
|
1 |
+
wp.apiFetch.use(function(options,next){if('undefined'===typeof options.url){if('undefined'===typeof options.data){options.path+=((options.path.indexOf('?')>=0)?'&lang=':'?lang=')+getCurrentLanguage()}else{options.data.lang=getCurrentLanguage()}}return next(options)});function getCurrentLanguage(){return document.querySelector('[name=post_lang_choice]').value}jQuery(document).ready(function($){$('.post_lang_choice').change(function(){const select=wp.data.select;const dispatch=wp.data.dispatch;const subscribe=wp.data.subscribe;let unsubscribe=null;const savePostIsDone=new Promise(function(resolve,reject){unsubscribe=subscribe(function(){const isSavePostSucceeded=select('core/editor').didPostSaveRequestSucceed();const isSavePostFailed=select('core/editor').didPostSaveRequestFail();if(isSavePostSucceeded||isSavePostFailed){if(isSavePostFailed){reject()}else{resolve()}}})});if(location.pathname.match(/post-new.php/gi)){const title=select('core/editor').getEditedPostAttribute('title');const content=select('core/editor').getEditedPostAttribute('content');const excerpt=select('core/editor').getEditedPostAttribute('excerpt');if(''===title&&''===content&&''===excerpt){if(-1!=location.search.indexOf('new_lang')){window.location.search=window.location.search.replace(/(?:new_lang=[^&]*)(&)?(.*)/,'new_lang='+this.value+'$1$2');}else{window.location.search=window.location.search+((-1!=window.location.search.indexOf('?'))?'&':'?')+'new_lang='+this.value}}}dispatch('core/editor').savePost();savePostIsDone.then(function(){unsubscribe();window.location.reload()},function(){unsubscribe()}).catch(function(){unsubscribe()})})});jQuery(document).ready(function($){$('.post_lang_choice').change(function(){var data={action:'post_lang_choice',lang:$(this).val(),post_type:$('#post_type').val(),post_id:$('#post_ID').val(),_pll_nonce:$('#_pll_nonce').val()};$.post(ajaxurl,data,function(response){var res=wpAjax.parseAjaxResponse(response,'ajax-response');$.each(res.responses,function(){switch(this.what){case 'translations':$('.translations').html(this.data);init_translations();break;case 'flag':$('.pll-select-flag').html(this.data);break}})})});function init_translations(){$('.tr_lang').each(function(){var tr_lang=$(this).attr('id').substring(8);var td=$(this).parent().parent().siblings('.pll-edit-column');$(this).autocomplete({minLength:0,source:ajaxurl+'?action=pll_posts_not_translated&post_language='+$('.post_lang_choice').val()+'&translation_language='+tr_lang+'&post_type='+$('#post_type').val()+'&_pll_nonce='+$('#_pll_nonce').val(),select:function(event,ui){$('#htr_lang_'+tr_lang).val(ui.item.id);td.html(ui.item.link)}});$(this).blur(function(){if(!$(this).val()){$('#htr_lang_'+tr_lang).val(0);td.html(td.siblings('.hidden').children().clone())}})})}init_translations();$('#ml_box').on('click','.pll-button',function(){var value=$(this).hasClass('wp-ui-text-highlight');var id=$(this).attr('id');var post_id=$('#htr_lang_'+id.replace('pll_sync_post[','').replace(']','')).val();if('undefined'==typeof(post_id)||0==post_id||value||confirm(confirm_text)){var data={action:'toggle_'+id,value:value,post_type:$('#post_type').val(),_pll_nonce:$('#_pll_nonce').val()};$.post(ajaxurl,data,function(response){var res=wpAjax.parseAjaxResponse(response,'ajax-response');$.each(res.responses,function(){id=id.replace('[','\\[').replace(']','\\]');$('#'+id).toggleClass('wp-ui-text-highlight').attr('title',this.data).children('span').html(this.data);$('input[name="'+id+'"]').val(!data['value'])})})}})});
|
js/classic-editor.js
CHANGED
@@ -154,4 +154,29 @@ jQuery( document ).ready(function( $ ) {
|
|
154 |
}
|
155 |
|
156 |
init_translations();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
157 |
});
|
154 |
}
|
155 |
|
156 |
init_translations();
|
157 |
+
|
158 |
+
// Handle the response to a click on a Languages metabox button
|
159 |
+
$( '#ml_box' ).on( 'click', '.pll-button', function(){
|
160 |
+
var value = $( this ).hasClass( 'wp-ui-text-highlight' );
|
161 |
+
var id = $( this ).attr( 'id' );
|
162 |
+
var post_id = $( '#htr_lang_' + id.replace( 'pll_sync_post[', '' ).replace( ']', '' ) ).val();
|
163 |
+
|
164 |
+
if ( 'undefined' == typeof( post_id ) || 0 == post_id || value || confirm( confirm_text ) ) {
|
165 |
+
var data = {
|
166 |
+
action: 'toggle_' + id,
|
167 |
+
value: value,
|
168 |
+
post_type: $( '#post_type' ).val(),
|
169 |
+
_pll_nonce: $( '#_pll_nonce' ).val()
|
170 |
+
}
|
171 |
+
|
172 |
+
$.post( ajaxurl, data , function( response ){
|
173 |
+
var res = wpAjax.parseAjaxResponse( response, 'ajax-response' );
|
174 |
+
$.each( res.responses, function() {
|
175 |
+
id = id.replace( '[', '\\[' ).replace( ']', '\\]' );
|
176 |
+
$( '#' + id ).toggleClass( 'wp-ui-text-highlight' ).attr( 'title', this.data ).children( 'span' ).html( this.data );
|
177 |
+
$( 'input[name="' + id + '"]' ).val( ! data['value'] );
|
178 |
+
});
|
179 |
+
});
|
180 |
+
}
|
181 |
+
});
|
182 |
});
|
js/classic-editor.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
!function(t){t.ajaxPrefilter(function(a){"string"==typeof a.data&&-1!==a.url.indexOf("action=ajax-tag-search")&&(lang=t(".post_lang_choice").val())&&(a.data="lang="+lang+"&"+a.data)})}(jQuery),function(t){tagBox.get=function(a){var l=a.substr(a.indexOf("-")+1),n={action:"get-tagcloud",lang:t(".post_lang_choice").val(),tax:l};t.post(ajaxurl,n,function(n,e){0!=n&&"success"==e||(n=wpAjax.broken),n=t('<div id="tagcloud-'+l+'" class="the-tagcloud">'+n+"</div>"),t("a",n).click(function(){return tagBox.flushTags(t(this).closest(".inside").children(".tagsdiv"),this),!1}),(v=t(".the-tagcloud").css("display"))?(t(".the-tagcloud").replaceWith(n),t(".the-tagcloud").css("display",v)):t("#"+a).after(n)})}}(jQuery),jQuery(document).ready(function(t){function a(){t(".tr_lang").each(function(){var a=t(this).attr("id").substring(8),l=t(this).parent().parent().siblings(".pll-edit-column");t(this).autocomplete({minLength:0,source:ajaxurl+"?action=pll_posts_not_translated&post_language="+t(".post_lang_choice").val()+"&translation_language="+a+"&post_type="+t("#post_type").val()+"&_pll_nonce="+t("#_pll_nonce").val(),select:function(n,e){t("#htr_lang_"+a).val(e.item.id),l.html(e.item.link)}}),t(this).blur(function(){t(this).val()||(t("#htr_lang_"+a).val(0),l.html(l.siblings(".hidden").children().clone()))})})}var l=new Array;t(".categorydiv").each(function(){var a,n,e=t(this).attr("id");a=e.split("-"),a.shift(),n=a.join("-"),l.push(n),t("#"+n+"-add-submit").before(t("<input />").attr("type","hidden").attr("id",n+"-lang").attr("name","term_lang_choice").attr("value",t(".post_lang_choice").val()))}),t(".post_lang_choice").change(function(){var n=t(this).val(),e=t(this).children('option[value="'+n+'"]').attr("lang"),i=t('.pll-translation-column > span[lang="'+e+'"]').attr("dir"),s={action:"post_lang_choice",lang:n,post_type:t("#post_type").val(),taxonomies:l,post_id:t("#post_ID").val(),_pll_nonce:t("#_pll_nonce").val()};t.post(ajaxurl,s,function(l){var n=wpAjax.parseAjaxResponse(l,"ajax-response");t.each(n.responses,function(){switch(this.what){case"translations":t(".translations").html(this.data),a();break;case"taxonomy":var l=this.data;t("#"+l+"checklist").html(this.supplemental.all),t("#"+l+"checklist-pop").html(this.supplemental.populars),t("#new"+l+"_parent").replaceWith(this.supplemental.dropdown),t("#"+l+"-lang").val(t(".post_lang_choice").val());break;case"pages":t("#parent_id").html(this.data);break;case"flag":t(".pll-select-flag").html(this.data);break;case"permalink":var n=t("#edit-slug-box");"-1"!=this.data&&n.children().length&&n.html(this.data)}}),t(".tagcloud-link").each(function(){var a=t(this).attr("id");tagBox.get(a)}),t("body").removeClass("pll-dir-rtl").removeClass("pll-dir-ltr").addClass("pll-dir-"+i),t("#content_ifr").contents().find("html").attr("lang",e).attr("dir",i),t("#content_ifr").contents().find("body").attr("dir",i)})}),a()});
|
1 |
+
!function(t){t.ajaxPrefilter(function(a){"string"==typeof a.data&&-1!==a.url.indexOf("action=ajax-tag-search")&&(lang=t(".post_lang_choice").val())&&(a.data="lang="+lang+"&"+a.data)})}(jQuery),function(t){tagBox.get=function(a){var l=a.substr(a.indexOf("-")+1),n={action:"get-tagcloud",lang:t(".post_lang_choice").val(),tax:l};t.post(ajaxurl,n,function(n,e){0!=n&&"success"==e||(n=wpAjax.broken),n=t('<div id="tagcloud-'+l+'" class="the-tagcloud">'+n+"</div>"),t("a",n).click(function(){return tagBox.flushTags(t(this).closest(".inside").children(".tagsdiv"),this),!1}),(v=t(".the-tagcloud").css("display"))?(t(".the-tagcloud").replaceWith(n),t(".the-tagcloud").css("display",v)):t("#"+a).after(n)})}}(jQuery),jQuery(document).ready(function(t){function a(){t(".tr_lang").each(function(){var a=t(this).attr("id").substring(8),l=t(this).parent().parent().siblings(".pll-edit-column");t(this).autocomplete({minLength:0,source:ajaxurl+"?action=pll_posts_not_translated&post_language="+t(".post_lang_choice").val()+"&translation_language="+a+"&post_type="+t("#post_type").val()+"&_pll_nonce="+t("#_pll_nonce").val(),select:function(n,e){t("#htr_lang_"+a).val(e.item.id),l.html(e.item.link)}}),t(this).blur(function(){t(this).val()||(t("#htr_lang_"+a).val(0),l.html(l.siblings(".hidden").children().clone()))})})}var l=new Array;t(".categorydiv").each(function(){var a,n,e=t(this).attr("id");a=e.split("-"),a.shift(),n=a.join("-"),l.push(n),t("#"+n+"-add-submit").before(t("<input />").attr("type","hidden").attr("id",n+"-lang").attr("name","term_lang_choice").attr("value",t(".post_lang_choice").val()))}),t(".post_lang_choice").change(function(){var n=t(this).val(),e=t(this).children('option[value="'+n+'"]').attr("lang"),i=t('.pll-translation-column > span[lang="'+e+'"]').attr("dir"),s={action:"post_lang_choice",lang:n,post_type:t("#post_type").val(),taxonomies:l,post_id:t("#post_ID").val(),_pll_nonce:t("#_pll_nonce").val()};t.post(ajaxurl,s,function(l){var n=wpAjax.parseAjaxResponse(l,"ajax-response");t.each(n.responses,function(){switch(this.what){case"translations":t(".translations").html(this.data),a();break;case"taxonomy":var l=this.data;t("#"+l+"checklist").html(this.supplemental.all),t("#"+l+"checklist-pop").html(this.supplemental.populars),t("#new"+l+"_parent").replaceWith(this.supplemental.dropdown),t("#"+l+"-lang").val(t(".post_lang_choice").val());break;case"pages":t("#parent_id").html(this.data);break;case"flag":t(".pll-select-flag").html(this.data);break;case"permalink":var n=t("#edit-slug-box");"-1"!=this.data&&n.children().length&&n.html(this.data)}}),t(".tagcloud-link").each(function(){var a=t(this).attr("id");tagBox.get(a)}),t("body").removeClass("pll-dir-rtl").removeClass("pll-dir-ltr").addClass("pll-dir-"+i),t("#content_ifr").contents().find("html").attr("lang",e).attr("dir",i),t("#content_ifr").contents().find("body").attr("dir",i)})}),a(),t("#ml_box").on("click",".pll-button",function(){var a=t(this).hasClass("wp-ui-text-highlight"),l=t(this).attr("id"),n=t("#htr_lang_"+l.replace("pll_sync_post[","").replace("]","")).val();if("undefined"==typeof n||0==n||a||confirm(confirm_text)){var e={action:"toggle_"+l,value:a,post_type:t("#post_type").val(),_pll_nonce:t("#_pll_nonce").val()};t.post(ajaxurl,e,function(a){var n=wpAjax.parseAjaxResponse(a,"ajax-response");t.each(n.responses,function(){l=l.replace("[","\\[").replace("]","\\]"),t("#"+l).toggleClass("wp-ui-text-highlight").attr("title",this.data).children("span").html(this.data),t('input[name="'+l+'"]').val(!e.value)})})}})});
|
js/media.js
DELETED
@@ -1,6 +0,0 @@
|
|
1 |
-
// when clicking on attach link, filters find post list per media language
|
2 |
-
(function( $ ){
|
3 |
-
$.ajaxPrefilter(function ( options, originalOptions, jqXHR ) {
|
4 |
-
options.data = 'pll_post_id=' + $( '#affected' ).val() + '&' + options.data;
|
5 |
-
});
|
6 |
-
})( jQuery )
|
|
|
|
|
|
|
|
|
|
|
|
js/media.min.js
DELETED
@@ -1 +0,0 @@
|
|
1 |
-
!function(a){a.ajaxPrefilter(function(t){t.data="pll_post_id="+a("#affected").val()+"&"+t.data})}(jQuery);
|
|
js/post.js
CHANGED
@@ -1,4 +1,6 @@
|
|
1 |
-
|
|
|
|
|
2 |
(function( $ ){
|
3 |
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
|
4 |
if ( 'string' === typeof options.data && -1 !== options.data.indexOf( 'action=ajax-tag-search' ) && ( lang = $( ':input[name="inline_lang_choice"]' ).val() ) ) {
|
@@ -7,7 +9,9 @@
|
|
7 |
});
|
8 |
})( jQuery );
|
9 |
|
10 |
-
|
|
|
|
|
11 |
(function( $ ) {
|
12 |
$( document ).bind( 'DOMNodeInserted', function( e ) {
|
13 |
var t = $( e.target );
|
@@ -61,8 +65,10 @@
|
|
61 |
});
|
62 |
})( jQuery );
|
63 |
|
64 |
-
|
65 |
-
|
|
|
|
|
66 |
(function( $ ) {
|
67 |
$( document ).ajaxSuccess(function( event, xhr, settings ) {
|
68 |
function update_rows( post_id ) {
|
@@ -94,7 +100,7 @@
|
|
94 |
});
|
95 |
}
|
96 |
|
97 |
-
if ( 'string' == typeof( settings.data ) ) { // Need to check the type due to
|
98 |
var data = wpAjax.unserialize( settings.data ); // what were the data sent by the ajax request?
|
99 |
if ( 'undefined' != typeof( data['action'] ) && 'inline-save' == data['action'] ) {
|
100 |
update_rows( data['post_ID'] );
|
@@ -102,3 +108,67 @@
|
|
102 |
}
|
103 |
});
|
104 |
})( jQuery );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Tag suggest in quick edit
|
3 |
+
*/
|
4 |
(function( $ ){
|
5 |
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
|
6 |
if ( 'string' === typeof options.data && -1 !== options.data.indexOf( 'action=ajax-tag-search' ) && ( lang = $( ':input[name="inline_lang_choice"]' ).val() ) ) {
|
9 |
});
|
10 |
})( jQuery );
|
11 |
|
12 |
+
/**
|
13 |
+
* Quick edit
|
14 |
+
*/
|
15 |
(function( $ ) {
|
16 |
$( document ).bind( 'DOMNodeInserted', function( e ) {
|
17 |
var t = $( e.target );
|
65 |
});
|
66 |
})( jQuery );
|
67 |
|
68 |
+
/**
|
69 |
+
* Update rows of translated posts when the language is modified in quick edit
|
70 |
+
* Acts on ajaxSuccess event
|
71 |
+
*/
|
72 |
(function( $ ) {
|
73 |
$( document ).ajaxSuccess(function( event, xhr, settings ) {
|
74 |
function update_rows( post_id ) {
|
100 |
});
|
101 |
}
|
102 |
|
103 |
+
if ( 'string' == typeof( settings.data ) ) { // Need to check the type due to block editor sometime sending FormData objects
|
104 |
var data = wpAjax.unserialize( settings.data ); // what were the data sent by the ajax request?
|
105 |
if ( 'undefined' != typeof( data['action'] ) && 'inline-save' == data['action'] ) {
|
106 |
update_rows( data['post_ID'] );
|
108 |
}
|
109 |
});
|
110 |
})( jQuery );
|
111 |
+
|
112 |
+
/**
|
113 |
+
* Media list table
|
114 |
+
* When clicking on attach link, filters find post list per media language
|
115 |
+
*/
|
116 |
+
(function( $ ){
|
117 |
+
$.ajaxPrefilter( function ( options, originalOptions, jqXHR ) {
|
118 |
+
if ( 'string' === typeof options.data && -1 !== options.data.indexOf( 'action=find_posts' ) ) {
|
119 |
+
options.data = 'pll_post_id=' + $( '#affected' ).val() + '&' + options.data;
|
120 |
+
}
|
121 |
+
});
|
122 |
+
})( jQuery )
|
123 |
+
|
124 |
+
|
125 |
+
/**
|
126 |
+
* Bulk translate
|
127 |
+
*/
|
128 |
+
jQuery( document ).ready( function( $ ) {
|
129 |
+
var t = this;
|
130 |
+
|
131 |
+
$( '.editinline' ).click( function(){
|
132 |
+
$( '#pll-translate' ).find( '.cancel' ).click(); // Close the form on quick edit
|
133 |
+
} );
|
134 |
+
|
135 |
+
$( '#doaction, #doaction2' ).click( function( e ){
|
136 |
+
t.whichBulkButtonId = $( this ).attr( 'id' );
|
137 |
+
var n = t.whichBulkButtonId.substr( 2 );
|
138 |
+
|
139 |
+
if ( 'pll_translate' === $( 'select[name="' + n + '"]' ).val() ) {
|
140 |
+
e.preventDefault();
|
141 |
+
|
142 |
+
if ( typeof inlineEditPost !== 'undefined' ) { // Not available for media.
|
143 |
+
inlineEditPost.revert(); // Close Bulk edit and Quick edit if open.
|
144 |
+
}
|
145 |
+
|
146 |
+
$( '#pll-translate td' ).attr( 'colspan', $( 'th:visible, td:visible', '.widefat:first thead' ).length );
|
147 |
+
$( 'table.widefat tbody' ).prepend( $( '#pll-translate' ) ).prepend( '<tr class="hidden"></tr>' ); // The hidden tr allows to keep the background color
|
148 |
+
} else {
|
149 |
+
$( '#pll-translate' ).find( '.cancel' ).click(); // Close the form on any other bulk action
|
150 |
+
}
|
151 |
+
} );
|
152 |
+
|
153 |
+
// Cancel
|
154 |
+
$( '#pll-translate' ).on( 'click', '.cancel', function(){
|
155 |
+
$( '#pll-translate' ).siblings( '.hidden' ).remove();
|
156 |
+
$( '#pll-bulk-translate' ).append( $( '#pll-translate' ) );
|
157 |
+
|
158 |
+
// Move focus back to the Bulk Action button that was activated.
|
159 |
+
$( '#' + t.whichBulkButtonId ).focus();
|
160 |
+
} );
|
161 |
+
|
162 |
+
// Act when pressing enter or esc
|
163 |
+
$( '#pll-translate' ).keydown( function( event ){
|
164 |
+
if ( 13 === event.keyCode && ! $( event.target ).hasClass( 'cancel' ) ) {
|
165 |
+
event.preventDefault();
|
166 |
+
$( this ).find( 'input[type=submit]' ).click();
|
167 |
+
}
|
168 |
+
|
169 |
+
if ( 27 === event.keyCode ) {
|
170 |
+
event.preventDefault();
|
171 |
+
$( this ).find( '.cancel' ).click();
|
172 |
+
}
|
173 |
+
} );
|
174 |
+
} );
|
js/post.min.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
!function(
|
1 |
+
!function(t){t.ajaxPrefilter(function(n){"string"==typeof n.data&&-1!==n.data.indexOf("action=ajax-tag-search")&&(lang=t(':input[name="inline_lang_choice"]').val())&&(n.data="lang="+lang+"&"+n.data)})}(jQuery),function(t){t(document).bind("DOMNodeInserted",function(n){function a(n){"undefined"!=typeof pll_term_languages&&t.each(pll_term_languages,function(a,e){t.each(e,function(e,i){t.each(i,function(i){id="#"+e+"-"+pll_term_languages[a][e][i],n==a?t(id).show():t(id).hide()})})})}function e(n){"undefined"!=typeof pll_page_languages&&t.each(pll_page_languages,function(a,e){t.each(e,function(e){v=t('#post_parent option[value="'+pll_page_languages[a][e]+'"]'),n==a?v.show():v.hide()})})}var i=t(n.target);if("inline-edit"==i.attr("id")){var l=i.prev().attr("id").replace("post-","");if(l>0){var c=i.find(':input[name="inline_lang_choice"]'),s=t("#lang_"+l).html();c.val(s),a(s),e(s),c.change(function(){a(t(this).val()),e(t(this).val())})}}})}(jQuery),function(t){t(document).ajaxSuccess(function(n,a,e){function i(n){var a=new Array;t(".translation_"+n).each(function(){a.push(t(this).parent().parent().attr("id").substring(5))});var e={action:"pll_update_post_rows",post_id:n,translations:a.join(","),post_type:t("input[name='post_type']").val(),screen:t("input[name='screen']").val(),_pll_nonce:t("input[name='_inline_edit']").val()};t.post(ajaxurl,e,function(n){if(n){var a=wpAjax.parseAjaxResponse(n,"ajax-response");t.each(a.responses,function(){"row"==this.what&&t("#post-"+this.supplemental.post_id).replaceWith(this.data)})}})}if("string"==typeof e.data){var l=wpAjax.unserialize(e.data);"undefined"!=typeof l.action&&"inline-save"==l.action&&i(l.post_ID)}})}(jQuery),function(t){t.ajaxPrefilter(function(n){"string"==typeof n.data&&-1!==n.data.indexOf("action=find_posts")&&(n.data="pll_post_id="+t("#affected").val()+"&"+n.data)})}(jQuery),jQuery(document).ready(function(t){var n=this;t(".editinline").click(function(){t("#pll-translate").find(".cancel").click()}),t("#doaction, #doaction2").click(function(a){n.whichBulkButtonId=t(this).attr("id");var e=n.whichBulkButtonId.substr(2);"pll_translate"===t('select[name="'+e+'"]').val()?(a.preventDefault(),"undefined"!=typeof inlineEditPost&&inlineEditPost.revert(),t("#pll-translate td").attr("colspan",t("th:visible, td:visible",".widefat:first thead").length),t("table.widefat tbody").prepend(t("#pll-translate")).prepend('<tr class="hidden"></tr>')):t("#pll-translate").find(".cancel").click()}),t("#pll-translate").on("click",".cancel",function(){t("#pll-translate").siblings(".hidden").remove(),t("#pll-bulk-translate").append(t("#pll-translate")),t("#"+n.whichBulkButtonId).focus()}),t("#pll-translate").keydown(function(n){13!==n.keyCode||t(n.target).hasClass("cancel")||(n.preventDefault(),t(this).find("input[type=submit]").click()),27===n.keyCode&&(n.preventDefault(),t(this).find(".cancel").click())})});
|
lingotek/lingotek.php
CHANGED
@@ -1,9 +1,5 @@
|
|
1 |
<?php
|
2 |
|
3 |
-
if ( ! defined( 'ABSPATH' ) ) {
|
4 |
-
exit; // Don't access directly
|
5 |
-
};
|
6 |
-
|
7 |
/**
|
8 |
* Class to manage Lingotek ads
|
9 |
*
|
@@ -24,7 +20,7 @@ class PLL_Lingotek {
|
|
24 |
add_filter( 'pll_settings_tabs', array( $this, 'add_tab' ) );
|
25 |
add_action( 'pll_settings_active_tab_lingotek', array( $this, 'display_tab' ) );
|
26 |
|
27 |
-
if ( PLL_SETTINGS && isset( $_GET['page'] ) && 'mlang_lingotek'
|
28 |
add_action( 'admin_print_styles', array( $this, 'print_css' ) );
|
29 |
}
|
30 |
|
@@ -103,11 +99,11 @@ class PLL_Lingotek {
|
|
103 |
printf( '<p>%s</p>', esc_html__( 'Polylang is now fully integrated with Lingotek, a professional translation management system!', 'polylang' ) );
|
104 |
|
105 |
$this->box(
|
106 |
-
__( 'Automatically
|
107 |
__( 'Polylang is now fully integrated with Lingotek!', 'polylang' ),
|
108 |
array(
|
109 |
__( 'Access free machine translation for your site for up to 100,000 characters.', 'polylang' ),
|
110 |
-
__( '
|
111 |
),
|
112 |
array_intersect_key( $links, array_flip( array( 'activate' ) ) ),
|
113 |
'image01.gif'
|
@@ -127,19 +123,19 @@ class PLL_Lingotek {
|
|
127 |
);
|
128 |
|
129 |
$this->box(
|
130 |
-
__( 'Professionally
|
131 |
-
__( 'Do you need
|
132 |
array(
|
133 |
__( 'Start the process of getting a professional translation bid.', 'polylang' ),
|
134 |
-
__( '
|
135 |
-
__( 'Once activated click on the request translation bid and a certified translation project manager will contact you
|
136 |
),
|
137 |
array_intersect_key( $links, array_flip( array( 'activate', 'translation' ) ) ),
|
138 |
'image03.png'
|
139 |
);
|
140 |
|
141 |
$this->box(
|
142 |
-
__( 'Need
|
143 |
__( 'Do you need help translating your site?', 'polylang' ),
|
144 |
array(
|
145 |
__( 'Start the process of getting extra services.', 'polylang' ),
|
@@ -169,7 +165,7 @@ class PLL_Lingotek {
|
|
169 |
border: 1px solid #ddd;
|
170 |
margin-right: 3px;
|
171 |
margin-bottom: 3px;
|
172 |
-
height:
|
173 |
background: #fafafa;
|
174 |
}
|
175 |
.rtl .ltk-feature {
|
@@ -300,5 +296,3 @@ class PLL_Lingotek {
|
|
300 |
return '';
|
301 |
}
|
302 |
}
|
303 |
-
|
304 |
-
add_action( 'wp_loaded', array( new PLL_Lingotek(), 'init' ) );
|
1 |
<?php
|
2 |
|
|
|
|
|
|
|
|
|
3 |
/**
|
4 |
* Class to manage Lingotek ads
|
5 |
*
|
20 |
add_filter( 'pll_settings_tabs', array( $this, 'add_tab' ) );
|
21 |
add_action( 'pll_settings_active_tab_lingotek', array( $this, 'display_tab' ) );
|
22 |
|
23 |
+
if ( PLL_SETTINGS && isset( $_GET['page'] ) && 'mlang_lingotek' === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
24 |
add_action( 'admin_print_styles', array( $this, 'print_css' ) );
|
25 |
}
|
26 |
|
99 |
printf( '<p>%s</p>', esc_html__( 'Polylang is now fully integrated with Lingotek, a professional translation management system!', 'polylang' ) );
|
100 |
|
101 |
$this->box(
|
102 |
+
__( 'Automatically translate my site', 'polylang' ),
|
103 |
__( 'Polylang is now fully integrated with Lingotek!', 'polylang' ),
|
104 |
array(
|
105 |
__( 'Access free machine translation for your site for up to 100,000 characters.', 'polylang' ),
|
106 |
+
__( 'If you\'re on a tight budget, looking for near-instant results, and are okay with less-than-perfect quality, machine translation is an excellent option.', 'polylang' ),
|
107 |
),
|
108 |
array_intersect_key( $links, array_flip( array( 'activate' ) ) ),
|
109 |
'image01.gif'
|
123 |
);
|
124 |
|
125 |
$this->box(
|
126 |
+
__( 'Professionally translate my site', 'polylang' ),
|
127 |
+
__( 'Do you need professional translations for your site?', 'polylang' ),
|
128 |
array(
|
129 |
__( 'Start the process of getting a professional translation bid.', 'polylang' ),
|
130 |
+
__( 'When you activate your account, Lingotek will be able to get an accurate count of the number of words in your site. Then tell them which languages you wish to have them translated into.', 'polylang' ),
|
131 |
+
__( 'Once activated, click on the "request translation bid" and a certified translation project manager will contact you for a no-obligations translation bid.', 'polylang' ),
|
132 |
),
|
133 |
array_intersect_key( $links, array_flip( array( 'activate', 'translation' ) ) ),
|
134 |
'image03.png'
|
135 |
);
|
136 |
|
137 |
$this->box(
|
138 |
+
__( 'Need extra services?', 'polylang' ),
|
139 |
__( 'Do you need help translating your site?', 'polylang' ),
|
140 |
array(
|
141 |
__( 'Start the process of getting extra services.', 'polylang' ),
|
165 |
border: 1px solid #ddd;
|
166 |
margin-right: 3px;
|
167 |
margin-bottom: 3px;
|
168 |
+
height: 650px;
|
169 |
background: #fafafa;
|
170 |
}
|
171 |
.rtl .ltk-feature {
|
296 |
return '';
|
297 |
}
|
298 |
}
|
|
|
|
modules/plugins/as3cf.php
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
|
3 |
+
/**
|
4 |
+
* A class to manage the integration with WP Offload Media Lite.
|
5 |
+
* Version tested: 2.1.1
|
6 |
+
*
|
7 |
+
* @since 2.6
|
8 |
+
*/
|
9 |
+
class PLL_AS3CF {
|
10 |
+
private $is_media_translated;
|
11 |
+
|
12 |
+
/**
|
13 |
+
* Initializes filters and actions.
|
14 |
+
*
|
15 |
+
* @since 2.6
|
16 |
+
*/
|
17 |
+
public function init() {
|
18 |
+
add_filter( 'pll_copy_post_metas', array( $this, 'copy_post_metas' ) );
|
19 |
+
add_action( 'delete_attachment', array( $this, 'check_translated_media' ), 5 ); // Before Polylang deletes the translations information.
|
20 |
+
add_action( 'delete_attachment', array( $this, 'prevent_file_deletion' ), 15 ); // Between Polylang and WP Offload Media.
|
21 |
+
}
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Synchronizes post metas
|
25 |
+
*
|
26 |
+
* @since 2.6
|
27 |
+
*
|
28 |
+
* @param array $metas List of custom fields names.
|
29 |
+
* @return array
|
30 |
+
*/
|
31 |
+
public function copy_post_metas( $metas ) {
|
32 |
+
$metas[] = 'amazonS3_info';
|
33 |
+
$metas[] = 'as3cf_filesize_total';
|
34 |
+
return $metas;
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Checks if the deleted attachment was translated and stores the information.
|
39 |
+
*
|
40 |
+
* @since 2.6
|
41 |
+
*
|
42 |
+
* @param int $post_id Id of the attachment being deleted.
|
43 |
+
*/
|
44 |
+
public function check_translated_media( $post_id ) {
|
45 |
+
$this->is_media_translated[ $post_id ] = ( count( pll_get_post_translations( $post_id ) ) > 1 );
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Deletes the WP Offload Media information from the attachment being deleted.
|
50 |
+
* That way WP Offload Media won't delete the file stored in the cloud.
|
51 |
+
* Done after Polylang has deleted the translations informations, to avoid the synchronization of the deletion
|
52 |
+
* and of course before WP Offload Media deletes the file, normally at priority 20.
|
53 |
+
*
|
54 |
+
* @since 2.6
|
55 |
+
*
|
56 |
+
* @param int $post_id Id of the attachment being deleted.
|
57 |
+
*/
|
58 |
+
public function prevent_file_deletion( $post_id ) {
|
59 |
+
if ( ! empty( $this->is_media_translated[ $post_id ] ) ) {
|
60 |
+
delete_post_meta( $post_id, 'amazonS3_info' );
|
61 |
+
delete_post_meta( $post_id, 'as3cf_filesize_total' );
|
62 |
+
}
|
63 |
+
}
|
64 |
+
}
|
modules/plugins/cache-compat.php
CHANGED
@@ -31,7 +31,7 @@ class PLL_Cache_Compat {
|
|
31 |
* @since 2.3
|
32 |
*/
|
33 |
public function add_cookie_script() {
|
34 |
-
$domain = ( 2 == PLL()->options['force_lang'] ) ?
|
35 |
$js = sprintf(
|
36 |
'(function() {
|
37 |
var expirationDate = new Date();
|
@@ -44,7 +44,7 @@ class PLL_Cache_Compat {
|
|
44 |
esc_js( COOKIEPATH ),
|
45 |
$domain ? '; domain=' . esc_js( $domain ) : ''
|
46 |
);
|
47 |
-
echo '<script type="text/javascript">' . $js . '</script>';
|
48 |
}
|
49 |
|
50 |
/**
|
31 |
* @since 2.3
|
32 |
*/
|
33 |
public function add_cookie_script() {
|
34 |
+
$domain = ( 2 == PLL()->options['force_lang'] ) ? wp_parse_url( PLL()->links_model->home, PHP_URL_HOST ) : COOKIE_DOMAIN;
|
35 |
$js = sprintf(
|
36 |
'(function() {
|
37 |
var expirationDate = new Date();
|
44 |
esc_js( COOKIEPATH ),
|
45 |
$domain ? '; domain=' . esc_js( $domain ) : ''
|
46 |
);
|
47 |
+
echo '<script type="text/javascript">' . $js . '</script>'; // phpcs:ignore WordPress.Security.EscapeOutput
|
48 |
}
|
49 |
|
50 |
/**
|
modules/plugins/featured-content.php
CHANGED
@@ -9,9 +9,9 @@ class PLL_Featured_Content {
|
|
9 |
/**
|
10 |
* Constructor
|
11 |
*
|
12 |
-
* @since 2.
|
13 |
*/
|
14 |
-
public function
|
15 |
add_filter( 'transient_featured_content_ids', array( $this, 'featured_content_ids' ) );
|
16 |
add_filter( 'pll_filter_query_excluded_query_vars', array( $this, 'fix_featured_posts' ) );
|
17 |
add_filter( 'option_featured-content', array( $this, 'option_featured_content' ) );
|
@@ -55,7 +55,7 @@ class PLL_Featured_Content {
|
|
55 |
* @return array modified featured posts ids ( include all languages )
|
56 |
*/
|
57 |
public function featured_content_ids( $featured_ids ) {
|
58 |
-
if ( ! $this->is_active() ||
|
59 |
return $featured_ids;
|
60 |
}
|
61 |
|
@@ -72,22 +72,25 @@ class PLL_Featured_Content {
|
|
72 |
// Query for featured posts in all languages
|
73 |
// One query per language to get the correct number of posts per language
|
74 |
foreach ( $tags as $tag ) {
|
75 |
-
$
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
'taxonomy' => 'post_tag',
|
84 |
-
'terms' => (int) $tag,
|
85 |
-
),
|
86 |
),
|
87 |
-
)
|
88 |
);
|
89 |
|
90 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
}
|
92 |
|
93 |
$ids = array_map( 'absint', $ids );
|
9 |
/**
|
10 |
* Constructor
|
11 |
*
|
12 |
+
* @since 2.6
|
13 |
*/
|
14 |
+
public function init() {
|
15 |
add_filter( 'transient_featured_content_ids', array( $this, 'featured_content_ids' ) );
|
16 |
add_filter( 'pll_filter_query_excluded_query_vars', array( $this, 'fix_featured_posts' ) );
|
17 |
add_filter( 'option_featured-content', array( $this, 'option_featured_content' ) );
|
55 |
* @return array modified featured posts ids ( include all languages )
|
56 |
*/
|
57 |
public function featured_content_ids( $featured_ids ) {
|
58 |
+
if ( ! $this->is_active() || false !== $featured_ids ) {
|
59 |
return $featured_ids;
|
60 |
}
|
61 |
|
72 |
// Query for featured posts in all languages
|
73 |
// One query per language to get the correct number of posts per language
|
74 |
foreach ( $tags as $tag ) {
|
75 |
+
$args = array(
|
76 |
+
'lang' => 0, // Avoid language filters.
|
77 |
+
'fields' => 'ids',
|
78 |
+
'numberposts' => Featured_Content::$max_posts,
|
79 |
+
'tax_query' => array(
|
80 |
+
array(
|
81 |
+
'taxonomy' => 'post_tag',
|
82 |
+
'terms' => (int) $tag,
|
|
|
|
|
|
|
83 |
),
|
84 |
+
),
|
85 |
);
|
86 |
|
87 |
+
// Available in Jetpack, but not in Twenty Fourteen.
|
88 |
+
if ( isset( Featured_Content::$post_types ) ) {
|
89 |
+
$args['post_type'] = Featured_Content::$post_types;
|
90 |
+
}
|
91 |
+
|
92 |
+
$_ids = get_posts( $args );
|
93 |
+
$ids = array_merge( $ids, $_ids );
|
94 |
}
|
95 |
|
96 |
$ids = array_map( 'absint', $ids );
|
modules/plugins/jetpack.php
CHANGED
@@ -19,7 +19,7 @@ class PLL_Jetpack {
|
|
19 |
add_filter( 'jetpack_relatedposts_filter_filters', array( $this, 'jetpack_relatedposts_filter_filters' ), 10, 2 );
|
20 |
|
21 |
// Jetpack infinite scroll
|
22 |
-
if ( isset( $_GET['infinity'], $_POST['action'] ) && 'infinite_scroll' == $_POST['action'] ) {
|
23 |
add_filter( 'pll_is_ajax_on_front', '__return_true' );
|
24 |
}
|
25 |
}
|
@@ -131,7 +131,7 @@ class PLL_Jetpack {
|
|
131 |
* @return array
|
132 |
*/
|
133 |
public function jetpack_infinite_scroll_js_settings( $settings ) {
|
134 |
-
$settings['history']['host'] =
|
135 |
return $settings;
|
136 |
}
|
137 |
}
|
19 |
add_filter( 'jetpack_relatedposts_filter_filters', array( $this, 'jetpack_relatedposts_filter_filters' ), 10, 2 );
|
20 |
|
21 |
// Jetpack infinite scroll
|
22 |
+
if ( isset( $_GET['infinity'], $_POST['action'] ) && 'infinite_scroll' == $_POST['action'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
23 |
add_filter( 'pll_is_ajax_on_front', '__return_true' );
|
24 |
}
|
25 |
}
|
131 |
* @return array
|
132 |
*/
|
133 |
public function jetpack_infinite_scroll_js_settings( $settings ) {
|
134 |
+
$settings['history']['host'] = wp_parse_url( pll_home_url(), PHP_URL_HOST ); // Jetpack uses get_option( 'home' )
|
135 |
return $settings;
|
136 |
}
|
137 |
}
|
modules/plugins/plugins-compat.php
CHANGED
@@ -7,7 +7,7 @@
|
|
7 |
* @since 1.0
|
8 |
*/
|
9 |
class PLL_Plugins_Compat {
|
10 |
-
static
|
11 |
|
12 |
/**
|
13 |
* Constructor
|
@@ -35,8 +35,8 @@ class PLL_Plugins_Compat {
|
|
35 |
add_filter( 'option_duplicate_post_taxonomies_blacklist', array( $this, 'duplicate_post_taxonomies_blacklist' ) );
|
36 |
|
37 |
// Jetpack
|
38 |
-
$this->jetpack
|
39 |
-
$this->featured_content = new PLL_Featured_Content();
|
40 |
|
41 |
// WP Sweep
|
42 |
add_filter( 'wp_sweep_excluded_taxonomies', array( $this, 'wp_sweep_excluded_taxonomies' ) );
|
@@ -83,7 +83,7 @@ class PLL_Plugins_Compat {
|
|
83 |
public function plugins_loaded() {
|
84 |
// Yoast SEO
|
85 |
if ( defined( 'WPSEO_VERSION' ) ) {
|
86 |
-
add_action( '
|
87 |
}
|
88 |
|
89 |
if ( pll_is_cache_active() ) {
|
@@ -114,6 +114,16 @@ class PLL_Plugins_Compat {
|
|
114 |
if ( ( defined( 'AC_FILE' ) || defined( 'ACP_FILE' ) ) && class_exists( 'PLL_CPAC' ) ) {
|
115 |
add_action( 'admin_init', array( $this->cpac = new PLL_CPAC(), 'init' ) );
|
116 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
}
|
118 |
|
119 |
/**
|
@@ -153,7 +163,7 @@ class PLL_Plugins_Compat {
|
|
153 |
load_plugin_textdomain( 'wordpress-importer', false, basename( dirname( $class->getFileName() ) ) . '/languages' );
|
154 |
|
155 |
$GLOBALS['wp_import'] = new PLL_WP_Import();
|
156 |
-
register_importer( 'wordpress', 'WordPress', __( 'Import <strong>posts, pages, comments, custom fields, categories, and tags</strong> from a WordPress export file.', '
|
157 |
}
|
158 |
|
159 |
/**
|
@@ -167,14 +177,14 @@ class PLL_Plugins_Compat {
|
|
167 |
* @return array
|
168 |
*/
|
169 |
public function wp_import_terms( $terms ) {
|
170 |
-
include PLL_SETTINGS_INC . '/languages.php';
|
171 |
|
172 |
foreach ( $terms as $key => $term ) {
|
173 |
if ( 'language' === $term['term_taxonomy'] ) {
|
174 |
$description = maybe_unserialize( $term['term_description'] );
|
175 |
if ( empty( $description['flag_code'] ) && isset( $languages[ $description['locale'] ] ) ) {
|
176 |
$description['flag_code'] = $languages[ $description['locale'] ]['flag'];
|
177 |
-
$terms[ $key ]['term_description'] =
|
178 |
}
|
179 |
}
|
180 |
}
|
@@ -214,7 +224,7 @@ class PLL_Plugins_Compat {
|
|
214 |
*/
|
215 |
public function cft_copy( $post_type, $post ) {
|
216 |
global $custom_field_template;
|
217 |
-
if ( isset( $custom_field_template, $_REQUEST['from_post'], $_REQUEST['new_lang'] ) && ! empty( $post ) ) {
|
218 |
$_REQUEST['post'] = $post->ID;
|
219 |
}
|
220 |
}
|
@@ -298,23 +308,26 @@ class PLL_Plugins_Compat {
|
|
298 |
}
|
299 |
|
300 |
// Don't redirect post previews
|
301 |
-
if ( isset( $_GET['preview'] ) && 'true' === $_GET['preview'] ) {
|
302 |
return;
|
303 |
}
|
304 |
|
305 |
// Don't redirect theme customizer
|
306 |
-
if ( isset( $_POST['customize'] ) && isset( $_POST['theme'] ) && 'on' === $_POST['customize'] ) {
|
307 |
return;
|
308 |
}
|
309 |
|
310 |
// If we can't associate the requested domain to a language, redirect to the default domain
|
|
|
|
|
|
|
311 |
$hosts = PLL()->links_model->get_hosts();
|
312 |
-
$lang
|
313 |
|
314 |
if ( empty( $lang ) ) {
|
315 |
-
$status
|
316 |
-
$redirect = (
|
317 |
-
|
318 |
exit;
|
319 |
}
|
320 |
} else {
|
7 |
* @since 1.0
|
8 |
*/
|
9 |
class PLL_Plugins_Compat {
|
10 |
+
protected static $instance; // for singleton
|
11 |
|
12 |
/**
|
13 |
* Constructor
|
35 |
add_filter( 'option_duplicate_post_taxonomies_blacklist', array( $this, 'duplicate_post_taxonomies_blacklist' ) );
|
36 |
|
37 |
// Jetpack
|
38 |
+
$this->jetpack = new PLL_Jetpack(); // Must be loaded before the plugin is active
|
39 |
+
add_action( 'pll_init', array( $this->featured_content = new PLL_Featured_Content(), 'init' ) );
|
40 |
|
41 |
// WP Sweep
|
42 |
add_filter( 'wp_sweep_excluded_taxonomies', array( $this, 'wp_sweep_excluded_taxonomies' ) );
|
83 |
public function plugins_loaded() {
|
84 |
// Yoast SEO
|
85 |
if ( defined( 'WPSEO_VERSION' ) ) {
|
86 |
+
add_action( 'pll_init', array( $this->wpseo = new PLL_WPSEO(), 'init' ) );
|
87 |
}
|
88 |
|
89 |
if ( pll_is_cache_active() ) {
|
114 |
if ( ( defined( 'AC_FILE' ) || defined( 'ACP_FILE' ) ) && class_exists( 'PLL_CPAC' ) ) {
|
115 |
add_action( 'admin_init', array( $this->cpac = new PLL_CPAC(), 'init' ) );
|
116 |
}
|
117 |
+
|
118 |
+
// WP Offload Media Lite
|
119 |
+
if ( function_exists( 'as3cf_init' ) && class_exists( 'PLL_AS3CF' ) ) {
|
120 |
+
add_action( 'pll_init', array( $this->as3cf = new PLL_AS3CF(), 'init' ) );
|
121 |
+
}
|
122 |
+
|
123 |
+
// Content Blocks (Custom Post Widget)
|
124 |
+
if ( function_exists( 'custom_post_widget_plugin_init' ) && class_exists( 'PLL_Content_Blocks' ) ) {
|
125 |
+
add_action( 'pll_init', array( $this->content_blocks = new PLL_Content_Blocks(), 'init' ) );
|
126 |
+
}
|
127 |
}
|
128 |
|
129 |
/**
|
163 |
load_plugin_textdomain( 'wordpress-importer', false, basename( dirname( $class->getFileName() ) ) . '/languages' );
|
164 |
|
165 |
$GLOBALS['wp_import'] = new PLL_WP_Import();
|
166 |
+
register_importer( 'wordpress', 'WordPress', __( 'Import <strong>posts, pages, comments, custom fields, categories, and tags</strong> from a WordPress export file.', 'polylang' ), array( $GLOBALS['wp_import'], 'dispatch' ) ); // phpcs:ignore WordPress.WP.CapitalPDangit.Misspelled
|
167 |
}
|
168 |
|
169 |
/**
|
177 |
* @return array
|
178 |
*/
|
179 |
public function wp_import_terms( $terms ) {
|
180 |
+
$languages = include PLL_SETTINGS_INC . '/languages.php';
|
181 |
|
182 |
foreach ( $terms as $key => $term ) {
|
183 |
if ( 'language' === $term['term_taxonomy'] ) {
|
184 |
$description = maybe_unserialize( $term['term_description'] );
|
185 |
if ( empty( $description['flag_code'] ) && isset( $languages[ $description['locale'] ] ) ) {
|
186 |
$description['flag_code'] = $languages[ $description['locale'] ]['flag'];
|
187 |
+
$terms[ $key ]['term_description'] = maybe_serialize( $description );
|
188 |
}
|
189 |
}
|
190 |
}
|
224 |
*/
|
225 |
public function cft_copy( $post_type, $post ) {
|
226 |
global $custom_field_template;
|
227 |
+
if ( isset( $custom_field_template, $_REQUEST['from_post'], $_REQUEST['new_lang'] ) && ! empty( $post ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
228 |
$_REQUEST['post'] = $post->ID;
|
229 |
}
|
230 |
}
|
308 |
}
|
309 |
|
310 |
// Don't redirect post previews
|
311 |
+
if ( isset( $_GET['preview'] ) && 'true' === $_GET['preview'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
312 |
return;
|
313 |
}
|
314 |
|
315 |
// Don't redirect theme customizer
|
316 |
+
if ( isset( $_POST['customize'] ) && isset( $_POST['theme'] ) && 'on' === $_POST['customize'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
317 |
return;
|
318 |
}
|
319 |
|
320 |
// If we can't associate the requested domain to a language, redirect to the default domain
|
321 |
+
$requested_url = pll_get_requested_url();
|
322 |
+
$requested_host = wp_parse_url( $requested_url, PHP_URL_HOST );
|
323 |
+
|
324 |
$hosts = PLL()->links_model->get_hosts();
|
325 |
+
$lang = array_search( $requested_host, $hosts );
|
326 |
|
327 |
if ( empty( $lang ) ) {
|
328 |
+
$status = get_site_option( 'dm_301_redirect' ) ? '301' : '302'; // Honor status redirect option
|
329 |
+
$redirect = str_replace( '://' . $requested_host, '://' . $hosts[ $options['default_lang'] ], $requested_url );
|
330 |
+
wp_safe_redirect( $redirect, $status );
|
331 |
exit;
|
332 |
}
|
333 |
} else {
|
modules/plugins/wp-import.php
CHANGED
@@ -89,7 +89,7 @@ class PLL_WP_Import extends WP_Import {
|
|
89 |
$lang_id = (int) substr( $post['post_title'], 12 );
|
90 |
|
91 |
if ( ! empty( $this->processed_terms[ $lang_id ] ) ) {
|
92 |
-
if ( $strings =
|
93 |
$mo = new PLL_MO();
|
94 |
$mo->import_from_db( $this->processed_terms[ $lang_id ] );
|
95 |
foreach ( $strings as $msg ) {
|
@@ -114,7 +114,7 @@ class PLL_WP_Import extends WP_Import {
|
|
114 |
global $wpdb;
|
115 |
|
116 |
foreach ( $terms as $term ) {
|
117 |
-
$translations =
|
118 |
foreach ( $translations as $slug => $old_id ) {
|
119 |
if ( $old_id && ! empty( $this->processed_terms[ $old_id ] ) && $lang = PLL()->model->get_language( $slug ) ) {
|
120 |
// Language relationship
|
@@ -162,7 +162,7 @@ class PLL_WP_Import extends WP_Import {
|
|
162 |
global $wpdb;
|
163 |
|
164 |
foreach ( $terms as $term ) {
|
165 |
-
$translations =
|
166 |
$new_translations = array();
|
167 |
|
168 |
foreach ( $translations as $slug => $old_id ) {
|
@@ -172,7 +172,7 @@ class PLL_WP_Import extends WP_Import {
|
|
172 |
}
|
173 |
|
174 |
if ( ! empty( $new_translations ) ) {
|
175 |
-
$u['case'][] = $wpdb->prepare( 'WHEN %d THEN %s', $this->processed_terms[ $term['term_id'] ],
|
176 |
$u['in'][] = (int) $this->processed_terms[ $term['term_id'] ];
|
177 |
}
|
178 |
}
|
89 |
$lang_id = (int) substr( $post['post_title'], 12 );
|
90 |
|
91 |
if ( ! empty( $this->processed_terms[ $lang_id ] ) ) {
|
92 |
+
if ( $strings = maybe_unserialize( $post['post_content'] ) ) {
|
93 |
$mo = new PLL_MO();
|
94 |
$mo->import_from_db( $this->processed_terms[ $lang_id ] );
|
95 |
foreach ( $strings as $msg ) {
|
114 |
global $wpdb;
|
115 |
|
116 |
foreach ( $terms as $term ) {
|
117 |
+
$translations = maybe_unserialize( $term['term_description'] );
|
118 |
foreach ( $translations as $slug => $old_id ) {
|
119 |
if ( $old_id && ! empty( $this->processed_terms[ $old_id ] ) && $lang = PLL()->model->get_language( $slug ) ) {
|
120 |
// Language relationship
|
162 |
global $wpdb;
|
163 |
|
164 |
foreach ( $terms as $term ) {
|
165 |
+
$translations = maybe_unserialize( $term['term_description'] );
|
166 |
$new_translations = array();
|
167 |
|
168 |
foreach ( $translations as $slug => $old_id ) {
|
172 |
}
|
173 |
|
174 |
if ( ! empty( $new_translations ) ) {
|
175 |
+
$u['case'][] = $wpdb->prepare( 'WHEN %d THEN %s', $this->processed_terms[ $term['term_id'] ], maybe_serialize( $new_translations ) );
|
176 |
$u['in'][] = (int) $this->processed_terms[ $term['term_id'] ];
|
177 |
}
|
178 |
}
|
modules/plugins/wpseo.php
CHANGED
@@ -12,23 +12,9 @@ class PLL_WPSEO {
|
|
12 |
* @since 1.6.4
|
13 |
*/
|
14 |
public function init() {
|
15 |
-
if ( ! defined( 'WPSEO_VERSION' ) ) {
|
16 |
-
return;
|
17 |
-
}
|
18 |
-
|
19 |
if ( PLL() instanceof PLL_Frontend ) {
|
20 |
add_filter( 'option_wpseo_titles', array( $this, 'wpseo_translate_titles' ) );
|
21 |
|
22 |
-
// Reloads options once the language has been defined to enable translations
|
23 |
-
// Useful only when the language is set from content
|
24 |
-
if ( version_compare( WPSEO_VERSION, '7.0', '<' ) && did_action( 'wp_loaded' ) ) {
|
25 |
-
$wpseo_front = WPSEO_Frontend::get_instance();
|
26 |
-
$options = WPSEO_Options::get_option_names();
|
27 |
-
foreach ( $options as $opt ) {
|
28 |
-
$wpseo_front->options = array_merge( $wpseo_front->options, (array) get_option( $opt ) );
|
29 |
-
}
|
30 |
-
}
|
31 |
-
|
32 |
// Filters sitemap queries to remove inactive language or to get
|
33 |
// one sitemap per language when using multiple domains or subdomains
|
34 |
// because WPSEO does not accept several domains or subdomains in one sitemap
|
@@ -43,13 +29,10 @@ class PLL_WPSEO {
|
|
43 |
} else {
|
44 |
// Get all terms in all languages when the language is set from the content or directory name
|
45 |
add_filter( 'get_terms_args', array( $this, 'wpseo_remove_terms_filter' ) );
|
46 |
-
|
47 |
-
// Add the homepages for all languages to the sitemap when the front page displays posts
|
48 |
-
if ( ! get_option( 'page_on_front' ) ) {
|
49 |
-
add_filter( 'wpseo_sitemap_post_content', array( $this, 'add_language_home_urls' ) );
|
50 |
-
}
|
51 |
}
|
52 |
|
|
|
|
|
53 |
add_filter( 'pll_home_url_white_list', array( $this, 'wpseo_home_url_white_list' ) );
|
54 |
add_action( 'wpseo_opengraph', array( $this, 'wpseo_ogp' ), 2 );
|
55 |
add_filter( 'wpseo_canonical', array( $this, 'wpseo_canonical' ) );
|
@@ -144,9 +127,11 @@ class PLL_WPSEO {
|
|
144 |
* @return $url
|
145 |
*/
|
146 |
public function wpseo_home_url( $url, $path ) {
|
147 |
-
|
|
|
|
|
148 |
|
149 |
-
if ( 'sitemap_index.xml' === $
|
150 |
$url = PLL()->links_model->switch_language_in_link( $url, PLL()->curlang );
|
151 |
}
|
152 |
|
@@ -222,30 +207,55 @@ class PLL_WPSEO {
|
|
222 |
}
|
223 |
|
224 |
/**
|
225 |
-
*
|
226 |
*
|
227 |
-
* @since
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
228 |
*
|
229 |
* @param string $str additional urls to sitemap post
|
230 |
* @return string
|
231 |
*/
|
232 |
-
public function
|
233 |
global $wpseo_sitemaps;
|
234 |
-
$renderer = version_compare( WPSEO_VERSION, '3.2', '<' ) ? $wpseo_sitemaps : $wpseo_sitemaps->renderer;
|
235 |
|
236 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
|
238 |
foreach ( $languages as $lang ) {
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
)
|
247 |
-
|
248 |
}
|
|
|
249 |
return $str;
|
250 |
}
|
251 |
|
12 |
* @since 1.6.4
|
13 |
*/
|
14 |
public function init() {
|
|
|
|
|
|
|
|
|
15 |
if ( PLL() instanceof PLL_Frontend ) {
|
16 |
add_filter( 'option_wpseo_titles', array( $this, 'wpseo_translate_titles' ) );
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
// Filters sitemap queries to remove inactive language or to get
|
19 |
// one sitemap per language when using multiple domains or subdomains
|
20 |
// because WPSEO does not accept several domains or subdomains in one sitemap
|
29 |
} else {
|
30 |
// Get all terms in all languages when the language is set from the content or directory name
|
31 |
add_filter( 'get_terms_args', array( $this, 'wpseo_remove_terms_filter' ) );
|
|
|
|
|
|
|
|
|
|
|
32 |
}
|
33 |
|
34 |
+
add_action( 'pre_get_posts', array( $this, 'before_sitemap' ), 0 ); // Needs to be fired before WPSEO_Sitemaps::redirect()
|
35 |
+
|
36 |
add_filter( 'pll_home_url_white_list', array( $this, 'wpseo_home_url_white_list' ) );
|
37 |
add_action( 'wpseo_opengraph', array( $this, 'wpseo_ogp' ), 2 );
|
38 |
add_filter( 'wpseo_canonical', array( $this, 'wpseo_canonical' ) );
|
127 |
* @return $url
|
128 |
*/
|
129 |
public function wpseo_home_url( $url, $path ) {
|
130 |
+
if ( empty( $path ) ) {
|
131 |
+
$path = ltrim( wp_parse_url( pll_get_requested_url(), PHP_URL_PATH ), '/' );
|
132 |
+
}
|
133 |
|
134 |
+
if ( 'sitemap_index.xml' === $path || preg_match( '#([^/]+?)-sitemap([0-9]+)?\.xml|([a-z]+)?-?sitemap\.xsl#', $path ) ) {
|
135 |
$url = PLL()->links_model->switch_language_in_link( $url, PLL()->curlang );
|
136 |
}
|
137 |
|
207 |
}
|
208 |
|
209 |
/**
|
210 |
+
* Add filters before the sitemap is evaluated and outputed
|
211 |
*
|
212 |
+
* @since 2.6
|
213 |
+
*/
|
214 |
+
public function before_sitemap() {
|
215 |
+
$type = get_query_var( 'sitemap' );
|
216 |
+
|
217 |
+
// Add the post post type archives in all languages to the sitemap
|
218 |
+
// Add the homepages for all languages to the sitemap when the front page displays posts
|
219 |
+
if ( $type && pll_is_translated_post_type( $type ) && ( 'post' !== $type || ( PLL()->options['force_lang'] < 2 && ! get_option( 'page_on_front' ) ) ) ) {
|
220 |
+
add_filter( "wpseo_sitemap_{$type}_content", array( $this, 'add_post_type_archive' ) );
|
221 |
+
}
|
222 |
+
}
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Adds the home and post type archives urls for all (active) languages to the sitemap
|
226 |
+
*
|
227 |
+
* @since 2.6
|
228 |
*
|
229 |
* @param string $str additional urls to sitemap post
|
230 |
* @return string
|
231 |
*/
|
232 |
+
public function add_post_type_archive( $str ) {
|
233 |
global $wpseo_sitemaps;
|
|
|
234 |
|
235 |
+
$post_type = substr( substr( current_filter(), 14 ), 0, -8 );
|
236 |
+
|
237 |
+
$languages = wp_list_filter( PLL()->model->get_languages_list(), array( 'active' => false ), 'NOT' );
|
238 |
+
|
239 |
+
if ( 'post' !== $post_type ) {
|
240 |
+
// The post type archive in the current language is already added by WPSEO
|
241 |
+
$languages = wp_list_filter( PLL()->model->get_languages_list(), array( 'slug' => pll_current_language() ), 'NOT' );
|
242 |
+
} elseif ( ! empty( PLL()->options['hide_default'] ) ) {
|
243 |
+
// The home url is of course already added by WPSEO
|
244 |
+
$languages = wp_list_filter( PLL()->model->get_languages_list(), array( 'slug' => pll_default_language() ), 'NOT' );
|
245 |
+
}
|
246 |
|
247 |
foreach ( $languages as $lang ) {
|
248 |
+
$link = 'post' === $post_type ? pll_home_url( $lang->slug ) : PLL()->links_model->switch_language_in_link( get_post_type_archive_link( $post_type ), $lang );
|
249 |
+
$str .= $wpseo_sitemaps->renderer->sitemap_url(
|
250 |
+
array(
|
251 |
+
'loc' => $link,
|
252 |
+
'mod' => WPSEO_Sitemaps::get_last_modified_gmt( $post_type ),
|
253 |
+
'pri' => 1,
|
254 |
+
'chf' => 'daily',
|
255 |
+
)
|
256 |
+
);
|
257 |
}
|
258 |
+
|
259 |
return $str;
|
260 |
}
|
261 |
|
modules/share-slug/settings-share-slug.php
CHANGED
@@ -70,10 +70,10 @@ class PLL_Settings_Share_Slug extends PLL_Settings_Module {
|
|
70 |
$( "input[name='force_lang']" ).change( function() {
|
71 |
var value = $( this ).val();
|
72 |
if ( value > 0 ) {
|
73 |
-
$( "#pll-module-share-slugs" ).removeClass( "inactive" ).addClass( "active" ).children( "td" ).children( ".row-actions" ).html( '<?php echo $activated; ?>' );
|
74 |
}
|
75 |
else {
|
76 |
-
$( "#pll-module-share-slugs" ).removeClass( "active" ).addClass( "inactive" ).children( "td" ).children( ".row-actions" ).html( '<?php echo $deactivated; ?>' );
|
77 |
}
|
78 |
} );
|
79 |
} )( jQuery );
|
70 |
$( "input[name='force_lang']" ).change( function() {
|
71 |
var value = $( this ).val();
|
72 |
if ( value > 0 ) {
|
73 |
+
$( "#pll-module-share-slugs" ).removeClass( "inactive" ).addClass( "active" ).children( "td" ).children( ".row-actions" ).html( '<?php echo $activated; // phpcs:ignore WordPress.Security.EscapeOutput ?>' );
|
74 |
}
|
75 |
else {
|
76 |
+
$( "#pll-module-share-slugs" ).removeClass( "active" ).addClass( "inactive" ).children( "td" ).children( ".row-actions" ).html( '<?php echo $deactivated; // phpcs:ignore WordPress.Security.EscapeOutput ?>' );
|
77 |
}
|
78 |
} );
|
79 |
} )( jQuery );
|
modules/sync/admin-sync.php
CHANGED
@@ -164,7 +164,7 @@ class PLL_Admin_Sync extends PLL_Sync {
|
|
164 |
// Sticky posts
|
165 |
if ( in_array( 'sticky_posts', $this->options['sync'] ) ) {
|
166 |
$stickies = get_option( 'sticky_posts' );
|
167 |
-
if ( isset( $_REQUEST['sticky'] ) && 'sticky' === $_REQUEST['sticky'] ) {
|
168 |
$stickies = array_merge( $stickies, array_values( $translations ) );
|
169 |
} else {
|
170 |
$stickies = array_diff( $stickies, array_values( $translations ) );
|
@@ -189,23 +189,31 @@ class PLL_Admin_Sync extends PLL_Sync {
|
|
189 |
|
190 |
if ( is_object( $this->$obj ) && method_exists( $this->$obj, 'copy' ) ) {
|
191 |
if ( WP_DEBUG ) {
|
192 |
-
$debug = debug_backtrace();
|
193 |
$i = 1 + empty( $debug[1]['line'] ); // The file and line are in $debug[2] if the function was called using call_user_func
|
194 |
|
195 |
-
trigger_error(
|
196 |
sprintf(
|
197 |
'%1$s was called incorrectly in %3$s on line %4$s: the call to PLL()->sync->%1$s() has been deprecated in Polylang 2.3, use PLL()->sync->%2$s->copy() instead.' . "\nError handler",
|
198 |
-
$func,
|
199 |
-
$obj,
|
200 |
-
$debug[ $i ]['file'],
|
201 |
-
$debug[ $i ]['line']
|
202 |
)
|
203 |
);
|
204 |
}
|
205 |
return call_user_func_array( array( $this->$obj, 'copy' ), $args );
|
206 |
}
|
207 |
|
208 |
-
$debug = debug_backtrace();
|
209 |
-
trigger_error(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
}
|
211 |
}
|
164 |
// Sticky posts
|
165 |
if ( in_array( 'sticky_posts', $this->options['sync'] ) ) {
|
166 |
$stickies = get_option( 'sticky_posts' );
|
167 |
+
if ( isset( $_REQUEST['sticky'] ) && 'sticky' === $_REQUEST['sticky'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
168 |
$stickies = array_merge( $stickies, array_values( $translations ) );
|
169 |
} else {
|
170 |
$stickies = array_diff( $stickies, array_values( $translations ) );
|
189 |
|
190 |
if ( is_object( $this->$obj ) && method_exists( $this->$obj, 'copy' ) ) {
|
191 |
if ( WP_DEBUG ) {
|
192 |
+
$debug = debug_backtrace(); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
193 |
$i = 1 + empty( $debug[1]['line'] ); // The file and line are in $debug[2] if the function was called using call_user_func
|
194 |
|
195 |
+
trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
196 |
sprintf(
|
197 |
'%1$s was called incorrectly in %3$s on line %4$s: the call to PLL()->sync->%1$s() has been deprecated in Polylang 2.3, use PLL()->sync->%2$s->copy() instead.' . "\nError handler",
|
198 |
+
esc_html( $func ),
|
199 |
+
esc_html( $obj ),
|
200 |
+
esc_html( $debug[ $i ]['file'] ),
|
201 |
+
absint( $debug[ $i ]['line'] )
|
202 |
)
|
203 |
);
|
204 |
}
|
205 |
return call_user_func_array( array( $this->$obj, 'copy' ), $args );
|
206 |
}
|
207 |
|
208 |
+
$debug = debug_backtrace(); // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
209 |
+
trigger_error( // phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
210 |
+
sprintf(
|
211 |
+
'Call to undefined function PLL()->sync->%1$s() in %2$s on line %3$s' . "\nError handler",
|
212 |
+
esc_html( $func ),
|
213 |
+
esc_html( $debug[0]['file'] ),
|
214 |
+
absint( $debug[0]['line'] )
|
215 |
+
),
|
216 |
+
E_USER_ERROR
|
217 |
+
);
|
218 |
}
|
219 |
}
|
modules/sync/settings-sync.php
CHANGED
@@ -48,7 +48,7 @@ class PLL_Settings_Sync extends PLL_Settings_Module {
|
|
48 |
printf(
|
49 |
'<li><label><input name="sync[%s]" type="checkbox" value="1" %s /> %s</label></li>',
|
50 |
esc_attr( $key ),
|
51 |
-
in_array( $key, $this->options['sync'] )
|
52 |
esc_html( $str )
|
53 |
);
|
54 |
}
|
48 |
printf(
|
49 |
'<li><label><input name="sync[%s]" type="checkbox" value="1" %s /> %s</label></li>',
|
50 |
esc_attr( $key ),
|
51 |
+
checked( in_array( $key, $this->options['sync'] ), true, false ),
|
52 |
esc_html( $str )
|
53 |
);
|
54 |
}
|
modules/sync/sync-metas.php
CHANGED
@@ -19,6 +19,10 @@ abstract class PLL_Sync_Metas {
|
|
19 |
public function __construct( &$polylang ) {
|
20 |
$this->model = &$polylang->model;
|
21 |
|
|
|
|
|
|
|
|
|
22 |
$this->add_all_meta_actions();
|
23 |
|
24 |
add_action( "pll_save_{$this->meta_type}", array( $this, 'save_object' ), 10, 3 );
|
@@ -126,6 +130,32 @@ abstract class PLL_Sync_Metas {
|
|
126 |
return array_unique( apply_filters( "pll_copy_{$this->meta_type}_metas", array(), $sync, $from, $to, $lang ) );
|
127 |
}
|
128 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
/**
|
130 |
* Synchronize added metas across translations
|
131 |
*
|
@@ -148,7 +178,7 @@ abstract class PLL_Sync_Metas {
|
|
148 |
$to_copy = $this->get_metas_to_copy( $id, $tr_id, $lang, true );
|
149 |
if ( in_array( $meta_key, $to_copy ) ) {
|
150 |
$meta_value = $this->maybe_translate_value( $meta_value, $meta_key, $id, $tr_id, $lang );
|
151 |
-
add_metadata( $this->meta_type, $tr_id, $meta_key, $meta_value );
|
152 |
}
|
153 |
}
|
154 |
}
|
@@ -194,22 +224,22 @@ abstract class PLL_Sync_Metas {
|
|
194 |
$avoid_recursion = true;
|
195 |
$hash = md5( "$id|$meta_key|" . maybe_serialize( $meta_value ) );
|
196 |
|
197 |
-
$
|
198 |
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
if ( empty( $this->prev_value[ $hash ] ) || $this->prev_value[ $hash ] === $prev_meta->meta_value ) {
|
206 |
$prev_value = $this->maybe_translate_value( $prev_meta->meta_value, $meta_key, $id, $tr_id, $lang );
|
207 |
-
$this->
|
208 |
-
update_metadata( $this->meta_type, $tr_id, $meta_key, $meta_value, $prev_value );
|
209 |
-
$this->restore_add_meta_action();
|
210 |
}
|
211 |
}
|
212 |
}
|
|
|
213 |
}
|
214 |
|
215 |
unset( $this->prev_value[ $hash ] );
|
@@ -257,7 +287,7 @@ abstract class PLL_Sync_Metas {
|
|
257 |
if ( '' !== $value && null !== $value && false !== $value ) { // Same test as WP
|
258 |
$value = $this->maybe_translate_value( $value, $key, $id, $tr_id, $lang );
|
259 |
}
|
260 |
-
delete_metadata( $this->meta_type, $tr_id, $key, $value );
|
261 |
}
|
262 |
}
|
263 |
}
|
@@ -298,7 +328,7 @@ abstract class PLL_Sync_Metas {
|
|
298 |
$value = reset( $metas[ $key ] );
|
299 |
$value = maybe_unserialize( $value );
|
300 |
$to_value = $this->maybe_translate_value( $value, $key, $from, $to, $lang );
|
301 |
-
update_metadata( $this->meta_type, $to, $key, $to_value );
|
302 |
} else {
|
303 |
// Multiple custom fields, either in the source or the target
|
304 |
if ( ! empty( $tr_metas[ $key ] ) ) {
|
@@ -309,7 +339,7 @@ abstract class PLL_Sync_Metas {
|
|
309 |
foreach ( $metas[ $key ] as $value ) {
|
310 |
$value = maybe_unserialize( $value );
|
311 |
$to_value = $this->maybe_translate_value( $value, $key, $from, $to, $lang );
|
312 |
-
add_metadata( $this->meta_type, $to, $key, $to_value );
|
313 |
}
|
314 |
}
|
315 |
}
|
19 |
public function __construct( &$polylang ) {
|
20 |
$this->model = &$polylang->model;
|
21 |
|
22 |
+
add_filter( "add_{$this->meta_type}_metadata", array( $this, 'can_synchronize_metadata' ), 1, 3 );
|
23 |
+
add_filter( "update_{$this->meta_type}_metadata", array( $this, 'can_synchronize_metadata' ), 1, 3 );
|
24 |
+
add_filter( "delete_{$this->meta_type}_metadata", array( $this, 'can_synchronize_metadata' ), 1, 3 );
|
25 |
+
|
26 |
$this->add_all_meta_actions();
|
27 |
|
28 |
add_action( "pll_save_{$this->meta_type}", array( $this, 'save_object' ), 10, 3 );
|
130 |
return array_unique( apply_filters( "pll_copy_{$this->meta_type}_metas", array(), $sync, $from, $to, $lang ) );
|
131 |
}
|
132 |
|
133 |
+
/**
|
134 |
+
* Disallow modifying synchronized meta if the current user can not modify translations
|
135 |
+
*
|
136 |
+
* @since 2.6
|
137 |
+
*
|
138 |
+
* @param null|bool $check Whether to allow adding/updating/deleting metadata.
|
139 |
+
* @param int $id Object ID.
|
140 |
+
* @param string $meta_key Meta key.
|
141 |
+
* @return null|bool
|
142 |
+
*/
|
143 |
+
public function can_synchronize_metadata( $check, $id, $meta_key ) {
|
144 |
+
if ( ! $this->model->{$this->meta_type}->current_user_can_synchronize( $id ) ) {
|
145 |
+
$tr_ids = $this->model->{$this->meta_type}->get_translations( $id );
|
146 |
+
|
147 |
+
foreach ( $tr_ids as $lang => $tr_id ) {
|
148 |
+
if ( $tr_id != $id ) {
|
149 |
+
$to_copy = $this->get_metas_to_copy( $id, $tr_id, $lang, true );
|
150 |
+
if ( in_array( $meta_key, $to_copy ) ) {
|
151 |
+
return false;
|
152 |
+
}
|
153 |
+
}
|
154 |
+
}
|
155 |
+
}
|
156 |
+
return $check;
|
157 |
+
}
|
158 |
+
|
159 |
/**
|
160 |
* Synchronize added metas across translations
|
161 |
*
|
178 |
$to_copy = $this->get_metas_to_copy( $id, $tr_id, $lang, true );
|
179 |
if ( in_array( $meta_key, $to_copy ) ) {
|
180 |
$meta_value = $this->maybe_translate_value( $meta_value, $meta_key, $id, $tr_id, $lang );
|
181 |
+
add_metadata( $this->meta_type, $tr_id, $meta_key, wp_slash( $meta_value ) );
|
182 |
}
|
183 |
}
|
184 |
}
|
224 |
$avoid_recursion = true;
|
225 |
$hash = md5( "$id|$meta_key|" . maybe_serialize( $meta_value ) );
|
226 |
|
227 |
+
$prev_meta = get_metadata_by_mid( $this->meta_type, $mid );
|
228 |
|
229 |
+
if ( $prev_meta ) {
|
230 |
+
$this->remove_add_meta_action(); // We don't want to sync back the new metas
|
231 |
+
$tr_ids = $this->model->{$this->meta_type}->get_translations( $id );
|
232 |
+
|
233 |
+
foreach ( $tr_ids as $lang => $tr_id ) {
|
234 |
+
if ( $tr_id != $id && in_array( $meta_key, $this->get_metas_to_copy( $id, $tr_id, $lang, true ) ) ) {
|
235 |
if ( empty( $this->prev_value[ $hash ] ) || $this->prev_value[ $hash ] === $prev_meta->meta_value ) {
|
236 |
$prev_value = $this->maybe_translate_value( $prev_meta->meta_value, $meta_key, $id, $tr_id, $lang );
|
237 |
+
$meta_value = $this->maybe_translate_value( $meta_value, $meta_key, $id, $tr_id, $lang );
|
238 |
+
update_metadata( $this->meta_type, $tr_id, $meta_key, wp_slash( $meta_value ), $prev_value );
|
|
|
239 |
}
|
240 |
}
|
241 |
}
|
242 |
+
$this->restore_add_meta_action();
|
243 |
}
|
244 |
|
245 |
unset( $this->prev_value[ $hash ] );
|
287 |
if ( '' !== $value && null !== $value && false !== $value ) { // Same test as WP
|
288 |
$value = $this->maybe_translate_value( $value, $key, $id, $tr_id, $lang );
|
289 |
}
|
290 |
+
delete_metadata( $this->meta_type, $tr_id, $key, wp_slash( $value ) );
|
291 |
}
|
292 |
}
|
293 |
}
|
328 |
$value = reset( $metas[ $key ] );
|
329 |
$value = maybe_unserialize( $value );
|
330 |
$to_value = $this->maybe_translate_value( $value, $key, $from, $to, $lang );
|
331 |
+
update_metadata( $this->meta_type, $to, $key, wp_slash( $to_value ) );
|
332 |
} else {
|
333 |
// Multiple custom fields, either in the source or the target
|
334 |
if ( ! empty( $tr_metas[ $key ] ) ) {
|
339 |
foreach ( $metas[ $key ] as $value ) {
|
340 |
$value = maybe_unserialize( $value );
|
341 |
$to_value = $this->maybe_translate_value( $value, $key, $from, $to, $lang );
|
342 |
+
add_metadata( $this->meta_type, $to, $key, wp_slash( $to_value ) );
|
343 |
}
|
344 |
}
|
345 |
}
|
modules/sync/sync-post-metas.php
CHANGED
@@ -57,9 +57,11 @@ class PLL_Sync_Post_Metas extends PLL_Sync_Metas {
|
|
57 |
}
|
58 |
}
|
59 |
|
60 |
-
// Random header image
|
61 |
if ( $this->options['media_support'] ) {
|
62 |
-
$keys[] = '
|
|
|
|
|
|
|
63 |
}
|
64 |
|
65 |
/** This filter is documented in modules/sync/sync-metas.php */
|
57 |
}
|
58 |
}
|
59 |
|
|
|
60 |
if ( $this->options['media_support'] ) {
|
61 |
+
$keys[] = '_wp_attached_file';
|
62 |
+
$keys[] = '_wp_attachment_metadata';
|
63 |
+
$keys[] = '_wp_attachment_backup_sizes';
|
64 |
+
$keys[] = '_wp_attachment_is_custom_header'; // Random header image
|
65 |
}
|
66 |
|
67 |
/** This filter is documented in modules/sync/sync-metas.php */
|
modules/sync/sync-tax.php
CHANGED
@@ -100,6 +100,41 @@ class PLL_Sync_Tax {
|
|
100 |
return $terms; // Empty $terms or untranslated taxonomy
|
101 |
}
|
102 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
/**
|
104 |
* When assigning terms to a post, assign translated terms to the translated posts (synchronisation)
|
105 |
*
|
@@ -123,24 +158,17 @@ class PLL_Sync_Tax {
|
|
123 |
|
124 |
foreach ( $tr_ids as $lang => $tr_id ) {
|
125 |
if ( $tr_id !== $object_id ) {
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
if (
|
133 |
-
$tr_terms =
|
134 |
-
|
135 |
-
foreach ( $tr_terms as $term ) {
|
136 |
-
if ( ! $this->model->term->get_translation( $term->term_id, $this->model->post->get_language( $object_id ) ) ) {
|
137 |
-
$newterms[] = (int) $term->term_id;
|
138 |
-
}
|
139 |
-
}
|
140 |
-
}
|
141 |
}
|
142 |
-
|
143 |
-
wp_set_object_terms( $tr_id, $newterms, $taxonomy, $append );
|
144 |
}
|
145 |
}
|
146 |
}
|
@@ -226,7 +254,9 @@ class PLL_Sync_Tax {
|
|
226 |
$posts = array_unique( $posts );
|
227 |
|
228 |
foreach ( $posts as $post_id ) {
|
229 |
-
|
|
|
|
|
230 |
}
|
231 |
}
|
232 |
}
|
100 |
return $terms; // Empty $terms or untranslated taxonomy
|
101 |
}
|
102 |
|
103 |
+
/**
|
104 |
+
* Maybe copy taxonomy terms from one post to the other
|
105 |
+
*
|
106 |
+
* @since 2.6
|
107 |
+
*
|
108 |
+
* @param int $object_id Source object ID.
|
109 |
+
* @param int $tr_id Target object ID.
|
110 |
+
* @param string $lang Target language.
|
111 |
+
* @param array $terms An array of object terms.
|
112 |
+
* @param string $taxonomy Taxonomy slug.
|
113 |
+
* @param bool $append Whether to append new terms to the old terms.
|
114 |
+
*/
|
115 |
+
protected function copy_object_terms( $object_id, $tr_id, $lang, $terms, $taxonomy, $append ) {
|
116 |
+
$to_copy = $this->get_taxonomies_to_copy( true, $object_id, $tr_id, $lang );
|
117 |
+
|
118 |
+
if ( in_array( $taxonomy, $to_copy ) ) {
|
119 |
+
$newterms = $this->maybe_translate_terms( $object_id, $terms, $taxonomy, $lang );
|
120 |
+
|
121 |
+
// For some reasons, the user may have untranslated terms in the translation. Don't forget them.
|
122 |
+
if ( $this->model->is_translated_taxonomy( $taxonomy ) ) {
|
123 |
+
$tr_terms = get_the_terms( $tr_id, $taxonomy );
|
124 |
+
if ( is_array( $tr_terms ) ) {
|
125 |
+
foreach ( $tr_terms as $term ) {
|
126 |
+
if ( ! $this->model->term->get_translation( $term->term_id, $this->model->post->get_language( $object_id ) ) ) {
|
127 |
+
$newterms[] = (int) $term->term_id;
|
128 |
+
}
|
129 |
+
}
|
130 |
+
}
|
131 |
+
}
|
132 |
+
|
133 |
+
wp_set_object_terms( $tr_id, $newterms, $taxonomy, $append );
|
134 |
+
}
|
135 |
+
|
136 |
+
}
|
137 |
+
|
138 |
/**
|
139 |
* When assigning terms to a post, assign translated terms to the translated posts (synchronisation)
|
140 |
*
|
158 |
|
159 |
foreach ( $tr_ids as $lang => $tr_id ) {
|
160 |
if ( $tr_id !== $object_id ) {
|
161 |
+
if ( $this->model->post->current_user_can_synchronize( $object_id ) ) {
|
162 |
+
$this->copy_object_terms( $object_id, $tr_id, $lang, $terms, $taxonomy, $append );
|
163 |
+
} else {
|
164 |
+
// No permission to synchronize, so let's synchronize in reverse order
|
165 |
+
$orig_lang = array_search( $object_id, $tr_ids );
|
166 |
+
$tr_terms = (array) get_the_terms( $tr_id, $taxonomy );
|
167 |
+
if ( is_array( $tr_terms ) ) {
|
168 |
+
$tr_terms = wp_list_pluck( $tr_terms, 'term_id' );
|
169 |
+
$this->copy_object_terms( $tr_id, $object_id, $orig_lang, $tr_terms, $taxonomy, $append );
|
|
|
|
|
|
|
|
|
|
|
|
|
170 |
}
|
171 |
+
break;
|
|
|
172 |
}
|
173 |
}
|
174 |
}
|
254 |
$posts = array_unique( $posts );
|
255 |
|
256 |
foreach ( $posts as $post_id ) {
|
257 |
+
if ( current_user_can( 'assign_term', $term_id ) ) {
|
258 |
+
wp_set_object_terms( $post_id, $term_id, $taxonomy, true );
|
259 |
+
}
|
260 |
}
|
261 |
}
|
262 |
}
|
modules/sync/sync.php
CHANGED
@@ -23,6 +23,9 @@ class PLL_Sync {
|
|
23 |
$this->post_metas = new PLL_Sync_Post_Metas( $polylang );
|
24 |
$this->term_metas = new PLL_Sync_Term_Metas( $polylang );
|
25 |
|
|
|
|
|
|
|
26 |
add_action( 'pll_save_post', array( $this, 'pll_save_post' ), 10, 3 );
|
27 |
add_action( 'created_term', array( $this, 'sync_term_parent' ), 10, 3 );
|
28 |
add_action( 'edited_term', array( $this, 'sync_term_parent' ), 10, 3 );
|
@@ -67,6 +70,52 @@ class PLL_Sync {
|
|
67 |
return $postarr;
|
68 |
}
|
69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
/**
|
71 |
* Synchronizes post fields in translations
|
72 |
*
|
@@ -79,29 +128,31 @@ class PLL_Sync {
|
|
79 |
public function pll_save_post( $post_id, $post, $translations ) {
|
80 |
global $wpdb;
|
81 |
|
82 |
-
|
|
|
83 |
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
|
90 |
-
|
91 |
-
|
92 |
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
|
|
98 |
}
|
99 |
-
}
|
100 |
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
|
|
105 |
}
|
106 |
}
|
107 |
}
|
23 |
$this->post_metas = new PLL_Sync_Post_Metas( $polylang );
|
24 |
$this->term_metas = new PLL_Sync_Term_Metas( $polylang );
|
25 |
|
26 |
+
add_filter( 'wp_insert_post_parent', array( $this, 'can_sync_post_parent' ), 10, 3 );
|
27 |
+
add_filter( 'wp_insert_post_data', array( $this, 'can_sync_post_data' ), 10, 2 );
|
28 |
+
|
29 |
add_action( 'pll_save_post', array( $this, 'pll_save_post' ), 10, 3 );
|
30 |
add_action( 'created_term', array( $this, 'sync_term_parent' ), 10, 3 );
|
31 |
add_action( 'edited_term', array( $this, 'sync_term_parent' ), 10, 3 );
|
70 |
return $postarr;
|
71 |
}
|
72 |
|
73 |
+
/**
|
74 |
+
* Prevents synchronized post parent modification if the current user hasn't enough rights
|
75 |
+
*
|
76 |
+
* @since 2.6
|
77 |
+
*
|
78 |
+
* @param int $post_parent Post parent ID
|
79 |
+
* @param int $post_id Post ID, unused
|
80 |
+
* @param array $postarr Array of parsed post data
|
81 |
+
* @return int
|
82 |
+
*/
|
83 |
+
public function can_sync_post_parent( $post_parent, $post_id, $postarr ) {
|
84 |
+
if ( ! empty( $postarr['ID'] ) && ! $this->model->post->current_user_can_synchronize( $postarr['ID'] ) ) {
|
85 |
+
$tr_ids = $this->model->post->get_translations( $postarr['ID'] );
|
86 |
+
$orig_lang = array_search( $postarr['ID'], $tr_ids );
|
87 |
+
foreach ( $tr_ids as $tr_id ) {
|
88 |
+
if ( $tr_id !== $postarr['ID'] && $post = get_post( $tr_id ) ) {
|
89 |
+
$post_parent = $post->post_parent;
|
90 |
+
break;
|
91 |
+
}
|
92 |
+
}
|
93 |
+
}
|
94 |
+
return $post_parent;
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Prevents synchronized post data modification if the current user hasn't enough rights
|
99 |
+
*
|
100 |
+
* @since 2.6
|
101 |
+
*
|
102 |
+
* @param array $data An array of slashed post data.
|
103 |
+
* @param array $postarr An array of sanitized, but otherwise unmodified post data.
|
104 |
+
* @return array
|
105 |
+
*/
|
106 |
+
public function can_sync_post_data( $data, $postarr ) {
|
107 |
+
if ( ! empty( $postarr['ID'] ) && ! $this->model->post->current_user_can_synchronize( $postarr['ID'] ) ) {
|
108 |
+
foreach ( $this->model->post->get_translations( $postarr['ID'] ) as $tr_id ) {
|
109 |
+
if ( $tr_id !== $postarr['ID'] && $post = get_post( $tr_id ) ) {
|
110 |
+
$to_sync = $this->get_fields_to_sync( $post );
|
111 |
+
$data = array_merge( $data, $to_sync );
|
112 |
+
break;
|
113 |
+
}
|
114 |
+
}
|
115 |
+
}
|
116 |
+
return $data;
|
117 |
+
}
|
118 |
+
|
119 |
/**
|
120 |
* Synchronizes post fields in translations
|
121 |
*
|
128 |
public function pll_save_post( $post_id, $post, $translations ) {
|
129 |
global $wpdb;
|
130 |
|
131 |
+
if ( $this->model->post->current_user_can_synchronize( $post_id ) ) {
|
132 |
+
$postarr = $this->get_fields_to_sync( $post );
|
133 |
|
134 |
+
if ( ! empty( $postarr ) ) {
|
135 |
+
foreach ( $translations as $lang => $tr_id ) {
|
136 |
+
if ( ! $tr_id || $tr_id === $post_id ) {
|
137 |
+
continue;
|
138 |
+
}
|
139 |
|
140 |
+
$tr_arr = $postarr;
|
141 |
+
unset( $tr_arr['post_parent'] );
|
142 |
|
143 |
+
// Do not udpate the translation parent if the user set a parent with no translation
|
144 |
+
if ( isset( $postarr['post_parent'] ) ) {
|
145 |
+
$post_parent = $postarr['post_parent'] ? $this->model->post->get_translation( $postarr['post_parent'], $lang ) : 0;
|
146 |
+
if ( ! ( $postarr['post_parent'] && ! $post_parent ) ) {
|
147 |
+
$tr_arr['post_parent'] = $post_parent;
|
148 |
+
}
|
149 |
}
|
|
|
150 |
|
151 |
+
// Update all the row at once
|
152 |
+
// Don't use wp_update_post to avoid infinite loop
|
153 |
+
$wpdb->update( $wpdb->posts, $tr_arr, array( 'ID' => $tr_id ) );
|
154 |
+
clean_post_cache( $tr_id );
|
155 |
+
}
|
156 |
}
|
157 |
}
|
158 |
}
|
modules/wpml/settings-wpml.php
CHANGED
@@ -19,8 +19,8 @@ class PLL_Settings_WPML extends PLL_Settings_Module {
|
|
19 |
$polylang,
|
20 |
array(
|
21 |
'module' => 'wpml',
|
22 |
-
'title' => __( 'WPML
|
23 |
-
'description' => __( 'WPML compatibility mode
|
24 |
)
|
25 |
);
|
26 |
}
|
19 |
$polylang,
|
20 |
array(
|
21 |
'module' => 'wpml',
|
22 |
+
'title' => __( 'WPML compatibility', 'polylang' ),
|
23 |
+
'description' => __( 'Polylang\'s WPML compatibility mode', 'polylang' ),
|
24 |
)
|
25 |
);
|
26 |
}
|
modules/wpml/wpml-api.php
CHANGED
@@ -146,7 +146,7 @@ class PLL_WPML_API {
|
|
146 |
$lang = pll_current_language();
|
147 |
$field = sprintf( '<input type="hidden" name="lang" value="%s" />', esc_attr( $lang ) );
|
148 |
$field = apply_filters( 'wpml_language_form_input_field', $field, $lang );
|
149 |
-
echo $field;
|
150 |
}
|
151 |
|
152 |
/**
|
146 |
$lang = pll_current_language();
|
147 |
$field = sprintf( '<input type="hidden" name="lang" value="%s" />', esc_attr( $lang ) );
|
148 |
$field = apply_filters( 'wpml_language_form_input_field', $field, $lang );
|
149 |
+
echo $field; // phpcs:ignore WordPress.Security.EscapeOutput
|
150 |
}
|
151 |
|
152 |
/**
|
modules/wpml/wpml-compat.php
CHANGED
@@ -77,12 +77,27 @@ class PLL_WPML_Compat {
|
|
77 |
*
|
78 |
* @since 1.0.2
|
79 |
*
|
80 |
-
* @param string $context
|
81 |
-
* @param string $name
|
82 |
-
* @param string $string
|
83 |
*/
|
84 |
public function register_string( $context, $name, $string ) {
|
85 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
$to_register = array( 'context' => $context, 'name' => $name, 'string' => $string, 'multiline' => true, 'icl' => true );
|
87 |
if ( ! in_array( $to_register, self::$strings ) && $to_register['string'] ) {
|
88 |
self::$strings[] = $to_register;
|
77 |
*
|
78 |
* @since 1.0.2
|
79 |
*
|
80 |
+
* @param string $context The group in which the string is registered.
|
81 |
+
* @param string $name A unique name for the string.
|
82 |
+
* @param string $string The string to register.
|
83 |
*/
|
84 |
public function register_string( $context, $name, $string ) {
|
85 |
+
// If a string has already been registered with the same name and context, let's replace it.
|
86 |
+
$exist_string = $this->get_string_by_context_and_name( $context, $name );
|
87 |
+
if ( $exist_string && $exist_string !== $string ) {
|
88 |
+
$languages = PLL()->model->get_languages_list();
|
89 |
+
|
90 |
+
// Assign translations of the old string to the new string.
|
91 |
+
foreach ( $languages as $language ) {
|
92 |
+
$mo = new PLL_MO();
|
93 |
+
$mo->import_from_db( $language );
|
94 |
+
$mo->add_entry( $mo->make_entry( $string, $mo->translate( $exist_string ) ) );
|
95 |
+
$mo->export_to_db( $language );
|
96 |
+
}
|
97 |
+
$this->unregister_string( $context, $name );
|
98 |
+
}
|
99 |
+
|
100 |
+
// Registers the string if it does not exist yet (multiline as in WPML).
|
101 |
$to_register = array( 'context' => $context, 'name' => $name, 'string' => $string, 'multiline' => true, 'icl' => true );
|
102 |
if ( ! in_array( $to_register, self::$strings ) && $to_register['string'] ) {
|
103 |
self::$strings[] = $to_register;
|
modules/wpml/wpml-config.php
CHANGED
@@ -71,7 +71,8 @@ class PLL_WPML_Config {
|
|
71 |
}
|
72 |
|
73 |
if ( ! empty( $this->xmls ) ) {
|
74 |
-
add_filter( 'pll_copy_post_metas', array( $this, 'copy_post_metas' ),
|
|
|
75 |
add_filter( 'pll_get_post_types', array( $this, 'translate_types' ), 10, 2 );
|
76 |
add_filter( 'pll_get_taxonomies', array( $this, 'translate_taxonomies' ), 10, 2 );
|
77 |
|
@@ -113,6 +114,29 @@ class PLL_WPML_Config {
|
|
113 |
return $metas;
|
114 |
}
|
115 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
/**
|
117 |
* Language and translation management for custom post types
|
118 |
*
|
71 |
}
|
72 |
|
73 |
if ( ! empty( $this->xmls ) ) {
|
74 |
+
add_filter( 'pll_copy_post_metas', array( $this, 'copy_post_metas' ), 20, 2 );
|
75 |
+
add_filter( 'pll_copy_term_metas', array( $this, 'copy_term_metas' ), 20, 2 );
|
76 |
add_filter( 'pll_get_post_types', array( $this, 'translate_types' ), 10, 2 );
|
77 |
add_filter( 'pll_get_taxonomies', array( $this, 'translate_taxonomies' ), 10, 2 );
|
78 |
|
114 |
return $metas;
|
115 |
}
|
116 |
|
117 |
+
/**
|
118 |
+
* Adds term metas to the list of metas to copy when creating a new translation
|
119 |
+
*
|
120 |
+
* @since 2.6
|
121 |
+
*
|
122 |
+
* @param array $metas The list of term metas to copy or synchronize.
|
123 |
+
* @param bool $sync True for sync, false for copy.
|
124 |
+
* @return array The list of term metas to copy or synchronize.
|
125 |
+
*/
|
126 |
+
public function copy_term_metas( $metas, $sync ) {
|
127 |
+
foreach ( $this->xmls as $xml ) {
|
128 |
+
foreach ( $xml->xpath( 'custom-term-fields/custom-term-field' ) as $cf ) {
|
129 |
+
$attributes = $cf->attributes();
|
130 |
+
if ( 'copy' == $attributes['action'] || ( ! $sync && in_array( $attributes['action'], array( 'translate', 'copy-once' ) ) ) ) {
|
131 |
+
$metas[] = (string) $cf;
|
132 |
+
} else {
|
133 |
+
$metas = array_diff( $metas, array( (string) $cf ) );
|
134 |
+
}
|
135 |
+
}
|
136 |
+
}
|
137 |
+
return $metas;
|
138 |
+
}
|
139 |
+
|
140 |
/**
|
141 |
* Language and translation management for custom post types
|
142 |
*
|
modules/wpml/wpml-legacy-api.php
CHANGED
@@ -116,7 +116,7 @@ if ( ! function_exists( 'icl_link_to_element' ) ) {
|
|
116 |
}
|
117 |
|
118 |
$pll_type = ( 'post' == $type || pll_is_translated_post_type( $type ) ) ? 'post' : ( 'term' == $type || pll_is_translated_taxonomy( $type ) ? 'term' : false );
|
119 |
-
if ( $pll_type && ( $lang = pll_current_language() ) && ( $tr_id = PLL()->model->$pll_type->get_translation( $id, $lang ) ) && ( 'term' === $pll_type || PLL()->
|
120 |
$id = $tr_id;
|
121 |
} elseif ( ! $return_original_if_missing ) {
|
122 |
return '';
|
@@ -149,7 +149,7 @@ if ( ! function_exists( 'icl_link_to_element' ) ) {
|
|
149 |
$link = sprintf( '<a href="%s">%s</a>', esc_url( $link ), esc_html( $text ) );
|
150 |
|
151 |
if ( $echo ) {
|
152 |
-
echo $link;
|
153 |
}
|
154 |
|
155 |
return $link;
|
@@ -325,12 +325,14 @@ if ( ! function_exists( 'wpml_get_copied_fields_for_post_edit' ) ) {
|
|
325 |
* @return array
|
326 |
*/
|
327 |
function wpml_get_copied_fields_for_post_edit() {
|
328 |
-
if ( empty( $_GET['from_post'] ) ) {
|
329 |
return array();
|
330 |
}
|
331 |
|
|
|
|
|
332 |
// Don't know what WPML does but Polylang does copy all public meta keys by default
|
333 |
-
foreach ( $keys = array_unique( array_keys( get_post_custom(
|
334 |
if ( is_protected_meta( $meta_key ) ) {
|
335 |
unset( $keys[ $k ] );
|
336 |
}
|
@@ -339,7 +341,6 @@ if ( ! function_exists( 'wpml_get_copied_fields_for_post_edit' ) ) {
|
|
339 |
// Apply our filter and fill the expected output ( see /types/embedded/includes/fields-post.php )
|
340 |
/** This filter is documented in modules/sync/admin-sync.php */
|
341 |
$arr['fields'] = array_unique( apply_filters( 'pll_copy_post_metas', empty( $keys ) ? array() : $keys, false ) );
|
342 |
-
$arr['original_post_id'] = (int) $_GET['from_post'];
|
343 |
return $arr;
|
344 |
}
|
345 |
}
|
116 |
}
|
117 |
|
118 |
$pll_type = ( 'post' == $type || pll_is_translated_post_type( $type ) ) ? 'post' : ( 'term' == $type || pll_is_translated_taxonomy( $type ) ? 'term' : false );
|
119 |
+
if ( $pll_type && ( $lang = pll_current_language() ) && ( $tr_id = PLL()->model->$pll_type->get_translation( $id, $lang ) ) && ( 'term' === $pll_type || PLL()->model->post->current_user_can_read( $tr_id ) ) ) {
|
120 |
$id = $tr_id;
|
121 |
} elseif ( ! $return_original_if_missing ) {
|
122 |
return '';
|
149 |
$link = sprintf( '<a href="%s">%s</a>', esc_url( $link ), esc_html( $text ) );
|
150 |
|
151 |
if ( $echo ) {
|
152 |
+
echo $link; // phpcs:ignore WordPress.Security.EscapeOutput
|
153 |
}
|
154 |
|
155 |
return $link;
|
325 |
* @return array
|
326 |
*/
|
327 |
function wpml_get_copied_fields_for_post_edit() {
|
328 |
+
if ( empty( $_GET['from_post'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
329 |
return array();
|
330 |
}
|
331 |
|
332 |
+
$arr['original_post_id'] = (int) $_GET['from_post']; // phpcs:ignore WordPress.Security.NonceVerification
|
333 |
+
|
334 |
// Don't know what WPML does but Polylang does copy all public meta keys by default
|
335 |
+
foreach ( $keys = array_unique( array_keys( get_post_custom( $arr['original_post_id'] ) ) ) as $k => $meta_key ) {
|
336 |
if ( is_protected_meta( $meta_key ) ) {
|
337 |
unset( $keys[ $k ] );
|
338 |
}
|
341 |
// Apply our filter and fill the expected output ( see /types/embedded/includes/fields-post.php )
|
342 |
/** This filter is documented in modules/sync/admin-sync.php */
|
343 |
$arr['fields'] = array_unique( apply_filters( 'pll_copy_post_metas', empty( $keys ) ? array() : $keys, false ) );
|
|
|
344 |
return $arr;
|
345 |
}
|
346 |
}
|
polylang.php
CHANGED
@@ -3,8 +3,8 @@
|
|
3 |
/**
|
4 |
Plugin Name: Polylang
|
5 |
Plugin URI: https://polylang.pro
|
6 |
-
Version: 2.
|
7 |
-
Author:
|
8 |
Author uri: https://polylang.pro
|
9 |
Description: Adds multilingual capability to WordPress
|
10 |
Text Domain: polylang
|
@@ -13,11 +13,12 @@ Domain Path: /languages
|
|
13 |
|
14 |
/*
|
15 |
* Copyright 2011-2019 Frédéric Demarle
|
|
|
16 |
*
|
17 |
-
* This program is free software
|
18 |
* it under the terms of the GNU General Public License as published by
|
19 |
-
* the Free Software Foundation
|
20 |
-
* (
|
21 |
*
|
22 |
* This program is distributed in the hope that it will be useful,
|
23 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
@@ -25,10 +26,7 @@ Domain Path: /languages
|
|
25 |
* GNU General Public License for more details.
|
26 |
*
|
27 |
* You should have received a copy of the GNU General Public License
|
28 |
-
* along with this program
|
29 |
-
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
30 |
-
* MA 02110-1301, USA.
|
31 |
-
*
|
32 |
*/
|
33 |
|
34 |
if ( ! defined( 'ABSPATH' ) ) {
|
@@ -53,7 +51,7 @@ if ( defined( 'POLYLANG_BASENAME' ) ) {
|
|
53 |
}
|
54 |
} else {
|
55 |
// Go on loading the plugin
|
56 |
-
define( 'POLYLANG_VERSION', '2.
|
57 |
define( 'PLL_MIN_WP_VERSION', '4.7' );
|
58 |
|
59 |
define( 'POLYLANG_FILE', __FILE__ ); // this file
|
@@ -67,11 +65,12 @@ if ( defined( 'POLYLANG_BASENAME' ) ) {
|
|
67 |
define( 'PLL_INSTALL_INC', POLYLANG_DIR . '/install' );
|
68 |
define( 'PLL_MODULES_INC', POLYLANG_DIR . '/modules' );
|
69 |
define( 'PLL_SETTINGS_INC', POLYLANG_DIR . '/settings' );
|
|
|
70 |
|
71 |
-
|
72 |
-
|
73 |
-
if ( file_exists( PLL_INC . '/class-polylang-pro.php' ) ) {
|
74 |
define( 'POLYLANG_PRO', true );
|
75 |
-
require_once PLL_INC . '/class-polylang-pro.php';
|
76 |
}
|
|
|
|
|
|
|
77 |
}
|
3 |
/**
|
4 |
Plugin Name: Polylang
|
5 |
Plugin URI: https://polylang.pro
|
6 |
+
Version: 2.6
|
7 |
+
Author: WP SYNTEX
|
8 |
Author uri: https://polylang.pro
|
9 |
Description: Adds multilingual capability to WordPress
|
10 |
Text Domain: polylang
|
13 |
|
14 |
/*
|
15 |
* Copyright 2011-2019 Frédéric Demarle
|
16 |
+
* Copyright 2019 WP SYNTEX
|
17 |
*
|
18 |
+
* This program is free software: you can redistribute it and/or modify
|
19 |
* it under the terms of the GNU General Public License as published by
|
20 |
+
* the Free Software Foundation, either version 3 of the License, or
|
21 |
+
* (at your option) any later version.
|
22 |
*
|
23 |
* This program is distributed in the hope that it will be useful,
|
24 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
26 |
* GNU General Public License for more details.
|
27 |
*
|
28 |
* You should have received a copy of the GNU General Public License
|
29 |
+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
30 |
*/
|
31 |
|
32 |
if ( ! defined( 'ABSPATH' ) ) {
|
51 |
}
|
52 |
} else {
|
53 |
// Go on loading the plugin
|
54 |
+
define( 'POLYLANG_VERSION', '2.6' );
|
55 |
define( 'PLL_MIN_WP_VERSION', '4.7' );
|
56 |
|
57 |
define( 'POLYLANG_FILE', __FILE__ ); // this file
|
65 |
define( 'PLL_INSTALL_INC', POLYLANG_DIR . '/install' );
|
66 |
define( 'PLL_MODULES_INC', POLYLANG_DIR . '/modules' );
|
67 |
define( 'PLL_SETTINGS_INC', POLYLANG_DIR . '/settings' );
|
68 |
+
define( 'PLL_PREFIX', 'pll_' );
|
69 |
|
70 |
+
if ( file_exists( PLL_MODULES_INC . '/pro.php' ) ) {
|
|
|
|
|
71 |
define( 'POLYLANG_PRO', true );
|
|
|
72 |
}
|
73 |
+
|
74 |
+
require_once PLL_INC . '/class-polylang.php';
|
75 |
+
new Polylang();
|
76 |
}
|
readme.txt
CHANGED
@@ -1,11 +1,11 @@
|
|
1 |
=== Polylang ===
|
2 |
-
Contributors: Chouby
|
3 |
Donate link: https://polylang.pro
|
4 |
Tags: multilingual, bilingual, translate, translation, language, multilanguage, international, localization
|
5 |
Requires at least: 4.7
|
6 |
Tested up to: 5.2
|
7 |
-
Stable tag: 2.
|
8 |
-
License:
|
9 |
|
10 |
Making WordPress multilingual
|
11 |
|
@@ -76,6 +76,43 @@ Don't hesitate to [give your feedback](http://wordpress.org/support/view/plugin-
|
|
76 |
|
77 |
== Changelog ==
|
78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
= 2.5.4 (2019-05-28) =
|
80 |
|
81 |
* Add Kannada to the predefined languages list
|
1 |
=== Polylang ===
|
2 |
+
Contributors: Chouby, manooweb
|
3 |
Donate link: https://polylang.pro
|
4 |
Tags: multilingual, bilingual, translate, translation, language, multilanguage, international, localization
|
5 |
Requires at least: 4.7
|
6 |
Tested up to: 5.2
|
7 |
+
Stable tag: 2.6
|
8 |
+
License: GPLv3 or later
|
9 |
|
10 |
Making WordPress multilingual
|
11 |
|
76 |
|
77 |
== Changelog ==
|
78 |
|
79 |
+
= 2.6 (2019-06-26) =
|
80 |
+
|
81 |
+
* Pro: Remove all languages files. All translations are now maintained on TranslationsPress
|
82 |
+
* Pro: Move the languages metabox to a block editor plugin
|
83 |
+
* Pro: Better management of user capabilities when synchronizing posts
|
84 |
+
* Pro: Separate REST requests from the frontend
|
85 |
+
* Pro: Copy the post slug when duplicating a post
|
86 |
+
* Pro: Duplicate ACF term metas when terms are automatically duplicated when creating a new post translation
|
87 |
+
* Pro: Fix hierarchy lost when duplicating terms
|
88 |
+
* Pro: Fix page shared slugs with special characters
|
89 |
+
* Pro: Fix synchronized posts sharing their slug when the language is set from the content
|
90 |
+
* Pro: Fix PHP warning with ACF Pro 5.8.1
|
91 |
+
* Pro: Fix ACF clone fields not translated in repeaters
|
92 |
+
* Better management of user capablities when synchronizing taxonomies terms and custom fields
|
93 |
+
* Extend string translations search to translated strings #207
|
94 |
+
* Update plugin updater to 1.6.18
|
95 |
+
* Honor the filter `pll_flag` when performing the flag validation when creating a new language
|
96 |
+
* Modify the title and the label for the language switcher menu items #307
|
97 |
+
* Add support for international domain names
|
98 |
+
* Add a title to the link icon used to add a translation #325
|
99 |
+
* Add a notice when a static front page is not translated in a language
|
100 |
+
* Add support for custom term fields in wpml-config.xml
|
101 |
+
* Add filter `pll_admin_languages_filter` for the list of items the admin bar language filter
|
102 |
+
* Add compatibility with WP Offload Media Lite. Props Daniel Berkman
|
103 |
+
* Yoast SEO: Add post type archive url in all languages to the sitemap
|
104 |
+
* Fix www. not redirected to not www. for the home page in multiple domains #311
|
105 |
+
* Fix cropped images not being synchronized
|
106 |
+
* Fix auto added page to menus when the page is created with the block editor
|
107 |
+
* Fix embed of translated static front page #318
|
108 |
+
* Fix a possible infinite redirect if the static front page is not translated
|
109 |
+
* Fix incorrect behavior of action 'wpml_register_single_string' when updating the string source
|
110 |
+
* Fix fatal error with Jetpack when no languages has been defined yet #330
|
111 |
+
* Fix a conflict with Laravel Valet. Props @chesio. #250
|
112 |
+
* Fix a conflict with Thesis.
|
113 |
+
* Fix a conflict with Pods in the block editor. Props Jory Hogeveen. #369
|
114 |
+
* Fix fatal error with Twenty Fourteen introduced in version 2.5.4. #374
|
115 |
+
|
116 |
= 2.5.4 (2019-05-28) =
|
117 |
|
118 |
* Add Kannada to the predefined languages list
|
settings/flags.php
CHANGED
@@ -153,7 +153,7 @@ $flags = array(
|
|
153 |
'me' => __( 'Montenegro', 'polylang' ),
|
154 |
'mg' => __( 'Madagascar', 'polylang' ),
|
155 |
'mh' => __( 'Marshall Islands', 'polylang' ),
|
156 |
-
'mk' => __( 'Macedonia', 'polylang' ),
|
157 |
'ml' => __( 'Mali', 'polylang' ),
|
158 |
'mm' => __( 'Myanmar', 'polylang' ),
|
159 |
'mn' => __( 'Mongolia', 'polylang' ),
|
@@ -270,4 +270,4 @@ $flags = array(
|
|
270 |
*
|
271 |
* @param array $flags
|
272 |
*/
|
273 |
-
|
153 |
'me' => __( 'Montenegro', 'polylang' ),
|
154 |
'mg' => __( 'Madagascar', 'polylang' ),
|
155 |
'mh' => __( 'Marshall Islands', 'polylang' ),
|
156 |
+
'mk' => __( 'North Macedonia', 'polylang' ),
|
157 |
'ml' => __( 'Mali', 'polylang' ),
|
158 |
'mm' => __( 'Myanmar', 'polylang' ),
|
159 |
'mn' => __( 'Mongolia', 'polylang' ),
|
270 |
*
|
271 |
* @param array $flags
|
272 |
*/
|
273 |
+
return apply_filters( 'pll_predefined_flags', $flags );
|
settings/languages.php
CHANGED
@@ -38,7 +38,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
38 |
* 'zu_ZA' (Zulu)
|
39 |
* 'zz_TR' (Zazaki)
|
40 |
*/
|
41 |
-
|
42 |
'af' => array(
|
43 |
'code' => 'af',
|
44 |
'locale' => 'af',
|
38 |
* 'zu_ZA' (Zulu)
|
39 |
* 'zz_TR' (Zazaki)
|
40 |
*/
|
41 |
+
return array(
|
42 |
'af' => array(
|
43 |
'code' => 'af',
|
44 |
'locale' => 'af',
|
settings/settings-browser.php
CHANGED
@@ -79,10 +79,10 @@ class PLL_Settings_Browser extends PLL_Settings_Module {
|
|
79 |
$( "input[name='force_lang']" ).change( function() {
|
80 |
var value = $( this ).val();
|
81 |
if ( 3 > value ) {
|
82 |
-
$( "#pll-module-browser" ).<?php echo $func; ?>.children( "td" ).children( ".row-actions" ).html( '<?php echo $link; ?>' );
|
83 |
}
|
84 |
else {
|
85 |
-
$( "#pll-module-browser" ).removeClass( "active" ).addClass( "inactive" ).children( "td" ).children( ".row-actions" ).html( '<?php echo $deactivated; ?>' );
|
86 |
}
|
87 |
} );
|
88 |
} )( jQuery );
|
79 |
$( "input[name='force_lang']" ).change( function() {
|
80 |
var value = $( this ).val();
|
81 |
if ( 3 > value ) {
|
82 |
+
$( "#pll-module-browser" ).<?php echo $func; // phpcs:ignore WordPress.Security.EscapeOutput ?>.children( "td" ).children( ".row-actions" ).html( '<?php echo $link; // phpcs:ignore WordPress.Security.EscapeOutput ?>' );
|
83 |
}
|
84 |
else {
|
85 |
+
$( "#pll-module-browser" ).removeClass( "active" ).addClass( "inactive" ).children( "td" ).children( ".row-actions" ).html( '<?php echo $deactivated; // phpcs:ignore WordPress.Security.EscapeOutput ?>' );
|
86 |
}
|
87 |
} );
|
88 |
} )( jQuery );
|
settings/settings-cpt.php
CHANGED
@@ -21,7 +21,7 @@ class PLL_Settings_CPT extends PLL_Settings_Module {
|
|
21 |
array(
|
22 |
'module' => 'cpt',
|
23 |
'title' => __( 'Custom post types and Taxonomies', 'polylang' ),
|
24 |
-
'description' => __( 'Activate
|
25 |
)
|
26 |
);
|
27 |
|
@@ -71,8 +71,8 @@ class PLL_Settings_CPT extends PLL_Settings_Module {
|
|
71 |
printf(
|
72 |
'<li><label><input name="post_types[%s]" type="checkbox" value="1" %s %s/> %s</label></li>',
|
73 |
esc_attr( $post_type ),
|
74 |
-
in_array( $post_type, $this->options['post_types'] ) || $disabled
|
75 |
-
$disabled
|
76 |
esc_html( $pt->labels->name )
|
77 |
);
|
78 |
}
|
@@ -95,8 +95,8 @@ class PLL_Settings_CPT extends PLL_Settings_Module {
|
|
95 |
printf(
|
96 |
'<li><label><input name="taxonomies[%s]" type="checkbox" value="1" %s %s/> %s</label></li>',
|
97 |
esc_attr( $taxonomy ),
|
98 |
-
in_array( $taxonomy, $this->options['taxonomies'] ) || $disabled
|
99 |
-
$disabled
|
100 |
esc_html( $tax->labels->name )
|
101 |
);
|
102 |
}
|
21 |
array(
|
22 |
'module' => 'cpt',
|
23 |
'title' => __( 'Custom post types and Taxonomies', 'polylang' ),
|
24 |
+
'description' => __( 'Activate languages and translations management for the custom post types and the taxonomies.', 'polylang' ),
|
25 |
)
|
26 |
);
|
27 |
|
71 |
printf(
|
72 |
'<li><label><input name="post_types[%s]" type="checkbox" value="1" %s %s/> %s</label></li>',
|
73 |
esc_attr( $post_type ),
|
74 |
+
checked( in_array( $post_type, $this->options['post_types'] ) || $disabled, true, false ),
|
75 |
+
disabled( $disabled, true, false ),
|
76 |
esc_html( $pt->labels->name )
|
77 |
);
|
78 |
}
|
95 |
printf(
|
96 |
'<li><label><input name="taxonomies[%s]" type="checkbox" value="1" %s %s/> %s</label></li>',
|
97 |
esc_attr( $taxonomy ),
|
98 |
+
checked( in_array( $taxonomy, $this->options['taxonomies'] ) || $disabled, true, false ),
|
99 |
+
disabled( $disabled, true, false ),
|
100 |
esc_html( $tax->labels->name )
|
101 |
);
|
102 |
}
|
settings/settings-licenses.php
CHANGED
@@ -21,11 +21,11 @@ class PLL_Settings_Licenses extends PLL_Settings_Module {
|
|
21 |
array(
|
22 |
'module' => 'licenses',
|
23 |
'title' => __( 'License keys', 'polylang' ),
|
24 |
-
'description' => __( 'Manage licenses for Polylang Pro
|
25 |
)
|
26 |
);
|
27 |
|
28 |
-
$this->buttons['cancel'] = sprintf( '<button type="button" class="button button-secondary cancel">%s</button>', __( 'Close' ) );
|
29 |
|
30 |
$this->items = apply_filters( 'pll_settings_licenses', array() );
|
31 |
|
@@ -53,7 +53,7 @@ class PLL_Settings_Licenses extends PLL_Settings_Module {
|
|
53 |
<table id="pll-licenses-table" class="form-table">
|
54 |
<?php
|
55 |
foreach ( $this->items as $item ) {
|
56 |
-
echo $this->get_row( $item );
|
57 |
}
|
58 |
?>
|
59 |
</table>
|
@@ -153,7 +153,7 @@ class PLL_Settings_Licenses extends PLL_Settings_Module {
|
|
153 |
$class = 'notice-warning notice-alt';
|
154 |
$message = sprintf(
|
155 |
/* translators: %1$s is a date, %2$s is link start tag, %3$s is link end tag. */
|
156 |
-
__( 'Your license key
|
157 |
date_i18n( get_option( 'date_format' ), strtotime( $license->expires, $now ) ),
|
158 |
sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/checkout/?edd_license_key=' . $item->license_key ),
|
159 |
'</a>'
|
@@ -187,15 +187,17 @@ class PLL_Settings_Licenses extends PLL_Settings_Module {
|
|
187 |
wp_die( -1 );
|
188 |
}
|
189 |
|
190 |
-
if ( $this->module === $_POST['module'] && ! empty( $_POST['licenses'] ) ) {
|
191 |
$x = new WP_Ajax_Response();
|
192 |
foreach ( $this->items as $item ) {
|
193 |
-
|
194 |
-
|
|
|
|
|
195 |
}
|
196 |
|
197 |
// Updated message
|
198 |
-
add_settings_error( 'general', 'settings_updated', __( 'Settings saved.' ), 'updated' );
|
199 |
ob_start();
|
200 |
settings_errors();
|
201 |
$x->Add( array( 'what' => 'success', 'data' => ob_get_clean() ) );
|
@@ -215,7 +217,11 @@ class PLL_Settings_Licenses extends PLL_Settings_Module {
|
|
215 |
wp_die( -1 );
|
216 |
}
|
217 |
|
218 |
-
|
|
|
|
|
|
|
|
|
219 |
wp_send_json(
|
220 |
array(
|
221 |
'id' => $id,
|
21 |
array(
|
22 |
'module' => 'licenses',
|
23 |
'title' => __( 'License keys', 'polylang' ),
|
24 |
+
'description' => __( 'Manage licenses for Polylang Pro and add-ons.', 'polylang' ),
|
25 |
)
|
26 |
);
|
27 |
|
28 |
+
$this->buttons['cancel'] = sprintf( '<button type="button" class="button button-secondary cancel">%s</button>', __( 'Close', 'polylang' ) );
|
29 |
|
30 |
$this->items = apply_filters( 'pll_settings_licenses', array() );
|
31 |
|
53 |
<table id="pll-licenses-table" class="form-table">
|
54 |
<?php
|
55 |
foreach ( $this->items as $item ) {
|
56 |
+
echo $this->get_row( $item ); // phpcs:ignore WordPress.Security.EscapeOutput
|
57 |
}
|
58 |
?>
|
59 |
</table>
|
153 |
$class = 'notice-warning notice-alt';
|
154 |
$message = sprintf(
|
155 |
/* translators: %1$s is a date, %2$s is link start tag, %3$s is link end tag. */
|
156 |
+
__( 'Your license key will expire soon! Precisely, it will expire on %1$s. %2$sRenew your license key today!%3$s.', 'polylang' ),
|
157 |
date_i18n( get_option( 'date_format' ), strtotime( $license->expires, $now ) ),
|
158 |
sprintf( '<a href="%s" target="_blank">', 'https://polylang.pro/checkout/?edd_license_key=' . $item->license_key ),
|
159 |
'</a>'
|
187 |
wp_die( -1 );
|
188 |
}
|
189 |
|
190 |
+
if ( isset( $_POST['module'] ) && $this->module === $_POST['module'] && ! empty( $_POST['licenses'] ) ) {
|
191 |
$x = new WP_Ajax_Response();
|
192 |
foreach ( $this->items as $item ) {
|
193 |
+
if ( ! empty( $_POST['licenses'][ $item->id ] ) ) {
|
194 |
+
$updated_item = $item->activate_license( sanitize_key( $_POST['licenses'][ $item->id ] ) );
|
195 |
+
$x->Add( array( 'what' => 'license-update', 'data' => $item->id, 'supplemental' => array( 'html' => $this->get_row( $updated_item ) ) ) );
|
196 |
+
}
|
197 |
}
|
198 |
|
199 |
// Updated message
|
200 |
+
add_settings_error( 'general', 'settings_updated', __( 'Settings saved.', 'polylang' ), 'updated' );
|
201 |
ob_start();
|
202 |
settings_errors();
|
203 |
$x->Add( array( 'what' => 'success', 'data' => ob_get_clean() ) );
|
217 |
wp_die( -1 );
|
218 |
}
|
219 |
|
220 |
+
if ( ! isset( $_POST['id'] ) ) {
|
221 |
+
wp_die( 0 );
|
222 |
+
}
|
223 |
+
|
224 |
+
$id = substr( sanitize_text_field( wp_unslash( $_POST['id'] ) ), 11 );
|
225 |
wp_send_json(
|
226 |
array(
|
227 |
'id' => $id,
|
settings/settings-media.php
CHANGED
@@ -19,7 +19,7 @@ class PLL_Settings_Media extends PLL_Settings_Module {
|
|
19 |
$polylang,
|
20 |
array(
|
21 |
'module' => 'media',
|
22 |
-
'title' => __( 'Media' ),
|
23 |
'description' => __( 'Activate languages and translations for media', 'polylang' ),
|
24 |
'active_option' => 'media_support',
|
25 |
)
|
19 |
$polylang,
|
20 |
array(
|
21 |
'module' => 'media',
|
22 |
+
'title' => __( 'Media', 'polylang' ),
|
23 |
'description' => __( 'Activate languages and translations for media', 'polylang' ),
|
24 |
'active_option' => 'media_support',
|
25 |
)
|
settings/settings-module.php
CHANGED
@@ -48,13 +48,13 @@ class PLL_Settings_Module {
|
|
48 |
'deactivate' => sprintf(
|
49 |
'<a title="%s" href="%s">%s</a>',
|
50 |
esc_attr__( 'Deactivate this module', 'polylang' ),
|
51 |
-
wp_nonce_url( '?page=mlang&
|
52 |
esc_html__( 'Deactivate', 'polylang' )
|
53 |
),
|
54 |
'activate' => sprintf(
|
55 |
'<a title="%s" href="%s">%s</a>',
|
56 |
esc_attr__( 'Activate this module', 'polylang' ),
|
57 |
-
wp_nonce_url( '?page=mlang&
|
58 |
esc_html__( 'Activate', 'polylang' )
|
59 |
),
|
60 |
'activated' => esc_html__( 'Activated', 'polylang' ),
|
@@ -62,8 +62,8 @@ class PLL_Settings_Module {
|
|
62 |
);
|
63 |
|
64 |
$this->buttons = array(
|
65 |
-
'cancel' => sprintf( '<button type="button" class="button button-secondary cancel">%s</button>', esc_html__( 'Cancel' ) ),
|
66 |
-
'save' => sprintf( '<button type="button" class="button button-primary save">%s</button>', esc_html__( 'Save Changes' ) ),
|
67 |
);
|
68 |
|
69 |
// Ajax action to save options
|
@@ -155,7 +155,7 @@ class PLL_Settings_Module {
|
|
155 |
wp_die( -1 );
|
156 |
}
|
157 |
|
158 |
-
if ( $this->module
|
159 |
// It's up to the child class to decide which options are saved, whether there are errors or not
|
160 |
$post = array_diff_key( $_POST, array_flip( array( 'action', 'module', 'pll_ajax_backend', '_pll_nonce' ) ) );
|
161 |
$options = $this->update( $post );
|
@@ -173,7 +173,7 @@ class PLL_Settings_Module {
|
|
173 |
|
174 |
if ( ! get_settings_errors() ) {
|
175 |
// Send update message
|
176 |
-
add_settings_error( 'general', 'settings_updated', __( 'Settings saved.' ), 'updated' );
|
177 |
settings_errors();
|
178 |
$x = new WP_Ajax_Response( array( 'what' => 'success', 'data' => ob_get_clean() ) );
|
179 |
$x->send();
|
@@ -230,7 +230,7 @@ class PLL_Settings_Module {
|
|
230 |
protected function default_upgrade_message() {
|
231 |
return sprintf(
|
232 |
'%s <a href="%s">%s</a>',
|
233 |
-
__( '
|
234 |
'https://polylang.pro',
|
235 |
__( 'Upgrade now.', 'polylang' )
|
236 |
);
|
48 |
'deactivate' => sprintf(
|
49 |
'<a title="%s" href="%s">%s</a>',
|
50 |
esc_attr__( 'Deactivate this module', 'polylang' ),
|
51 |
+
esc_url( wp_nonce_url( '?page=mlang&tab=modules&pll_action=deactivate&noheader=true&module=' . $this->module, 'pll_deactivate' ) ),
|
52 |
esc_html__( 'Deactivate', 'polylang' )
|
53 |
),
|
54 |
'activate' => sprintf(
|
55 |
'<a title="%s" href="%s">%s</a>',
|
56 |
esc_attr__( 'Activate this module', 'polylang' ),
|
57 |
+
esc_url( wp_nonce_url( '?page=mlang&tab=modules&pll_action=activate&noheader=true&module=' . $this->module, 'pll_activate' ) ),
|
58 |
esc_html__( 'Activate', 'polylang' )
|
59 |
),
|
60 |
'activated' => esc_html__( 'Activated', 'polylang' ),
|
62 |
);
|
63 |
|
64 |
$this->buttons = array(
|
65 |
+
'cancel' => sprintf( '<button type="button" class="button button-secondary cancel">%s</button>', esc_html__( 'Cancel', 'polylang' ) ),
|
66 |
+
'save' => sprintf( '<button type="button" class="button button-primary save">%s</button>', esc_html__( 'Save Changes', 'polylang' ) ),
|
67 |
);
|
68 |
|
69 |
// Ajax action to save options
|
155 |
wp_die( -1 );
|
156 |
}
|
157 |
|
158 |
+
if ( isset( $_POST['module'] ) && $this->module === $_POST['module'] ) {
|
159 |
// It's up to the child class to decide which options are saved, whether there are errors or not
|
160 |
$post = array_diff_key( $_POST, array_flip( array( 'action', 'module', 'pll_ajax_backend', '_pll_nonce' ) ) );
|
161 |
$options = $this->update( $post );
|
173 |
|
174 |
if ( ! get_settings_errors() ) {
|
175 |
// Send update message
|
176 |
+
add_settings_error( 'general', 'settings_updated', __( 'Settings saved.', 'polylang' ), 'updated' );
|
177 |
settings_errors();
|
178 |
$x = new WP_Ajax_Response( array( 'what' => 'success', 'data' => ob_get_clean() ) );
|
179 |
$x->send();
|
230 |
protected function default_upgrade_message() {
|
231 |
return sprintf(
|
232 |
'%s <a href="%s">%s</a>',
|
233 |
+
__( 'To enable this feature, you need Polylang Pro.', 'polylang' ),
|
234 |
'https://polylang.pro',
|
235 |
__( 'Upgrade now.', 'polylang' )
|
236 |
);
|
settings/settings-tools.php
CHANGED
@@ -33,8 +33,8 @@ class PLL_Settings_Tools extends PLL_Settings_Module {
|
|
33 |
protected function form() {
|
34 |
printf(
|
35 |
'<label for="uninstall"><input id="uninstall" name="uninstall" type="checkbox" value="1" %s /> %s</label>',
|
36 |
-
empty( $this->options['uninstall'] )
|
37 |
-
esc_html__( 'Remove all Polylang data
|
38 |
);
|
39 |
}
|
40 |
|
33 |
protected function form() {
|
34 |
printf(
|
35 |
'<label for="uninstall"><input id="uninstall" name="uninstall" type="checkbox" value="1" %s /> %s</label>',
|
36 |
+
checked( empty( $this->options['uninstall'] ), false, false ),
|
37 |
+
esc_html__( 'Remove all Polylang data upon using the "Delete" action in the "Plugins" admin page.', 'polylang' )
|
38 |
);
|
39 |
}
|
40 |
|
settings/settings-url.php
CHANGED
@@ -40,18 +40,18 @@ class PLL_Settings_Url extends PLL_Settings_Module {
|
|
40 |
<?php
|
41 |
printf(
|
42 |
'<input name="force_lang" type="radio" value="0" %s /> %s',
|
43 |
-
$this->options['force_lang']
|
44 |
esc_html__( 'The language is set from content', 'polylang' )
|
45 |
);
|
46 |
?>
|
47 |
</label>
|
48 |
-
<p class="description"><?php esc_html_e( 'Posts, pages, categories and tags
|
49 |
<label>
|
50 |
<?php
|
51 |
printf(
|
52 |
'<input name="force_lang" type="radio" value="1" %s/> %s',
|
53 |
-
|
54 |
-
$this->links_model->using_permalinks ? esc_html__( 'The language is set from the directory name in pretty permalinks', 'polylang' ) : esc_html__( 'The language is set from the code in the URL', 'polylang' )
|
55 |
);
|
56 |
?>
|
57 |
</label>
|
@@ -60,8 +60,8 @@ class PLL_Settings_Url extends PLL_Settings_Module {
|
|
60 |
<?php
|
61 |
printf(
|
62 |
'<input name="force_lang" type="radio" value="2" %s %s/> %s',
|
63 |
-
$this->links_model->using_permalinks
|
64 |
-
|
65 |
esc_html__( 'The language is set from the subdomain name in pretty permalinks', 'polylang' )
|
66 |
);
|
67 |
?>
|
@@ -71,8 +71,8 @@ class PLL_Settings_Url extends PLL_Settings_Module {
|
|
71 |
<?php
|
72 |
printf(
|
73 |
'<input name="force_lang" type="radio" value="3" %s %s/> %s',
|
74 |
-
$this->links_model->using_permalinks
|
75 |
-
|
76 |
esc_html__( 'The language is set from different domains', 'polylang' )
|
77 |
);
|
78 |
?>
|
@@ -80,12 +80,13 @@ class PLL_Settings_Url extends PLL_Settings_Module {
|
|
80 |
<table id="pll-domains-table" class="form-table" <?php echo 3 == $this->options['force_lang'] ? '' : 'style="display: none;"'; ?>>
|
81 |
<?php
|
82 |
foreach ( $this->model->get_languages_list() as $lg ) {
|
|
|
83 |
printf(
|
84 |
'<tr><td><label for="pll-domain[%1$s]">%2$s</label></td>' .
|
85 |
'<td><input name="domains[%1$s]" id="pll-domain[%1$s]" type="text" value="%3$s" class="regular-text code" aria-required="true" /></td></tr>',
|
86 |
esc_attr( $lg->slug ),
|
87 |
esc_attr( $lg->name ),
|
88 |
-
esc_url(
|
89 |
);
|
90 |
}
|
91 |
?>
|
@@ -104,7 +105,7 @@ class PLL_Settings_Url extends PLL_Settings_Module {
|
|
104 |
<?php
|
105 |
printf(
|
106 |
'<input name="hide_default" type="checkbox" value="1" %s /> %s',
|
107 |
-
$this->options['hide_default']
|
108 |
esc_html__( 'Hide URL language information for default language', 'polylang' )
|
109 |
);
|
110 |
?>
|
@@ -123,8 +124,8 @@ class PLL_Settings_Url extends PLL_Settings_Module {
|
|
123 |
<?php
|
124 |
printf(
|
125 |
'<input name="rewrite" type="radio" value="1" %s %s/> %s',
|
126 |
-
$this->links_model->using_permalinks
|
127 |
-
$this->options['rewrite']
|
128 |
esc_html__( 'Remove /language/ in pretty permalinks', 'polylang' )
|
129 |
);
|
130 |
?>
|
@@ -134,8 +135,8 @@ class PLL_Settings_Url extends PLL_Settings_Module {
|
|
134 |
<?php
|
135 |
printf(
|
136 |
'<input name="rewrite" type="radio" value="0" %s %s/> %s',
|
137 |
-
$this->links_model->using_permalinks
|
138 |
-
$this->options['rewrite']
|
139 |
esc_html__( 'Keep /language/ in pretty permalinks', 'polylang' )
|
140 |
);
|
141 |
?>
|
@@ -155,7 +156,7 @@ class PLL_Settings_Url extends PLL_Settings_Module {
|
|
155 |
<?php
|
156 |
printf(
|
157 |
'<input name="redirect_lang" type="checkbox" value="1" %s/> %s',
|
158 |
-
$this->options['redirect_lang']
|
159 |
esc_html__( 'The front page url contains the language code instead of the page name or page id', 'polylang' )
|
160 |
);
|
161 |
?>
|
@@ -291,7 +292,7 @@ class PLL_Settings_Url extends PLL_Settings_Module {
|
|
291 |
esc_html(
|
292 |
sprintf(
|
293 |
/* translators: %s is an url */
|
294 |
-
__( 'Polylang was unable to access the
|
295 |
$url
|
296 |
)
|
297 |
)
|
40 |
<?php
|
41 |
printf(
|
42 |
'<input name="force_lang" type="radio" value="0" %s /> %s',
|
43 |
+
checked( $this->options['force_lang'], 0, false ),
|
44 |
esc_html__( 'The language is set from content', 'polylang' )
|
45 |
);
|
46 |
?>
|
47 |
</label>
|
48 |
+
<p class="description"><?php esc_html_e( 'Posts, pages, categories and tags URLs will not be modified.', 'polylang' ); ?></p>
|
49 |
<label>
|
50 |
<?php
|
51 |
printf(
|
52 |
'<input name="force_lang" type="radio" value="1" %s/> %s',
|
53 |
+
checked( $this->options['force_lang'], 1, false ),
|
54 |
+
( $this->links_model->using_permalinks ? esc_html__( 'The language is set from the directory name in pretty permalinks', 'polylang' ) : esc_html__( 'The language is set from the code in the URL', 'polylang' ) )
|
55 |
);
|
56 |
?>
|
57 |
</label>
|
60 |
<?php
|
61 |
printf(
|
62 |
'<input name="force_lang" type="radio" value="2" %s %s/> %s',
|
63 |
+
disabled( $this->links_model->using_permalinks, false, false ),
|
64 |
+
checked( $this->options['force_lang'], 2, false ),
|
65 |
esc_html__( 'The language is set from the subdomain name in pretty permalinks', 'polylang' )
|
66 |
);
|
67 |
?>
|
71 |
<?php
|
72 |
printf(
|
73 |
'<input name="force_lang" type="radio" value="3" %s %s/> %s',
|
74 |
+
disabled( $this->links_model->using_permalinks, false, false ),
|
75 |
+
checked( $this->options['force_lang'], 3, false ),
|
76 |
esc_html__( 'The language is set from different domains', 'polylang' )
|
77 |
);
|
78 |
?>
|
80 |
<table id="pll-domains-table" class="form-table" <?php echo 3 == $this->options['force_lang'] ? '' : 'style="display: none;"'; ?>>
|
81 |
<?php
|
82 |
foreach ( $this->model->get_languages_list() as $lg ) {
|
83 |
+
$url = isset( $this->options['domains'][ $lg->slug ] ) ? $this->options['domains'][ $lg->slug ] : ( $lg->slug == $this->options['default_lang'] ? $this->links_model->home : '' );
|
84 |
printf(
|
85 |
'<tr><td><label for="pll-domain[%1$s]">%2$s</label></td>' .
|
86 |
'<td><input name="domains[%1$s]" id="pll-domain[%1$s]" type="text" value="%3$s" class="regular-text code" aria-required="true" /></td></tr>',
|
87 |
esc_attr( $lg->slug ),
|
88 |
esc_attr( $lg->name ),
|
89 |
+
esc_url( $url )
|
90 |
);
|
91 |
}
|
92 |
?>
|
105 |
<?php
|
106 |
printf(
|
107 |
'<input name="hide_default" type="checkbox" value="1" %s /> %s',
|
108 |
+
checked( $this->options['hide_default'], 1, false ),
|
109 |
esc_html__( 'Hide URL language information for default language', 'polylang' )
|
110 |
);
|
111 |
?>
|
124 |
<?php
|
125 |
printf(
|
126 |
'<input name="rewrite" type="radio" value="1" %s %s/> %s',
|
127 |
+
disabled( $this->links_model->using_permalinks, false, false ),
|
128 |
+
checked( $this->options['rewrite'], 1, false ),
|
129 |
esc_html__( 'Remove /language/ in pretty permalinks', 'polylang' )
|
130 |
);
|
131 |
?>
|
135 |
<?php
|
136 |
printf(
|
137 |
'<input name="rewrite" type="radio" value="0" %s %s/> %s',
|
138 |
+
disabled( $this->links_model->using_permalinks, false, false ),
|
139 |
+
checked( $this->options['rewrite'], 0, false ),
|
140 |
esc_html__( 'Keep /language/ in pretty permalinks', 'polylang' )
|
141 |
);
|
142 |
?>
|
156 |
<?php
|
157 |
printf(
|
158 |
'<input name="redirect_lang" type="checkbox" value="1" %s/> %s',
|
159 |
+
checked( $this->options['redirect_lang'], 1, false ),
|
160 |
esc_html__( 'The front page url contains the language code instead of the page name or page id', 'polylang' )
|
161 |
);
|
162 |
?>
|
292 |
esc_html(
|
293 |
sprintf(
|
294 |
/* translators: %s is an url */
|
295 |
+
__( 'Polylang was unable to access the %s URL. Please check that the URL is valid.', 'polylang' ),
|
296 |
$url
|
297 |
)
|
298 |
)
|
settings/settings.php
CHANGED
@@ -29,8 +29,8 @@ class PLL_Settings extends PLL_Admin_Base {
|
|
29 |
public function __construct( &$links_model ) {
|
30 |
parent::__construct( $links_model );
|
31 |
|
32 |
-
if ( isset( $_GET['page'] ) ) {
|
33 |
-
$this->active_tab = 'mlang' === $_GET['page'] ? 'lang' : substr( $_GET['page'], 6 );
|
34 |
}
|
35 |
|
36 |
PLL_Admin_Strings::init();
|
@@ -167,17 +167,27 @@ class PLL_Settings extends PLL_Admin_Base {
|
|
167 |
switch ( $action ) {
|
168 |
case 'add':
|
169 |
check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
|
|
|
170 |
|
171 |
-
if (
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
}
|
177 |
-
|
178 |
-
// Force checking for themes and plugins translations updates
|
179 |
-
wp_clean_themes_cache();
|
180 |
-
wp_clean_plugins_cache();
|
181 |
}
|
182 |
self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
|
183 |
break;
|
@@ -185,8 +195,8 @@ class PLL_Settings extends PLL_Admin_Base {
|
|
185 |
case 'delete':
|
186 |
check_admin_referer( 'delete-lang' );
|
187 |
|
188 |
-
if ( ! empty( $_GET['lang'] ) ) {
|
189 |
-
|
190 |
}
|
191 |
|
192 |
self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
|
@@ -194,7 +204,16 @@ class PLL_Settings extends PLL_Admin_Base {
|
|
194 |
|
195 |
case 'update':
|
196 |
check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
|
197 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
|
199 |
break;
|
200 |
|
@@ -225,13 +244,23 @@ class PLL_Settings extends PLL_Admin_Base {
|
|
225 |
|
226 |
case 'activate':
|
227 |
check_admin_referer( 'pll_activate' );
|
228 |
-
|
|
|
|
|
|
|
|
|
|
|
229 |
self::redirect();
|
230 |
break;
|
231 |
|
232 |
case 'deactivate':
|
233 |
check_admin_referer( 'pll_deactivate' );
|
234 |
-
|
|
|
|
|
|
|
|
|
|
|
235 |
self::redirect();
|
236 |
break;
|
237 |
|
@@ -267,9 +296,9 @@ class PLL_Settings extends PLL_Admin_Base {
|
|
267 |
}
|
268 |
|
269 |
// Handle user input
|
270 |
-
$action = isset( $_REQUEST['pll_action'] ) ? $_REQUEST['pll_action'] : '';
|
271 |
-
if ( 'edit' === $action && ! empty( $_GET['lang'] ) ) {
|
272 |
-
$edit_lang = $this->model->get_language( (int) $_GET['lang'] );
|
273 |
} else {
|
274 |
$this->handle_actions( $action );
|
275 |
}
|
@@ -302,7 +331,7 @@ class PLL_Settings extends PLL_Admin_Base {
|
|
302 |
printf(
|
303 |
'<div class="error"><p>%s <a href="%s">%s</a></p></div>',
|
304 |
esc_html__( 'There are posts, pages, categories or tags without language.', 'polylang' ),
|
305 |
-
wp_nonce_url( '?page=mlang&
|
306 |
esc_html__( 'You can set them all to the default language.', 'polylang' )
|
307 |
);
|
308 |
}
|
@@ -333,8 +362,8 @@ class PLL_Settings extends PLL_Admin_Base {
|
|
333 |
*/
|
334 |
public function get_predefined_languages() {
|
335 |
require_once ABSPATH . 'wp-admin/includes/translation-install.php';
|
336 |
-
include PLL_SETTINGS_INC . '/languages.php';
|
337 |
|
|
|
338 |
$translations = wp_get_available_translations();
|
339 |
|
340 |
// Keep only languages with existing WP language pack
|
29 |
public function __construct( &$links_model ) {
|
30 |
parent::__construct( $links_model );
|
31 |
|
32 |
+
if ( isset( $_GET['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
33 |
+
$this->active_tab = 'mlang' === $_GET['page'] ? 'lang' : substr( sanitize_key( $_GET['page'] ), 6 ); // phpcs:ignore WordPress.Security.NonceVerification
|
34 |
}
|
35 |
|
36 |
PLL_Admin_Strings::init();
|
167 |
switch ( $action ) {
|
168 |
case 'add':
|
169 |
check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
|
170 |
+
$errors = $this->model->add_language( $_POST );
|
171 |
|
172 |
+
if ( is_wp_error( $errors ) ) {
|
173 |
+
foreach ( $errors->get_error_messages() as $message ) {
|
174 |
+
add_settings_error( 'general', 'pll_add_language', $message );
|
175 |
+
}
|
176 |
+
} else {
|
177 |
+
add_settings_error( 'general', 'pll_languages_created', __( 'Language added.', 'polylang' ), 'updated' );
|
178 |
+
$locale = sanitize_text_field( wp_unslash( $_POST['locale'] ) ); // phpcs:ignore WordPress.Security
|
179 |
+
|
180 |
+
if ( 'en_US' !== $locale ) {
|
181 |
+
// Attempts to install the language pack
|
182 |
+
require_once ABSPATH . 'wp-admin/includes/translation-install.php';
|
183 |
+
if ( ! wp_download_language_pack( $locale ) ) {
|
184 |
+
add_settings_error( 'general', 'pll_download_mo', __( 'The language was created, but the WordPress language file was not downloaded. Please install it manually.', 'polylang' ) );
|
185 |
+
}
|
186 |
+
|
187 |
+
// Force checking for themes and plugins translations updates
|
188 |
+
wp_clean_themes_cache();
|
189 |
+
wp_clean_plugins_cache();
|
190 |
}
|
|
|
|
|
|
|
|
|
191 |
}
|
192 |
self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
|
193 |
break;
|
195 |
case 'delete':
|
196 |
check_admin_referer( 'delete-lang' );
|
197 |
|
198 |
+
if ( ! empty( $_GET['lang'] ) && $this->model->delete_language( (int) $_GET['lang'] ) ) {
|
199 |
+
add_settings_error( 'general', 'pll_languages_deleted', __( 'Language deleted.', 'polylang' ), 'updated' );
|
200 |
}
|
201 |
|
202 |
self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
|
204 |
|
205 |
case 'update':
|
206 |
check_admin_referer( 'add-lang', '_wpnonce_add-lang' );
|
207 |
+
$errors = $this->model->update_language( $_POST );
|
208 |
+
|
209 |
+
if ( is_wp_error( $errors ) ) {
|
210 |
+
foreach ( $errors->get_error_messages() as $message ) {
|
211 |
+
add_settings_error( 'general', 'pll_update_language', $message );
|
212 |
+
}
|
213 |
+
} else {
|
214 |
+
add_settings_error( 'general', 'pll_languages_updated', __( 'Language updated.', 'polylang' ), 'updated' );
|
215 |
+
}
|
216 |
+
|
217 |
self::redirect(); // To refresh the page ( possible thanks to the $_GET['noheader']=true )
|
218 |
break;
|
219 |
|
244 |
|
245 |
case 'activate':
|
246 |
check_admin_referer( 'pll_activate' );
|
247 |
+
if ( isset( $_GET['module'] ) ) {
|
248 |
+
$module = sanitize_key( $_GET['module'] );
|
249 |
+
if ( isset( $this->modules[ $module ] ) ) {
|
250 |
+
$this->modules[ $module ]->activate();
|
251 |
+
}
|
252 |
+
}
|
253 |
self::redirect();
|
254 |
break;
|
255 |
|
256 |
case 'deactivate':
|
257 |
check_admin_referer( 'pll_deactivate' );
|
258 |
+
if ( isset( $_GET['module'] ) ) {
|
259 |
+
$module = sanitize_key( $_GET['module'] );
|
260 |
+
if ( isset( $this->modules[ $module ] ) ) {
|
261 |
+
$this->modules[ $module ]->deactivate();
|
262 |
+
}
|
263 |
+
}
|
264 |
self::redirect();
|
265 |
break;
|
266 |
|
296 |
}
|
297 |
|
298 |
// Handle user input
|
299 |
+
$action = isset( $_REQUEST['pll_action'] ) ? sanitize_key( $_REQUEST['pll_action'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
|
300 |
+
if ( 'edit' === $action && ! empty( $_GET['lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
301 |
+
$edit_lang = $this->model->get_language( (int) $_GET['lang'] ); // phpcs:ignore WordPress.Security.NonceVerification
|
302 |
} else {
|
303 |
$this->handle_actions( $action );
|
304 |
}
|
331 |
printf(
|
332 |
'<div class="error"><p>%s <a href="%s">%s</a></p></div>',
|
333 |
esc_html__( 'There are posts, pages, categories or tags without language.', 'polylang' ),
|
334 |
+
esc_url( wp_nonce_url( '?page=mlang&pll_action=content-default-lang&noheader=true', 'content-default-lang' ) ),
|
335 |
esc_html__( 'You can set them all to the default language.', 'polylang' )
|
336 |
);
|
337 |
}
|
362 |
*/
|
363 |
public function get_predefined_languages() {
|
364 |
require_once ABSPATH . 'wp-admin/includes/translation-install.php';
|
|
|
365 |
|
366 |
+
$languages = include PLL_SETTINGS_INC . '/languages.php';
|
367 |
$translations = wp_get_available_translations();
|
368 |
|
369 |
// Keep only languages with existing WP language pack
|
settings/table-languages.php
CHANGED
@@ -235,7 +235,7 @@ class PLL_Table_Languages extends WP_List_Table {
|
|
235 |
* @return int -1 or 1 if $a is considered to be respectively less than or greater than $b.
|
236 |
*/
|
237 |
protected function usort_reorder( $a, $b ) {
|
238 |
-
$orderby = ! empty( $_GET['orderby'] ) ? $_GET['orderby'] : 'name';
|
239 |
// Determine sort order
|
240 |
if ( is_numeric( $a->$orderby ) ) {
|
241 |
$result = $a->$orderby > $b->$orderby ? 1 : -1;
|
@@ -243,7 +243,7 @@ class PLL_Table_Languages extends WP_List_Table {
|
|
243 |
$result = strcmp( $a->$orderby, $b->$orderby );
|
244 |
}
|
245 |
// Send final sort direction to usort
|
246 |
-
return ( empty( $_GET['order'] ) || 'asc'
|
247 |
}
|
248 |
|
249 |
/**
|
235 |
* @return int -1 or 1 if $a is considered to be respectively less than or greater than $b.
|
236 |
*/
|
237 |
protected function usort_reorder( $a, $b ) {
|
238 |
+
$orderby = ! empty( $_GET['orderby'] ) ? sanitize_key( $_GET['orderby'] ) : 'name'; // phpcs:ignore WordPress.Security.NonceVerification
|
239 |
// Determine sort order
|
240 |
if ( is_numeric( $a->$orderby ) ) {
|
241 |
$result = $a->$orderby > $b->$orderby ? 1 : -1;
|
243 |
$result = strcmp( $a->$orderby, $b->$orderby );
|
244 |
}
|
245 |
// Send final sort direction to usort
|
246 |
+
return ( empty( $_GET['order'] ) || 'asc' === $_GET['order'] ) ? $result : -$result; // phpcs:ignore WordPress.Security.NonceVerification
|
247 |
}
|
248 |
|
249 |
/**
|
settings/table-settings.php
CHANGED
@@ -59,7 +59,7 @@ class PLL_Table_Settings extends WP_List_Table {
|
|
59 |
'<tr class="plugin-update-tr">
|
60 |
<td colspan="3" class="plugin-update colspanchange">%s</td>
|
61 |
</tr>',
|
62 |
-
sprintf( '<div class="update-message notice inline notice-warning notice-alt"><p>%s</p></div>', $message )
|
63 |
);
|
64 |
}
|
65 |
|
@@ -78,8 +78,8 @@ class PLL_Table_Settings extends WP_List_Table {
|
|
78 |
</tr>',
|
79 |
esc_attr( $item->module ),
|
80 |
esc_html( $item->title ),
|
81 |
-
$form,
|
82 |
-
implode( $item->get_buttons() )
|
83 |
);
|
84 |
}
|
85 |
}
|
@@ -106,12 +106,12 @@ class PLL_Table_Settings extends WP_List_Table {
|
|
106 |
|
107 |
if ( 'cb' == $column_name ) {
|
108 |
echo '<th scope="row" class="check-column">';
|
109 |
-
echo $this->column_cb( $item );
|
110 |
echo '</th>';
|
111 |
}
|
112 |
else {
|
113 |
printf( '<td class="%s">', esc_attr( $classes ) );
|
114 |
-
echo $this->column_default( $item, $column_name );
|
115 |
echo '</td>';
|
116 |
}
|
117 |
}
|
59 |
'<tr class="plugin-update-tr">
|
60 |
<td colspan="3" class="plugin-update colspanchange">%s</td>
|
61 |
</tr>',
|
62 |
+
sprintf( '<div class="update-message notice inline notice-warning notice-alt"><p>%s</p></div>', $message ) // phpcs:ignore WordPress.Security.EscapeOutput
|
63 |
);
|
64 |
}
|
65 |
|
78 |
</tr>',
|
79 |
esc_attr( $item->module ),
|
80 |
esc_html( $item->title ),
|
81 |
+
$form, // phpcs:ignore
|
82 |
+
implode( $item->get_buttons() ) // phpcs:ignore
|
83 |
);
|
84 |
}
|
85 |
}
|
106 |
|
107 |
if ( 'cb' == $column_name ) {
|
108 |
echo '<th scope="row" class="check-column">';
|
109 |
+
echo $this->column_cb( $item ); // phpcs:ignore WordPress.Security.EscapeOutput
|
110 |
echo '</th>';
|
111 |
}
|
112 |
else {
|
113 |
printf( '<td class="%s">', esc_attr( $classes ) );
|
114 |
+
echo $this->column_default( $item, $column_name ); // phpcs:ignore WordPress.Security.EscapeOutput
|
115 |
echo '</td>';
|
116 |
}
|
117 |
}
|
settings/table-string.php
CHANGED
@@ -31,7 +31,15 @@ class PLL_Table_String extends WP_List_Table {
|
|
31 |
$this->languages = $languages;
|
32 |
$this->strings = PLL_Admin_Strings::get_strings();
|
33 |
$this->groups = array_unique( wp_list_pluck( $this->strings, 'context' ) );
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
|
36 |
add_action( 'mlang_action_string-translation', array( $this, 'save_translations' ) );
|
37 |
}
|
@@ -62,7 +70,7 @@ class PLL_Table_String extends WP_List_Table {
|
|
62 |
'<label class="screen-reader-text" for="cb-select-%1$s">%2$s</label><input id="cb-select-%1$s" type="checkbox" name="strings[]" value="%1$s" %3$s />',
|
63 |
esc_attr( $item['row'] ),
|
64 |
/* translators: accessibility text, %s is a string potentially in any language */
|
65 |
-
sprintf( __( 'Select %s' ), format_to_edit( $item['string'] ) ),
|
66 |
empty( $item['icl'] ) ? 'disabled' : '' // Only strings registered with WPML API can be removed
|
67 |
);
|
68 |
}
|
@@ -150,6 +158,29 @@ class PLL_Table_String extends WP_List_Table {
|
|
150 |
return 'string';
|
151 |
}
|
152 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
153 |
/**
|
154 |
* Sort items
|
155 |
*
|
@@ -160,8 +191,15 @@ class PLL_Table_String extends WP_List_Table {
|
|
160 |
* @return int -1 or 1 if $a is considered to be respectively less than or greater than $b.
|
161 |
*/
|
162 |
protected function usort_reorder( $a, $b ) {
|
163 |
-
|
164 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
}
|
166 |
|
167 |
/**
|
@@ -170,38 +208,47 @@ class PLL_Table_String extends WP_List_Table {
|
|
170 |
* @since 0.6
|
171 |
*/
|
172 |
public function prepare_items() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
$data = $this->strings;
|
174 |
|
175 |
-
// Filter
|
176 |
-
|
177 |
-
|
178 |
-
if ( ( -1 !== $this->selected_group && $row['context'] !== $this->selected_group ) || ( ! empty( $s ) && stripos( $row['name'], $s ) === false && stripos( $row['string'], $s ) === false ) ) {
|
179 |
-
unset( $data[ $key ] );
|
180 |
-
}
|
181 |
}
|
182 |
|
183 |
-
//
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
|
190 |
-
$mo = new PLL_MO();
|
191 |
-
$mo->import_from_db( $language );
|
192 |
foreach ( $data as $key => $row ) {
|
193 |
-
$
|
194 |
-
|
|
|
195 |
}
|
196 |
}
|
197 |
|
|
|
|
|
|
|
|
|
198 |
$per_page = $this->get_items_per_page( 'pll_strings_per_page' );
|
199 |
$this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );
|
200 |
|
201 |
-
if ( ! empty( $_GET['orderby'] ) ) { // No sort by default
|
202 |
-
usort( $data, array( $this, 'usort_reorder' ) );
|
203 |
-
}
|
204 |
-
|
205 |
$total_items = count( $data );
|
206 |
$this->items = array_slice( $data, ( $this->get_pagenum() - 1 ) * $per_page, $per_page );
|
207 |
|
@@ -212,6 +259,15 @@ class PLL_Table_String extends WP_List_Table {
|
|
212 |
'total_pages' => ceil( $total_items / $per_page ),
|
213 |
)
|
214 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
215 |
}
|
216 |
|
217 |
/**
|
@@ -234,7 +290,7 @@ class PLL_Table_String extends WP_List_Table {
|
|
234 |
* @return string|false The action name or False if no action was selected
|
235 |
*/
|
236 |
public function current_action() {
|
237 |
-
return empty( $_POST['submit'] ) ? parent::current_action() : false;
|
238 |
}
|
239 |
|
240 |
/**
|
@@ -258,7 +314,7 @@ class PLL_Table_String extends WP_List_Table {
|
|
258 |
echo '<select id="select-group" name="group">' . "\n";
|
259 |
printf(
|
260 |
'<option value="-1"%s>%s</option>' . "\n",
|
261 |
-
|
262 |
esc_html__( 'View all groups', 'polylang' )
|
263 |
);
|
264 |
|
@@ -266,13 +322,13 @@ class PLL_Table_String extends WP_List_Table {
|
|
266 |
printf(
|
267 |
'<option value="%s"%s>%s</option>' . "\n",
|
268 |
esc_attr( urlencode( $group ) ),
|
269 |
-
$this->selected_group
|
270 |
esc_html( $group )
|
271 |
);
|
272 |
}
|
273 |
echo '</select>' . "\n";
|
274 |
|
275 |
-
submit_button( __( 'Filter' ), 'button', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
|
276 |
echo '</div>';
|
277 |
}
|
278 |
|
@@ -294,7 +350,7 @@ class PLL_Table_String extends WP_List_Table {
|
|
294 |
$mo = new PLL_MO();
|
295 |
$mo->import_from_db( $language );
|
296 |
|
297 |
-
foreach ( $_POST['translation'][ $language->slug ] as $key => $translation ) {
|
298 |
/**
|
299 |
* Filter the string translation before it is saved in DB
|
300 |
* Allows to sanitize strings registered with pll_register_string
|
@@ -333,7 +389,7 @@ class PLL_Table_String extends WP_List_Table {
|
|
333 |
|
334 |
// Unregisters strings registered through WPML API
|
335 |
if ( $this->current_action() === 'delete' && ! empty( $_POST['strings'] ) && function_exists( 'icl_unregister_string' ) ) {
|
336 |
-
foreach ( $_POST['strings'] as $key ) {
|
337 |
icl_unregister_string( $this->strings[ $key ]['context'], $this->strings[ $key ]['name'] );
|
338 |
}
|
339 |
}
|
31 |
$this->languages = $languages;
|
32 |
$this->strings = PLL_Admin_Strings::get_strings();
|
33 |
$this->groups = array_unique( wp_list_pluck( $this->strings, 'context' ) );
|
34 |
+
|
35 |
+
$this->selected_group = -1;
|
36 |
+
|
37 |
+
if ( ! empty( $_GET['group'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
38 |
+
$group = sanitize_text_field( wp_unslash( $_GET['group'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
39 |
+
if ( in_array( $group, $this->groups ) ) {
|
40 |
+
$this->selected_group = $group;
|
41 |
+
}
|
42 |
+
}
|
43 |
|
44 |
add_action( 'mlang_action_string-translation', array( $this, 'save_translations' ) );
|
45 |
}
|
70 |
'<label class="screen-reader-text" for="cb-select-%1$s">%2$s</label><input id="cb-select-%1$s" type="checkbox" name="strings[]" value="%1$s" %3$s />',
|
71 |
esc_attr( $item['row'] ),
|
72 |
/* translators: accessibility text, %s is a string potentially in any language */
|
73 |
+
sprintf( __( 'Select %s', 'polylang' ), format_to_edit( $item['string'] ) ),
|
74 |
empty( $item['icl'] ) ? 'disabled' : '' // Only strings registered with WPML API can be removed
|
75 |
);
|
76 |
}
|
158 |
return 'string';
|
159 |
}
|
160 |
|
161 |
+
/**
|
162 |
+
* Search for a string in translations. Case insensitive.
|
163 |
+
*
|
164 |
+
* @since 2.6
|
165 |
+
*
|
166 |
+
* @param array $mos An array of PLL_MO objects
|
167 |
+
* @param string $s Searched string
|
168 |
+
* @return array Found strings
|
169 |
+
*/
|
170 |
+
protected function search_in_translations( $mos, $s ) {
|
171 |
+
$founds = array();
|
172 |
+
|
173 |
+
foreach ( $mos as $mo ) {
|
174 |
+
foreach ( wp_list_pluck( $mo->entries, 'translations' ) as $string => $translation ) {
|
175 |
+
if ( false !== stripos( $translation[0], $s ) ) {
|
176 |
+
$founds[] = $string;
|
177 |
+
}
|
178 |
+
}
|
179 |
+
}
|
180 |
+
|
181 |
+
return array_unique( $founds );
|
182 |
+
}
|
183 |
+
|
184 |
/**
|
185 |
* Sort items
|
186 |
*
|
191 |
* @return int -1 or 1 if $a is considered to be respectively less than or greater than $b.
|
192 |
*/
|
193 |
protected function usort_reorder( $a, $b ) {
|
194 |
+
if ( ! empty( $_GET['orderby'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
195 |
+
$orderby = sanitize_key( $_GET['orderby'] ); // phpcs:ignore WordPress.Security.NonceVerification
|
196 |
+
if ( isset( $a[ $orderby ], $b[ $orderby ] ) ) {
|
197 |
+
$result = strcmp( $a[ $orderby ], $b[ $orderby ] ); // Determine sort order
|
198 |
+
return ( empty( $_GET['order'] ) || 'asc' === $_GET['order'] ) ? $result : -$result; // phpcs:ignore WordPress.Security.NonceVerification
|
199 |
+
}
|
200 |
+
}
|
201 |
+
|
202 |
+
return 0;
|
203 |
}
|
204 |
|
205 |
/**
|
208 |
* @since 0.6
|
209 |
*/
|
210 |
public function prepare_items() {
|
211 |
+
// Is admin language filter active?
|
212 |
+
if ( $lg = get_user_meta( get_current_user_id(), 'pll_filter_content', true ) ) {
|
213 |
+
$languages = wp_list_filter( $this->languages, array( 'slug' => $lg ) );
|
214 |
+
} else {
|
215 |
+
$languages = $this->languages;
|
216 |
+
}
|
217 |
+
|
218 |
+
// Load translations
|
219 |
+
foreach ( $languages as $language ) {
|
220 |
+
$mo[ $language->slug ] = new PLL_MO();
|
221 |
+
$mo[ $language->slug ]->import_from_db( $language );
|
222 |
+
}
|
223 |
+
|
224 |
$data = $this->strings;
|
225 |
|
226 |
+
// Filter by selected group
|
227 |
+
if ( -1 !== $this->selected_group ) {
|
228 |
+
$data = wp_list_filter( $data, array( 'context' => $this->selected_group ) );
|
|
|
|
|
|
|
229 |
}
|
230 |
|
231 |
+
// Filter by searched string
|
232 |
+
$s = empty( $_GET['s'] ) ? '' : wp_unslash( $_GET['s'] ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput
|
233 |
+
|
234 |
+
if ( ! empty( $s ) ) {
|
235 |
+
// Search in translations
|
236 |
+
$in_translations = $this->search_in_translations( $mo, $s );
|
237 |
|
|
|
|
|
238 |
foreach ( $data as $key => $row ) {
|
239 |
+
if ( stripos( $row['name'], $s ) === false && stripos( $row['string'], $s ) === false && ! in_array( $row['string'], $in_translations ) ) {
|
240 |
+
unset( $data[ $key ] );
|
241 |
+
}
|
242 |
}
|
243 |
}
|
244 |
|
245 |
+
// Sorting
|
246 |
+
uasort( $data, array( $this, 'usort_reorder' ) );
|
247 |
+
|
248 |
+
// Paging
|
249 |
$per_page = $this->get_items_per_page( 'pll_strings_per_page' );
|
250 |
$this->_column_headers = array( $this->get_columns(), array(), $this->get_sortable_columns() );
|
251 |
|
|
|
|
|
|
|
|
|
252 |
$total_items = count( $data );
|
253 |
$this->items = array_slice( $data, ( $this->get_pagenum() - 1 ) * $per_page, $per_page );
|
254 |
|
259 |
'total_pages' => ceil( $total_items / $per_page ),
|
260 |
)
|
261 |
);
|
262 |
+
|
263 |
+
// Translate strings
|
264 |
+
// Kept for the end as it is a slow process
|
265 |
+
foreach ( $languages as $language ) {
|
266 |
+
foreach ( $this->items as $key => $row ) {
|
267 |
+
$this->items[ $key ]['translations'][ $language->slug ] = $mo[ $language->slug ]->translate( $row['string'] );
|
268 |
+
$this->items[ $key ]['row'] = $key; // Store the row number for convenience
|
269 |
+
}
|
270 |
+
}
|
271 |
}
|
272 |
|
273 |
/**
|
290 |
* @return string|false The action name or False if no action was selected
|
291 |
*/
|
292 |
public function current_action() {
|
293 |
+
return empty( $_POST['submit'] ) ? parent::current_action() : false; // phpcs:ignore WordPress.Security.NonceVerification
|
294 |
}
|
295 |
|
296 |
/**
|
314 |
echo '<select id="select-group" name="group">' . "\n";
|
315 |
printf(
|
316 |
'<option value="-1"%s>%s</option>' . "\n",
|
317 |
+
selected( $this->group_selected, -1, false ),
|
318 |
esc_html__( 'View all groups', 'polylang' )
|
319 |
);
|
320 |
|
322 |
printf(
|
323 |
'<option value="%s"%s>%s</option>' . "\n",
|
324 |
esc_attr( urlencode( $group ) ),
|
325 |
+
selected( $this->selected_group, $group, false ),
|
326 |
esc_html( $group )
|
327 |
);
|
328 |
}
|
329 |
echo '</select>' . "\n";
|
330 |
|
331 |
+
submit_button( __( 'Filter', 'polylang' ), 'button', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
|
332 |
echo '</div>';
|
333 |
}
|
334 |
|
350 |
$mo = new PLL_MO();
|
351 |
$mo->import_from_db( $language );
|
352 |
|
353 |
+
foreach ( $_POST['translation'][ $language->slug ] as $key => $translation ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
354 |
/**
|
355 |
* Filter the string translation before it is saved in DB
|
356 |
* Allows to sanitize strings registered with pll_register_string
|
389 |
|
390 |
// Unregisters strings registered through WPML API
|
391 |
if ( $this->current_action() === 'delete' && ! empty( $_POST['strings'] ) && function_exists( 'icl_unregister_string' ) ) {
|
392 |
+
foreach ( array_map( 'sanitize_key', $_POST['strings'] ) as $key ) {
|
393 |
icl_unregister_string( $this->strings[ $key ]['context'], $this->strings[ $key ]['name'] );
|
394 |
}
|
395 |
}
|
settings/view-about.php
CHANGED
@@ -12,7 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
12 |
<?php
|
13 |
printf(
|
14 |
/* translators: %1$s is link start tag, %2$s is link end tag. */
|
15 |
-
esc_html__( 'Polylang is provided with an extensive %1$sdocumentation%2$s (in English
|
16 |
'<a href="https://polylang.pro/doc/">',
|
17 |
'</a>'
|
18 |
);
|
@@ -27,14 +27,3 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
27 |
}
|
28 |
?>
|
29 |
</p>
|
30 |
-
<p>
|
31 |
-
<?php
|
32 |
-
printf(
|
33 |
-
/* translators: %1$s is link start tag, %2$s is link end tag. */
|
34 |
-
esc_html__( 'Polylang is released under the same license as WordPress, the %1$sGPL%2$s.', 'polylang' ),
|
35 |
-
'<a href="http://wordpress.org/about/gpl/">',
|
36 |
-
'</a>'
|
37 |
-
);
|
38 |
-
?>
|
39 |
-
</p>
|
40 |
-
|
12 |
<?php
|
13 |
printf(
|
14 |
/* translators: %1$s is link start tag, %2$s is link end tag. */
|
15 |
+
esc_html__( 'Polylang is provided with an extensive %1$sdocumentation%2$s (in English). It includes information on how to set up your multilingual site and use it on a daily basis; FAQs, and documentation for developers to adapt their plugins and themes.', 'polylang' ),
|
16 |
'<a href="https://polylang.pro/doc/">',
|
17 |
'</a>'
|
18 |
);
|
27 |
}
|
28 |
?>
|
29 |
</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
settings/view-tab-lang.php
CHANGED
@@ -28,7 +28,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
28 |
<div class="col-wrap">
|
29 |
|
30 |
<div class="form-wrap">
|
31 |
-
<
|
32 |
<?php
|
33 |
// Displays the add ( or edit ) language form
|
34 |
// Adds noheader=true in the action url to allow using wp_redirect when processing the form
|
@@ -106,12 +106,12 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
106 |
<?php
|
107 |
printf(
|
108 |
'<label><input name="rtl" type="radio" value="0" %s /> %s</label>',
|
109 |
-
! empty( $edit_lang ) && $edit_lang->is_rtl
|
110 |
esc_html__( 'left to right', 'polylang' )
|
111 |
);
|
112 |
printf(
|
113 |
'<label><input name="rtl" type="radio" value="1" %s /> %s</label>',
|
114 |
-
! empty( $edit_lang ) && $edit_lang->is_rtl
|
115 |
esc_html__( 'right to left', 'polylang' )
|
116 |
);
|
117 |
?>
|
@@ -123,7 +123,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
123 |
<select name="flag" id="flag_list">
|
124 |
<option value=""></option>
|
125 |
<?php
|
126 |
-
include PLL_SETTINGS_INC . '/flags.php';
|
127 |
foreach ( $flags as $code => $label ) {
|
128 |
/** This filter is documented in include/language.php */
|
129 |
$flag = apply_filters( 'pll_flag', array( 'url' => plugins_url( "/flags/{$code}.png", POLYLANG_FILE ) ), $code );
|
@@ -132,9 +132,9 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
132 |
'<option value="%s" data-url="%s"%s%s%s>%s</option>' . "\n",
|
133 |
esc_attr( $code ),
|
134 |
esc_url( $flag['url'] ),
|
135 |
-
empty( $flag['width'] ) ? '' : sprintf( ' data-width="%s"', (int) $flag['width'] ),
|
136 |
-
empty( $flag['height'] ) ? '' : sprintf( ' data-height="%s"', (int) $flag['height'] ),
|
137 |
-
isset( $edit_lang->flag_code ) && $edit_lang->flag_code
|
138 |
esc_html( $label )
|
139 |
);
|
140 |
}
|
@@ -172,7 +172,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
172 |
do_action( 'pll_language_add_form_fields' );
|
173 |
}
|
174 |
|
175 |
-
submit_button( ! empty( $edit_lang ) ? __( 'Update' ) : __( 'Add new language', 'polylang' ) ); // since WP 3.1
|
176 |
?>
|
177 |
</form>
|
178 |
</div><!-- form-wrap -->
|
28 |
<div class="col-wrap">
|
29 |
|
30 |
<div class="form-wrap">
|
31 |
+
<h2><?php echo ! empty( $edit_lang ) ? esc_html__( 'Edit language', 'polylang' ) : esc_html__( 'Add new language', 'polylang' ); ?></h2>
|
32 |
<?php
|
33 |
// Displays the add ( or edit ) language form
|
34 |
// Adds noheader=true in the action url to allow using wp_redirect when processing the form
|
106 |
<?php
|
107 |
printf(
|
108 |
'<label><input name="rtl" type="radio" value="0" %s /> %s</label>',
|
109 |
+
checked( ! empty( $edit_lang ) && $edit_lang->is_rtl, false, false ),
|
110 |
esc_html__( 'left to right', 'polylang' )
|
111 |
);
|
112 |
printf(
|
113 |
'<label><input name="rtl" type="radio" value="1" %s /> %s</label>',
|
114 |
+
checked( ! empty( $edit_lang ) && $edit_lang->is_rtl, true, false ),
|
115 |
esc_html__( 'right to left', 'polylang' )
|
116 |
);
|
117 |
?>
|
123 |
<select name="flag" id="flag_list">
|
124 |
<option value=""></option>
|
125 |
<?php
|
126 |
+
$flags = include PLL_SETTINGS_INC . '/flags.php';
|
127 |
foreach ( $flags as $code => $label ) {
|
128 |
/** This filter is documented in include/language.php */
|
129 |
$flag = apply_filters( 'pll_flag', array( 'url' => plugins_url( "/flags/{$code}.png", POLYLANG_FILE ) ), $code );
|
132 |
'<option value="%s" data-url="%s"%s%s%s>%s</option>' . "\n",
|
133 |
esc_attr( $code ),
|
134 |
esc_url( $flag['url'] ),
|
135 |
+
( empty( $flag['width'] ) ? '' : sprintf( ' data-width="%s"', (int) $flag['width'] ) ),
|
136 |
+
( empty( $flag['height'] ) ? '' : sprintf( ' data-height="%s"', (int) $flag['height'] ) ),
|
137 |
+
selected( isset( $edit_lang->flag_code ) && $edit_lang->flag_code === $code, true, false ),
|
138 |
esc_html( $label )
|
139 |
);
|
140 |
}
|
172 |
do_action( 'pll_language_add_form_fields' );
|
173 |
}
|
174 |
|
175 |
+
submit_button( ! empty( $edit_lang ) ? __( 'Update', 'polylang' ) : __( 'Add new language', 'polylang' ) ); // since WP 3.1
|
176 |
?>
|
177 |
</form>
|
178 |
</div><!-- form-wrap -->
|
uninstall.php
CHANGED
@@ -46,9 +46,23 @@ class PLL_Uninstall {
|
|
46 |
return;
|
47 |
}
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
// Suppress data of the old model < 1.2
|
50 |
// FIXME: to remove when support for v1.1.6 will be dropped
|
51 |
-
global $wpdb;
|
52 |
$wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
|
53 |
|
54 |
// Do nothing if the termmeta table does not exists
|
@@ -70,7 +84,6 @@ class PLL_Uninstall {
|
|
70 |
// Delete users options
|
71 |
foreach ( get_users( array( 'fields' => 'ID' ) ) as $user_id ) {
|
72 |
delete_user_meta( $user_id, 'pll_filter_content' );
|
73 |
-
delete_user_meta( $user_id, 'pll_duplicate_content' );
|
74 |
foreach ( $languages as $lang ) {
|
75 |
delete_user_meta( $user_id, 'description_' . $lang->slug );
|
76 |
}
|
@@ -138,7 +151,6 @@ class PLL_Uninstall {
|
|
138 |
// Delete transients
|
139 |
delete_transient( 'pll_languages_list' );
|
140 |
delete_transient( 'pll_upgrade_1_4' );
|
141 |
-
delete_transient( 'pll_translated_slugs' );
|
142 |
}
|
143 |
}
|
144 |
|
46 |
return;
|
47 |
}
|
48 |
|
49 |
+
global $wpdb;
|
50 |
+
|
51 |
+
// Executes each module's uninstall script, if it exists
|
52 |
+
$pll_modules_dir = dirname( __FILE__ ) . '/modules';
|
53 |
+
opendir( $pll_modules_dir );
|
54 |
+
while ( ( $module = readdir() ) != false ) {
|
55 |
+
if ( substr( $module, 0, 1 ) !== '.' ) {
|
56 |
+
$uninstall_script = $pll_modules_dir . '/' . $module . '/uninstall.php';
|
57 |
+
if ( file_exists( $uninstall_script ) ) {
|
58 |
+
require $uninstall_script;
|
59 |
+
}
|
60 |
+
}
|
61 |
+
}
|
62 |
+
closedir();
|
63 |
+
|
64 |
// Suppress data of the old model < 1.2
|
65 |
// FIXME: to remove when support for v1.1.6 will be dropped
|
|
|
66 |
$wpdb->termmeta = $wpdb->prefix . 'termmeta'; // registers the termmeta table in wpdb
|
67 |
|
68 |
// Do nothing if the termmeta table does not exists
|
84 |
// Delete users options
|
85 |
foreach ( get_users( array( 'fields' => 'ID' ) ) as $user_id ) {
|
86 |
delete_user_meta( $user_id, 'pll_filter_content' );
|
|
|
87 |
foreach ( $languages as $lang ) {
|
88 |
delete_user_meta( $user_id, 'description_' . $lang->slug );
|
89 |
}
|
151 |
// Delete transients
|
152 |
delete_transient( 'pll_languages_list' );
|
153 |
delete_transient( 'pll_upgrade_1_4' );
|
|
|
154 |
}
|
155 |
}
|
156 |
|