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

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