PluginProbe
Polylang / 2.6.2
Polylang v2.6.2
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / admin / admin-filters-term.php

admin-filters-term.php in Polylang 2.6.2, at admin/admin-filters-term.php

629 lines 21.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Manages filters and actions related to terms on admin side
5 *
6 * @since 1.2
7 */
8 class PLL_Admin_Filters_Term {
9 public $links, $model, $options, $pref_lang;
10 protected $pre_term_name; // Used to store the term name before creating a slug if needed
11 protected $post_id; // Used to store the current post_id when bulk editing posts
12
13 /**
14 * Constructor: setups filters and actions
15 *
16 * @param object $polylang
17 */
18 public function __construct( &$polylang ) {
19 $this->links = &$polylang->links;
20 $this->model = &$polylang->model;
21 $this->options = &$polylang->options;
22 $this->pref_lang = &$polylang->pref_lang;
23
24 foreach ( $this->model->get_translated_taxonomies() as $tax ) {
25 // Adds the language field in the 'Categories' and 'Post Tags' panels
26 add_action( $tax . '_add_form_fields', array( $this, 'add_term_form' ) );
27
28 // Adds the language field and translations tables in the 'Edit Category' and 'Edit Tag' panels
29 add_action( $tax . '_edit_form_fields', array( $this, 'edit_term_form' ) );
30 }
31
32 // Adds actions related to languages when creating or saving categories and post tags
33 add_filter( 'wp_dropdown_cats', array( $this, 'wp_dropdown_cats' ) );
34 add_action( 'create_term', array( $this, 'save_term' ), 900, 3 );
35 add_action( 'edit_term', array( $this, 'save_term' ), 900, 3 ); // Late as it may conflict with other plugins, see http://wordpress.org/support/topic/polylang-and-wordpress-seo-by-yoast
36 add_action( 'pre_post_update', array( $this, 'pre_post_update' ) );
37 add_filter( 'pre_term_name', array( $this, 'pre_term_name' ) );
38 add_filter( 'pre_term_slug', array( $this, 'pre_term_slug' ), 10, 2 );
39
40 // Ajax response for edit term form
41 add_action( 'wp_ajax_term_lang_choice', array( $this, 'term_lang_choice' ) );
42 add_action( 'wp_ajax_pll_terms_not_translated', array( $this, 'ajax_terms_not_translated' ) );
43
44 // Allows to get the default categories in all languages
45 add_filter( 'option_default_category', array( $this, 'option_default_category' ) );
46 add_action( 'update_option_default_category', array( $this, 'update_option_default_category' ), 10, 2 );
47
48 // Updates the translations term ids when splitting a shared term
49 add_action( 'split_shared_term', array( $this, 'split_shared_term' ), 10, 4 ); // WP 4.2
50 }
51
52 /**
53 * Adds the language field in the 'Categories' and 'Post Tags' panels
54 *
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(
93 '<div class="form-field">
94 <label for="term_lang_choice">%s</label>
95 <div id="select-add-term-language">%s</div>
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
108 echo '<div id="term-translations" class="form-field">';
109 if ( $lang ) {
110 include PLL_ADMIN_INC . '/view-translations-term.php';
111 }
112 echo '</div>' . "\n";
113 }
114
115 /**
116 * Adds the language field and translations tables in the 'Edit Category' and 'Edit Tag' panels
117 *
118 * @since 0.1
119 *
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;
133 }
134
135 $term_id = $tag->term_id;
136 $taxonomy = $tag->taxonomy;
137
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">
165 %s<br />
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
174 echo '<tr id="term-translations" class="form-field">';
175 if ( $lang ) {
176 include PLL_ADMIN_INC . '/view-translations-term.php';
177 }
178 echo '</tr>' . "\n";
179 }
180
181 /**
182 * Translates term parent if exists when using "Add new" ( translation )
183 *
184 * @since 0.7
185 *
186 * @param string $output html markup for dropdown list of categories
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 }
202 }
203 }
204 return $output;
205 }
206
207 /**
208 * Stores the current post_id when bulk editing posts for use in save_language and pre_term_slug
209 *
210 * @since 1.7
211 *
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 }
219
220 /**
221 * Saves language
222 *
223 * @since 1.5
224 *
225 * @param int $term_id
226 * @param string $taxonomy
227 */
228 protected function save_language( $term_id, $taxonomy ) {
229 global $wpdb;
230 // Security checks are necessary to accept language modifications
231 // as 'wp_update_term' can be called from outside WP admin
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
245 elseif ( isset( $_GET['bulk_edit'], $_GET['inline_lang_choice'] ) ) {
246 check_admin_referer( 'bulk-posts' );
247
248 // Bulk edit does not modify the language
249 // So we possibly create a tag in several languages
250 if ( -1 == $_GET['inline_lang_choice'] ) {
251 // The language of the current term is set a according to the language of the current post
252 $this->model->term->set_language( $term_id, $this->model->post->get_language( $this->post_id ) );
253 $term = get_term( $term_id, $taxonomy );
254
255 // Get all terms with the same name
256 // FIXME backward compatibility WP < 4.2
257 // No WP function to get all terms with the exact same name so let's use a custom query
258 // $terms = get_terms( $taxonomy, array( 'name' => $term->name, 'hide_empty' => false, 'fields' => 'ids' ) ); should be OK in 4.2
259 // I may need to rework the loop below
260 $terms = $wpdb->get_results(
261 $wpdb->prepare(
262 "SELECT t.term_id FROM $wpdb->terms AS t
263 INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id
264 WHERE tt.taxonomy = %s AND t.name = %s",
265 $taxonomy,
266 $term->name
267 )
268 );
269
270 // If we have several terms with the same name, they are translations of each other
271 if ( count( $terms ) > 1 ) {
272 foreach ( $terms as $term ) {
273 $translations[ $this->model->term->get_language( $term->term_id )->slug ] = $term->term_id;
274 }
275
276 $this->model->term->save_translations( $term_id, $translations );
277 }
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
285 // Quick edit
286 elseif ( isset( $_POST['inline_lang_choice'] ) ) {
287 check_ajax_referer(
288 isset( $_POST['action'] ) && 'inline-save' == $_POST['action'] ? 'inlineeditnonce' : 'taxinlineeditnonce', // Post quick edit or tag quick edit ?
289 '_inline_edit'
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
297 if ( $old_lang && $old_lang->slug != $lang->slug ) {
298 if ( array_key_exists( $lang->slug, $translations ) ) {
299 $this->model->term->delete_translation( $term_id );
300 }
301
302 elseif ( array_key_exists( $old_lang->slug, $translations ) ) {
303 unset( $translations[ $old_lang->slug ] );
304 $this->model->term->save_translations( $term_id, $translations );
305 }
306 }
307
308 $this->model->term->set_language( $term_id, $lang ); // Set new language
309 }
310
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
318 /**
319 * Save translations from our form
320 *
321 * @since 1.5
322 *
323 * @param int $term_id
324 * @return array
325 */
326 protected function save_translations( $term_id ) {
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 );
341
342 return $translations;
343 }
344
345 /**
346 * Called when a category or post tag is created or edited
347 * Saves language and translations
348 *
349 * @since 0.1
350 *
351 * @param int $term_id
352 * @param int $tt_id term taxonomy id
353 * @param string $taxonomy
354 */
355 public function save_term( $term_id, $tt_id, $taxonomy ) {
356 // Does nothing except on taxonomies which are filterable
357 if ( ! $this->model->is_translated_taxonomy( $taxonomy ) ) {
358 return;
359 }
360
361 // Capability check
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 }
372 }
373
374 /**
375 * Stores the term name for use in pre_term_slug
376 *
377 * @since 0.9.5
378 *
379 * @param string $name term name
380 * @return string unmodified term name
381 */
382 public function pre_term_name( $name ) {
383 return $this->pre_term_name = $name;
384 }
385
386 /**
387 * Creates the term slug in case the term already exists in another language
388 *
389 * @since 0.9.5
390 *
391 * @param string $slug
392 * @param string $taxonomy
393 * @return string
394 */
395 public function pre_term_slug( $slug, $taxonomy ) {
396 $name = sanitize_title( $this->pre_term_name );
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 }
418
419 return $slug;
420 }
421
422 /**
423 * Ajax response for edit term form
424 *
425 * @since 0.2
426 */
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();
444 if ( $lang ) {
445 include PLL_ADMIN_INC . '/view-translations-term.php';
446 }
447 $x = new WP_Ajax_Response( array( 'what' => 'translations', 'data' => ob_get_contents() ) );
448 ob_end_clean();
449
450 // Parent dropdown list ( only for hierarchical taxonomies )
451 // $args copied from edit_tags.php except echo
452 if ( is_taxonomy_hierarchical( $taxonomy ) ) {
453 $args = array(
454 'hide_empty' => 0,
455 'hide_if_empty' => false,
456 'taxonomy' => $taxonomy,
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 ) ) );
464 }
465
466 // Tag cloud
467 // Tests copied from edit_tags.php
468 else {
469 $tax = get_taxonomy( $taxonomy );
470 if ( ! is_null( $tax->labels->popular_items ) ) {
471 $args = array( 'taxonomy' => $taxonomy, 'echo' => false );
472 if ( current_user_can( $tax->cap->edit_terms ) ) {
473 $args = array_merge( $args, array( 'link' => 'edit' ) );
474 }
475
476 if ( $tag_cloud = wp_tag_cloud( $args ) ) {
477 $html = sprintf( '<div class="tagcloud"><h2>%1$s</h2>%2$s</div>', esc_html( $tax->labels->popular_items ), $tag_cloud );
478 $x->Add( array( 'what' => 'tag_cloud', 'data' => $html ) );
479 }
480 }
481 }
482
483 // Flag
484 $x->Add( array( 'what' => 'flag', 'data' => empty( $lang->flag ) ? esc_html( $lang->slug ) : $lang->flag ) );
485
486 $x->send();
487 }
488
489 /**
490 * Ajax response for input in translation autocomplete input box
491 *
492 * @since 1.5
493 */
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
514 // It is more efficient to use one common query for all languages as soon as there are more than 2
515 foreach ( get_terms( $taxonomy, 'hide_empty=0&lang=0&name__like=' . $s ) as $term ) {
516 $lang = $this->model->term->get_language( $term->term_id );
517
518 if ( $lang && $lang->slug == $translation_language->slug && ! $this->model->term->get_translation( $term->term_id, $term_language ) ) {
519 $return[] = array(
520 'id' => $term->term_id,
521 'value' => $term->name,
522 'link' => $this->links->edit_term_translation_link( $term->term_id, $taxonomy, $post_type ),
523 );
524 }
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,
533 array(
534 'id' => $term_id,
535 'value' => $term->name,
536 'link' => $this->links->edit_term_translation_link( $term->term_id, $taxonomy, $post_type ),
537 )
538 );
539 }
540
541 wp_die( wp_json_encode( $return ) );
542 }
543
544 /**
545 * Filters the default category in note below the category list table and in settings->writing dropdown
546 *
547 * @since 1.2
548 *
549 * @param int $value
550 * @return int
551 */
552 public function option_default_category( $value ) {
553 if ( isset( $this->pref_lang ) && $tr = $this->model->term->get( $value, $this->pref_lang ) ) {
554 $value = $tr;
555 }
556 return $value;
557 }
558
559 /**
560 * Checks if the new default category is translated in all languages
561 * If not, create the translations
562 *
563 * @since 1.7
564 *
565 * @param int $old_value
566 * @param int $value
567 */
568 public function update_option_default_category( $old_value, $value ) {
569 $default_cat_lang = $this->model->term->get_language( $value );
570
571 // Assign a default language to default category
572 if ( ! $default_cat_lang ) {
573 $default_cat_lang = $this->model->get_language( $this->options['default_lang'] );
574 $this->model->term->set_language( (int) $value, $default_cat_lang );
575 }
576
577 foreach ( $this->model->get_languages_list() as $language ) {
578 if ( $language->slug != $default_cat_lang->slug && ! $this->model->term->get_translation( $value, $language ) ) {
579 $this->model->create_default_category( $language );
580 }
581 }
582 }
583
584 /**
585 * Updates the translations term ids when splitting a shared term
586 * Splits translations if these are shared terms too
587 *
588 * @since 1.7
589 *
590 * @param int $term_id Shared term_id
591 * @param int $new_term_id
592 * @param int $term_taxonomy_id
593 * @param string $taxonomy
594 */
595 public function split_shared_term( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
596 if ( ! $this->model->is_translated_taxonomy( $taxonomy ) ) {
597 return;
598 }
599
600 // Avoid recursion
601 static $avoid_recursion = false;
602 if ( $avoid_recursion ) {
603 return;
604 }
605
606 $avoid_recursion = true;
607 $lang = $this->model->term->get_language( $term_id );
608
609 foreach ( $this->model->term->get_translations( $term_id ) as $key => $tr_id ) {
610 if ( $lang->slug == $key ) {
611 $translations[ $key ] = $new_term_id;
612 }
613 else {
614 $tr_term = get_term( $tr_id, $taxonomy );
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 }
622 $this->model->term->set_language( $translations[ $key ], $key );
623 }
624
625 $this->model->term->save_translations( $new_term_id, $translations );
626 $avoid_recursion = false;
627 }
628 }
629