PluginProbe
Polylang / 3.1.1
Polylang v3.1.1
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 3.1.1, at admin/admin-filters-term.php

665 lines 20.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Polylang
4 */
5
6 /**
7 * Manages filters and actions related to terms on admin side
8 *
9 * @since 1.2
10 */
11 class PLL_Admin_Filters_Term {
12 /**
13 * Stores the plugin options.
14 *
15 * @var array
16 */
17 public $options;
18
19 /**
20 * @var PLL_Model
21 */
22 public $model;
23
24 /**
25 * @var PLL_Admin_Links
26 */
27 public $links;
28
29 /**
30 * Language selected in the admin language filter.
31 *
32 * @var PLL_Language
33 */
34 public $filter_lang;
35
36 /**
37 * Preferred language to assign to the new terms.
38 *
39 * @var PLL_Language
40 */
41 public $pref_lang;
42
43 /**
44 * Stores the term name before creating a slug if needed.
45 *
46 * @var string
47 */
48 protected $pre_term_name;
49
50 /**
51 * Stores the current post_id when bulk editing posts.
52 *
53 * @var int
54 */
55 protected $post_id;
56
57 /**
58 * A reference to the PLL_Admin_Default_Term instance.
59 *
60 * @since 2.8
61 *
62 * @var PLL_Admin_Default_Term
63 */
64 protected $default_term;
65
66 /**
67 * Constructor: setups filters and actions
68 *
69 * @param object $polylang
70 */
71 public function __construct( &$polylang ) {
72 $this->links = &$polylang->links;
73 $this->model = &$polylang->model;
74 $this->options = &$polylang->options;
75 $this->pref_lang = &$polylang->pref_lang;
76 $this->default_term = &$polylang->default_term;
77
78 foreach ( $this->model->get_translated_taxonomies() as $tax ) {
79 // Adds the language field in the 'Categories' and 'Post Tags' panels
80 add_action( $tax . '_add_form_fields', array( $this, 'add_term_form' ) );
81
82 // Adds the language field and translations tables in the 'Edit Category' and 'Edit Tag' panels
83 add_action( $tax . '_edit_form_fields', array( $this, 'edit_term_form' ) );
84 }
85
86 // Adds actions related to languages when creating or saving categories and post tags
87 add_filter( 'wp_dropdown_cats', array( $this, 'wp_dropdown_cats' ) );
88 add_action( 'create_term', array( $this, 'save_term' ), 900, 3 );
89 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
90 add_action( 'pre_post_update', array( $this, 'pre_post_update' ) );
91 add_filter( 'pre_term_name', array( $this, 'pre_term_name' ) );
92 add_filter( 'pre_term_slug', array( $this, 'pre_term_slug' ), 10, 2 );
93
94 // Ajax response for edit term form
95 add_action( 'wp_ajax_term_lang_choice', array( $this, 'term_lang_choice' ) );
96 add_action( 'wp_ajax_pll_terms_not_translated', array( $this, 'ajax_terms_not_translated' ) );
97
98 // Updates the translations term ids when splitting a shared term
99 add_action( 'split_shared_term', array( $this, 'split_shared_term' ), 10, 4 ); // WP 4.2
100 }
101
102 /**
103 * Adds the language field in the 'Categories' and 'Post Tags' panels
104 *
105 * @since 0.1
106 *
107 * @return void
108 */
109 public function add_term_form() {
110 if ( isset( $_GET['taxonomy'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
111 $taxonomy = sanitize_key( $_GET['taxonomy'] ); // phpcs:ignore WordPress.Security.NonceVerification
112 }
113
114 if ( isset( $_REQUEST['post_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
115 $post_type = sanitize_key( $_REQUEST['post_type'] ); // phpcs:ignore WordPress.Security.NonceVerification
116 }
117
118 if ( isset( $GLOBALS['post_type'] ) ) {
119 $post_type = $GLOBALS['post_type'];
120 }
121
122 if ( ! isset( $taxonomy, $post_type ) || ! taxonomy_exists( $taxonomy ) || ! post_type_exists( $post_type ) ) {
123 return;
124 }
125
126 $from_term_id = isset( $_GET['from_tag'] ) ? (int) $_GET['from_tag'] : 0; // phpcs:ignore WordPress.Security.NonceVerification
127
128 $lang = isset( $_GET['new_lang'] ) ? $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ) : $this->pref_lang; // phpcs:ignore WordPress.Security.NonceVerification
129
130 $dropdown = new PLL_Walker_Dropdown();
131
132 $dropdown_html = $dropdown->walk(
133 $this->model->get_languages_list(),
134 -1,
135 array(
136 'name' => 'term_lang_choice',
137 'value' => 'term_id',
138 'selected' => $lang ? $lang->term_id : '',
139 'flag' => true,
140 )
141 );
142
143 wp_nonce_field( 'pll_language', '_pll_nonce' );
144
145 printf(
146 '<div class="form-field">
147 <label for="term_lang_choice">%s</label>
148 <div id="select-add-term-language">%s</div>
149 <p>%s</p>
150 </div>',
151 esc_html__( 'Language', 'polylang' ),
152 $dropdown_html, // phpcs:ignore
153 esc_html__( 'Sets the language', 'polylang' )
154 );
155
156 if ( ! empty( $from_term_id ) ) {
157 printf( '<input type="hidden" name="from_tag" value="%d" />', (int) $from_term_id );
158 }
159
160 // Adds translation fields
161 echo '<div id="term-translations" class="form-field">';
162 if ( $lang ) {
163 include __DIR__ . '/view-translations-term.php';
164 }
165 echo '</div>' . "\n";
166 }
167
168 /**
169 * Adds the language field and translations tables in the 'Edit Category' and 'Edit Tag' panels.
170 *
171 * @since 0.1
172 *
173 * @param WP_Term $tag The term being edited.
174 * @return void
175 */
176 public function edit_term_form( $tag ) {
177 if ( isset( $_REQUEST['post_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
178 $post_type = sanitize_key( $_REQUEST['post_type'] ); // phpcs:ignore WordPress.Security.NonceVerification
179 }
180
181 if ( isset( $GLOBALS['post_type'] ) ) {
182 $post_type = $GLOBALS['post_type'];
183 }
184
185 if ( ! isset( $post_type ) || ! post_type_exists( $post_type ) ) {
186 return;
187 }
188
189 $term_id = $tag->term_id;
190 $taxonomy = $tag->taxonomy; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
191
192 $lang = $this->model->term->get_language( $term_id );
193 $lang = empty( $lang ) ? $this->pref_lang : $lang;
194
195 // Disable the language dropdown and the translations input fields for default terms to prevent removal
196 $disabled = $this->default_term->is_default_term( $term_id );
197
198 $dropdown = new PLL_Walker_Dropdown();
199
200 $dropdown_html = $dropdown->walk(
201 $this->model->get_languages_list(),
202 -1,
203 array(
204 'name' => 'term_lang_choice',
205 'value' => 'term_id',
206 'selected' => $lang->term_id,
207 'disabled' => $disabled,
208 'flag' => true,
209 )
210 );
211
212 wp_nonce_field( 'pll_language', '_pll_nonce' );
213
214 printf(
215 '<tr class="form-field">
216 <th scope="row">
217 <label for="term_lang_choice">%s</label>
218 </th>
219 <td id="select-edit-term-language">
220 %s<br />
221 <p class="description">%s</p>
222 </td>
223 </tr>',
224 esc_html__( 'Language', 'polylang' ),
225 $dropdown_html, // phpcs:ignore
226 esc_html__( 'Sets the language', 'polylang' )
227 );
228
229 echo '<tr id="term-translations" class="form-field">';
230 include __DIR__ . '/view-translations-term.php';
231 echo '</tr>' . "\n";
232 }
233
234 /**
235 * Translates term parent if exists when using "Add new" ( translation )
236 *
237 * @since 0.7
238 *
239 * @param string $output html markup for dropdown list of categories
240 * @return string modified html
241 */
242 public function wp_dropdown_cats( $output ) {
243 if ( isset( $_GET['taxonomy'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
244 $taxonomy = sanitize_key( $_GET['taxonomy'] ); // phpcs:ignore WordPress.Security.NonceVerification
245 }
246
247 if ( isset( $taxonomy, $_GET['from_tag'], $_GET['new_lang'] ) && taxonomy_exists( $taxonomy ) ) { // phpcs:ignore WordPress.Security.NonceVerification
248 $term = get_term( (int) $_GET['from_tag'], $taxonomy ); // phpcs:ignore WordPress.Security.NonceVerification
249
250 if ( $term instanceof WP_Term && $id = $term->parent ) {
251 $lang = $this->model->get_language( sanitize_key( $_GET['new_lang'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
252 if ( $parent = $this->model->term->get_translation( $id, $lang ) ) {
253 return str_replace( '"' . $parent . '"', '"' . $parent . '" selected="selected"', $output );
254 }
255 }
256 }
257 return $output;
258 }
259
260 /**
261 * Stores the current post_id when bulk editing posts for use in save_language and pre_term_slug
262 *
263 * @since 1.7
264 *
265 * @param int $post_id
266 * @return void
267 */
268 public function pre_post_update( $post_id ) {
269 if ( isset( $_GET['bulk_edit'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
270 $this->post_id = $post_id;
271 }
272 }
273
274 /**
275 * Saves language
276 *
277 * @since 1.5
278 *
279 * @param int $term_id
280 * @param string $taxonomy
281 * @return void
282 */
283 protected function save_language( $term_id, $taxonomy ) {
284 global $wpdb;
285 // Security checks are necessary to accept language modifications
286 // as 'wp_update_term' can be called from outside WP admin
287
288 // Edit tags
289 if ( isset( $_POST['term_lang_choice'] ) ) {
290 if ( isset( $_POST['action'] ) && sanitize_key( $_POST['action'] ) === 'add-' . $taxonomy ) { // phpcs:ignore WordPress.Security.NonceVerification
291 check_ajax_referer( 'add-' . $taxonomy, '_ajax_nonce-add-' . $taxonomy ); // Category metabox
292 } else {
293 check_admin_referer( 'pll_language', '_pll_nonce' ); // Edit tags or tags metabox
294 }
295
296 $this->model->term->set_language( $term_id, $this->model->get_language( sanitize_key( $_POST['term_lang_choice'] ) ) );
297 }
298
299 // *Post* bulk edit, in case a new term is created
300 elseif ( isset( $_GET['bulk_edit'], $_GET['inline_lang_choice'] ) ) {
301 check_admin_referer( 'bulk-posts' );
302
303 // Bulk edit does not modify the language
304 // So we possibly create a tag in several languages
305 if ( -1 == $_GET['inline_lang_choice'] ) {
306 // The language of the current term is set a according to the language of the current post
307 $this->model->term->set_language( $term_id, $this->model->post->get_language( $this->post_id ) );
308 $term = get_term( $term_id, $taxonomy );
309
310 // Get all terms with the same name
311 // FIXME backward compatibility WP < 4.2
312 // No WP function to get all terms with the exact same name so let's use a custom query
313 // $terms = get_terms( $taxonomy, array( 'name' => $term->name, 'hide_empty' => false, 'fields' => 'ids' ) ); should be OK in 4.2
314 // I may need to rework the loop below
315 $terms = $wpdb->get_results(
316 $wpdb->prepare(
317 "SELECT t.term_id FROM $wpdb->terms AS t
318 INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id
319 WHERE tt.taxonomy = %s AND t.name = %s",
320 $taxonomy,
321 $term->name
322 )
323 );
324
325 // If we have several terms with the same name, they are translations of each other
326 if ( count( $terms ) > 1 ) {
327 $translations = array();
328
329 foreach ( $terms as $term ) {
330 $translations[ $this->model->term->get_language( $term->term_id )->slug ] = $term->term_id;
331 }
332
333 $this->model->term->save_translations( $term_id, $translations );
334 }
335 }
336
337 else {
338 if ( current_user_can( 'edit_term', $term_id ) ) {
339 $this->model->term->set_language( $term_id, $this->model->get_language( sanitize_key( $_GET['inline_lang_choice'] ) ) );
340 }
341 }
342 }
343
344 // Quick edit
345 elseif ( isset( $_POST['inline_lang_choice'] ) ) {
346 check_ajax_referer(
347 isset( $_POST['action'] ) && 'inline-save' == $_POST['action'] ? 'inlineeditnonce' : 'taxinlineeditnonce', // Post quick edit or tag quick edit ?
348 '_inline_edit'
349 );
350
351 $lang = $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) );
352 $this->model->term->update_language( $term_id, $lang );
353 }
354
355 // Edit post
356 elseif ( isset( $_POST['post_lang_choice'] ) ) { // FIXME should be useless now
357 check_admin_referer( 'pll_language', '_pll_nonce' );
358 $this->model->term->set_language( $term_id, $this->model->get_language( sanitize_key( $_POST['post_lang_choice'] ) ) );
359 }
360 }
361
362 /**
363 * Save translations from our form.
364 *
365 * @since 1.5
366 *
367 * @param int $term_id The term id of teh term being saved.
368 * @return int[] The array of translated term ids.
369 */
370 protected function save_translations( $term_id ) {
371 // Security check as 'wp_update_term' can be called from outside WP admin.
372 check_admin_referer( 'pll_language', '_pll_nonce' );
373
374 $translations = array();
375
376 // Save translations after checking the translated term is in the right language ( as well as cast id to int ).
377 if ( isset( $_POST['term_tr_lang'] ) ) {
378 foreach ( array_map( 'absint', $_POST['term_tr_lang'] ) as $lang => $tr_id ) {
379 $tr_lang = $this->model->term->get_language( $tr_id );
380 $translations[ $lang ] = $tr_lang && $tr_lang->slug == $lang ? $tr_id : 0;
381 }
382 }
383
384 $this->model->term->save_translations( $term_id, $translations );
385
386 return $translations;
387 }
388
389 /**
390 * Called when a category or post tag is created or edited
391 * Saves language and translations
392 *
393 * @since 0.1
394 *
395 * @param int $term_id
396 * @param int $tt_id term taxonomy id
397 * @param string $taxonomy
398 * @return void
399 */
400 public function save_term( $term_id, $tt_id, $taxonomy ) {
401 // Does nothing except on taxonomies which are filterable
402 if ( ! $this->model->is_translated_taxonomy( $taxonomy ) ) {
403 return;
404 }
405
406 $tax = get_taxonomy( $taxonomy );
407
408 if ( empty( $tax ) ) {
409 return;
410 }
411
412 // Capability check
413 // As 'wp_update_term' can be called from outside WP admin
414 // 2nd test for creating tags when creating / editing a post
415 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
416 $this->save_language( $term_id, $taxonomy );
417
418 if ( isset( $_POST['term_tr_lang'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
419 $this->save_translations( $term_id );
420 }
421 }
422 }
423
424 /**
425 * Stores the term name for use in pre_term_slug
426 *
427 * @since 0.9.5
428 *
429 * @param string $name term name
430 * @return string unmodified term name
431 */
432 public function pre_term_name( $name ) {
433 return $this->pre_term_name = $name;
434 }
435
436 /**
437 * Creates the term slug in case the term already exists in another language
438 *
439 * @since 0.9.5
440 *
441 * @param string $slug
442 * @param string $taxonomy
443 * @return string
444 */
445 public function pre_term_slug( $slug, $taxonomy ) {
446 $name = sanitize_title( $this->pre_term_name );
447
448 // If the term already exists in another language
449 if ( ! $slug && $this->model->is_translated_taxonomy( $taxonomy ) && term_exists( $name, $taxonomy ) ) {
450 if ( isset( $_POST['term_lang_choice'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
451 $lang = $this->model->get_language( sanitize_key( $_POST['term_lang_choice'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
452 }
453
454 elseif ( isset( $_POST['inline_lang_choice'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
455 $lang = $this->model->get_language( sanitize_key( $_POST['inline_lang_choice'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
456 }
457
458 // *Post* bulk edit, in case a new term is created
459 elseif ( isset( $_GET['bulk_edit'], $_GET['inline_lang_choice'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
460 // Bulk edit does not modify the language
461 if ( -1 == $_GET['inline_lang_choice'] ) { // phpcs:ignore WordPress.Security.NonceVerification
462 $lang = $this->model->post->get_language( $this->post_id );
463 } else {
464 $lang = $this->model->get_language( sanitize_key( $_GET['inline_lang_choice'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
465 }
466 }
467
468 if ( ! empty( $lang ) && ! $this->model->term_exists_by_slug( $name, $lang, $taxonomy ) ) {
469 $slug = $name . '-' . $lang->slug;
470 }
471 }
472
473 return $slug;
474 }
475
476 /**
477 * Ajax response for edit term form
478 *
479 * @since 0.2
480 *
481 * @return void
482 */
483 public function term_lang_choice() {
484 check_ajax_referer( 'pll_language', '_pll_nonce' );
485
486 if ( ! isset( $_POST['taxonomy'], $_POST['post_type'], $_POST['lang'] ) ) {
487 wp_die( 0 );
488 }
489
490 $lang = $this->model->get_language( sanitize_key( $_POST['lang'] ) );
491 $term_id = isset( $_POST['term_id'] ) ? (int) $_POST['term_id'] : null; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
492 $taxonomy = sanitize_key( $_POST['taxonomy'] );
493 $post_type = sanitize_key( $_POST['post_type'] );
494
495 if ( empty( $lang ) || ! post_type_exists( $post_type ) || ! taxonomy_exists( $taxonomy ) ) {
496 wp_die( 0 );
497 }
498
499 ob_start();
500 include __DIR__ . '/view-translations-term.php';
501 $x = new WP_Ajax_Response( array( 'what' => 'translations', 'data' => ob_get_contents() ) );
502 ob_end_clean();
503
504 // Parent dropdown list ( only for hierarchical taxonomies )
505 // $args copied from edit_tags.php except echo
506 if ( is_taxonomy_hierarchical( $taxonomy ) ) {
507 $args = array(
508 'hide_empty' => 0,
509 'hide_if_empty' => false,
510 'taxonomy' => $taxonomy,
511 'name' => 'parent',
512 'orderby' => 'name',
513 'hierarchical' => true,
514 'show_option_none' => __( 'None', 'polylang' ),
515 'echo' => 0,
516 );
517 $x->Add( array( 'what' => 'parent', 'data' => wp_dropdown_categories( $args ) ) );
518 }
519
520 // Tag cloud
521 // Tests copied from edit_tags.php
522 else {
523 $tax = get_taxonomy( $taxonomy );
524 if ( ! empty( $tax ) && ! is_null( $tax->labels->popular_items ) ) {
525 $args = array( 'taxonomy' => $taxonomy, 'echo' => false );
526 if ( current_user_can( $tax->cap->edit_terms ) ) {
527 $args = array_merge( $args, array( 'link' => 'edit' ) );
528 }
529
530 if ( $tag_cloud = wp_tag_cloud( $args ) ) {
531 $html = sprintf( '<div class="tagcloud"><h2>%1$s</h2>%2$s</div>', esc_html( $tax->labels->popular_items ), $tag_cloud );
532 $x->Add( array( 'what' => 'tag_cloud', 'data' => $html ) );
533 }
534 }
535 }
536
537 // Flag
538 $x->Add( array( 'what' => 'flag', 'data' => empty( $lang->flag ) ? esc_html( $lang->slug ) : $lang->flag ) );
539
540 $x->send();
541 }
542
543 /**
544 * Ajax response for input in translation autocomplete input box
545 *
546 * @since 1.5
547 *
548 * @return void
549 */
550 public function ajax_terms_not_translated() {
551 check_ajax_referer( 'pll_language', '_pll_nonce' );
552
553 if ( ! isset( $_GET['term'], $_GET['post_type'], $_GET['taxonomy'], $_GET['term_language'], $_GET['translation_language'] ) ) {
554 wp_die( 0 );
555 }
556
557 /** @var string */
558 $s = wp_unslash( $_GET['term'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
559 $post_type = sanitize_key( $_GET['post_type'] );
560 $taxonomy = sanitize_key( $_GET['taxonomy'] );
561
562 if ( ! post_type_exists( $post_type ) || ! taxonomy_exists( $taxonomy ) ) {
563 wp_die( 0 );
564 }
565
566 $term_language = $this->model->get_language( sanitize_key( $_GET['term_language'] ) );
567 $translation_language = $this->model->get_language( sanitize_key( $_GET['translation_language'] ) );
568
569 $terms = array();
570 $return = array();
571
572 // Add current translation in list.
573 // Not in add term as term_id is not set.
574 if ( isset( $_GET['term_id'] ) && 'undefined' !== $_GET['term_id'] && $term_id = $this->model->term->get_translation( (int) $_GET['term_id'], $translation_language ) ) {
575 $terms = array( get_term( $term_id, $taxonomy ) );
576 }
577
578 // It is more efficient to use one common query for all languages as soon as there are more than 2.
579 $all_terms = get_terms( $taxonomy, 'hide_empty=0&lang=0&name__like=' . $s );
580 if ( is_array( $all_terms ) ) {
581 foreach ( $all_terms as $term ) {
582 $lang = $this->model->term->get_language( $term->term_id );
583
584 if ( $lang && $lang->slug == $translation_language->slug && ! $this->model->term->get_translation( $term->term_id, $term_language ) ) {
585 $terms[] = $term;
586 }
587 }
588 }
589
590 // Format the ajax response.
591 foreach ( $terms as $term ) {
592 if ( $term instanceof WP_Term ) {
593 $return[] = array(
594 'id' => $term->term_id,
595 'value' => rtrim( // Trim the seperator added at the end by WP.
596 get_term_parents_list(
597 $term->term_id,
598 $term->taxonomy,
599 array(
600 'separator' => ' > ',
601 'link' => false,
602 )
603 ),
604 ' >'
605 ),
606 'link' => $this->links->edit_term_translation_link( $term->term_id, $term->taxonomy, $post_type ),
607 );
608 }
609 }
610
611 wp_die( wp_json_encode( $return ) );
612 }
613
614 /**
615 * Updates the translations term ids when splitting a shared term
616 * Splits translations if these are shared terms too
617 *
618 * @since 1.7
619 *
620 * @param int $term_id Shared term_id
621 * @param int $new_term_id
622 * @param int $term_taxonomy_id
623 * @param string $taxonomy
624 * @return void
625 */
626 public function split_shared_term( $term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
627 if ( ! $this->model->is_translated_taxonomy( $taxonomy ) ) {
628 return;
629 }
630
631 // Avoid recursion
632 static $avoid_recursion = false;
633 if ( $avoid_recursion ) {
634 return;
635 }
636
637 $lang = $this->model->term->get_language( $term_id );
638 if ( empty( $lang ) ) {
639 return;
640 }
641
642 $avoid_recursion = true;
643 $translations = array();
644
645 foreach ( $this->model->term->get_translations( $term_id ) as $key => $tr_id ) {
646 if ( $lang->slug == $key ) {
647 $translations[ $key ] = $new_term_id;
648 }
649 else {
650 $tr_term = get_term( $tr_id, $taxonomy );
651 $translations[ $key ] = _split_shared_term( $tr_id, $tr_term->term_taxonomy_id );
652
653 // Hack translation ids sent by the form to avoid overwrite in PLL_Admin_Filters_Term::save_translations
654 if ( isset( $_POST['term_tr_lang'][ $key ] ) && $_POST['term_tr_lang'][ $key ] == $tr_id ) { // phpcs:ignore WordPress.Security.NonceVerification
655 $_POST['term_tr_lang'][ $key ] = $translations[ $key ];
656 }
657 }
658 $this->model->term->set_language( $translations[ $key ], $key );
659 }
660
661 $this->model->term->save_translations( $new_term_id, $translations );
662 $avoid_recursion = false;
663 }
664 }
665