PluginProbe
Polylang / trunk
Polylang vtrunk
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 / src / admin / admin-filters-term.php

admin-filters-term.php in Polylang trunk, at src/admin/admin-filters-term.php

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