PluginProbe
Polylang / 2.8.1
Polylang v2.8.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 2.8.1, at admin/admin-filters-term.php

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