PluginProbe
Polylang / trunk
Polylang vtrunk
3.8.10 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 All 234 releases
← All changes | src/admin/admin-filters-columns.php +120 -32 3.8.4 → trunk View file →
@@ -84,9 +84,20 @@
84 84 $columns = array_slice( $columns, 0, $n );
85 85 }
86 86
87 87 foreach ( $this->model->get_languages_list() as $language ) {
88 - $columns[ 'language_' . $language->slug ] = $this->links->get_flag_html( $language ) . '<span class="screen-reader-text">' . esc_html( $language->name ) . '</span>';
88 + /*
89 + * Hack:
90 + * - `WP_Screen::render_list_table_columns_preferences()` applies `wp_strip_all_tags()` in the screen options:
91 + * this will remove the flag, and reveal the language name (that looses its `<span>`).
92 + * - `WP_List_Table::print_column_headers()` doesn't apply any escaping function in the column headers:
93 + * the flag will be displayed, and the language name will still be present but visually hidden.
94 + */
95 + $columns[ "language_{$language->slug}" ] = sprintf(
96 + '%s<span class="screen-reader-text">%s</span>',
97 + $language->get_admin_flag( 'aria-hidden' ),
98 + esc_html( $language->name )
99 + );
89 100 }
90 101
91 102 return isset( $end ) ? array_merge( $columns, $end ) : $columns;
92 103 }
@@ -335,35 +346,77 @@
335 346 if ( ! isset( $_POST['post_type'], $_POST['post_id'], $_POST['screen'] ) ) {
336 347 wp_die( 0 );
337 348 }
338 349
339 - $post_type = sanitize_key( $_POST['post_type'] );
350 + if ( ! is_numeric( $_POST['post_id'] ) ) {
351 + wp_die( 0 );
352 + }
340 353
341 - if ( ! post_type_exists( $post_type ) || ! $this->model->is_translated_post_type( $post_type ) ) {
354 + $post_type_object = get_post_type_object( sanitize_key( $_POST['post_type'] ) );
355 +
356 + if ( empty( $post_type_object ) || ! $this->model->is_translated_post_type( $post_type_object->name ) ) {
342 357 wp_die( 0 );
343 358 }
344 359
345 - /** @var WP_Posts_List_Table $wp_list_table */
346 360 $wp_list_table = _get_list_table( 'WP_Posts_List_Table', array( 'screen' => sanitize_key( $_POST['screen'] ) ) );
347 361
348 - $x = new WP_Ajax_Response();
362 + if ( empty( $wp_list_table ) ) {
363 + wp_die( 0 );
364 + }
349 365
366 + $response = new WP_Ajax_Response();
367 +
350 368 // Collect old translations.
351 - $translations = empty( $_POST['translations'] ) ? array() : explode( ',', $_POST['translations'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
352 - $translations = array_map( 'intval', $translations );
353 - $translations = array_merge( $translations, array( (int) $_POST['post_id'] ) ); // Add current post
369 + if ( ! empty( $_POST['translations'] ) && is_string( $_POST['translations'] ) ) {
370 + $translations = explode( ',', $_POST['translations'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
371 + $translations = array_filter( $translations, 'is_numeric' );
372 + $translations = array_map( 'intval', $translations );
373 + $translations = array_filter( $translations );
374 + } else {
375 + $translations = array();
376 + }
354 377
355 - foreach ( $translations as $post_id ) {
356 - $level = is_post_type_hierarchical( $post_type ) ? count( get_ancestors( $post_id, $post_type ) ) : 0;
357 - if ( $post = get_post( $post_id ) ) {
358 - ob_start();
359 - $wp_list_table->single_row( $post, $level );
360 - $data = (string) ob_get_clean();
361 - $x->add( array( 'what' => 'row', 'data' => $data, 'supplemental' => array( 'post_id' => $post_id ) ) );
378 + $translations = array_merge( $translations, $this->model->post->get_translations( (int) $_POST['post_id'] ) );
379 + $translations = array_unique( $translations );
380 +
381 + if ( empty( $translations ) ) { // May occur if the modified post has no language.
382 + $response->send();
383 + }
384 +
385 + /** @var WP_Post[] */
386 + $posts = ( new WP_Query() )->query(
387 + array(
388 + // Do not add `post_status`, as this allows `WP_Query` to handle user capabilities to read private posts.
389 + 'post__in' => $translations,
390 + 'post_type' => $post_type_object->name,
391 + 'posts_per_page' => count( $translations ),
392 + 'no_found_rows' => true,
393 + 'orderby' => 'ID',
394 + 'lang' => '',
395 + )
396 + );
397 +
398 + foreach ( $posts as $post ) {
399 + if ( $post_type_object->hierarchical ) {
400 + $level = count( get_ancestors( $post->ID, $post->post_type, 'post_type' ) );
401 + } else {
402 + $level = 0;
362 403 }
404 +
405 + ob_start();
406 + $wp_list_table->single_row( $post, $level );
407 + $data = (string) ob_get_clean();
408 +
409 + $response->add(
410 + array(
411 + 'what' => 'row',
412 + 'data' => $data,
413 + 'supplemental' => array( 'post_id' => $post->ID ),
414 + )
415 + );
363 416 }
364 417
365 - $x->send();
418 + $response->send();
366 419 }
367 420
368 421 /**
369 422 * Update rows of translated terms when adding / deleting a translation
@@ -381,38 +434,73 @@
381 434 if ( ! isset( $_POST['taxonomy'], $_POST['term_id'], $_POST['screen'] ) ) {
382 435 wp_die( 0 );
383 436 }
384 437
385 - $taxonomy = sanitize_key( $_POST['taxonomy'] );
438 + if ( ! is_numeric( $_POST['term_id'] ) ) {
439 + wp_die( 0 );
440 + }
386 441
387 - if ( ! taxonomy_exists( $taxonomy ) || ! $this->model->is_translated_taxonomy( $taxonomy ) ) {
442 + $taxonomy_object = get_taxonomy( sanitize_key( $_POST['taxonomy'] ) );
443 +
444 + if ( empty( $taxonomy_object ) || ! $this->model->is_translated_taxonomy( $taxonomy_object->name ) ) {
388 445 wp_die( 0 );
389 446 }
390 447
391 - /** @var WP_Terms_List_Table $wp_list_table */
392 448 $wp_list_table = _get_list_table( 'WP_Terms_List_Table', array( 'screen' => sanitize_key( $_POST['screen'] ) ) );
393 449
394 - $x = new WP_Ajax_Response();
450 + if ( empty( $wp_list_table ) ) {
451 + wp_die( 0 );
452 + }
395 453
454 + $response = new WP_Ajax_Response();
455 +
396 456 // Collect old translations.
397 - $translations = empty( $_POST['translations'] ) ? array() : explode( ',', $_POST['translations'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
398 - $translations = array_map( 'intval', $translations );
399 - $translations = array_merge( $translations, $this->model->term->get_translations( (int) $_POST['term_id'] ) ); // Add current translations.
400 - $translations = array_unique( $translations ); // Remove duplicates.
457 + if ( ! empty( $_POST['translations'] ) && is_string( $_POST['translations'] ) ) {
458 + $translations = explode( ',', $_POST['translations'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
459 + $translations = array_filter( $translations, 'is_numeric' );
460 + $translations = array_map( 'intval', $translations );
461 + $translations = array_filter( $translations );
462 + } else {
463 + $translations = array();
464 + }
401 465
402 - foreach ( $translations as $term_id ) {
403 - $level = is_taxonomy_hierarchical( $taxonomy ) ? count( get_ancestors( $term_id, $taxonomy ) ) : 0;
404 - $tag = get_term( $term_id, $taxonomy );
466 + $translations = array_merge( $translations, $this->model->term->get_translations( (int) $_POST['term_id'] ) );
467 + $translations = array_unique( $translations );
405 468
406 - if ( ! $tag instanceof WP_Term ) {
407 - continue;
469 + if ( empty( $translations ) ) { // May occur if the modified term has no language.
470 + $response->send();
471 + }
472 +
473 + /** @var WP_Term[] */
474 + $terms = ( new WP_Term_Query() )->query(
475 + array(
476 + 'include' => $translations,
477 + 'taxonomy' => $taxonomy_object->name,
478 + 'hide_empty' => false,
479 + 'orderby' => 'term_id',
480 + 'lang' => '',
481 + )
482 + );
483 +
484 + foreach ( $terms as $term ) {
485 + if ( $taxonomy_object->hierarchical ) {
486 + $level = count( get_ancestors( $term->term_id, $taxonomy_object->name, 'taxonomy' ) );
487 + } else {
488 + $level = 0;
408 489 }
409 490
410 491 ob_start();
411 - $wp_list_table->single_row( $tag, $level );
492 + $wp_list_table->single_row( $term, $level );
412 493 $data = (string) ob_get_clean();
413 - $x->add( array( 'what' => 'row', 'data' => $data, 'supplemental' => array( 'term_id' => $term_id ) ) );
494 +
495 + $response->add(
496 + array(
497 + 'what' => 'row',
498 + 'data' => $data,
499 + 'supplemental' => array( 'term_id' => $term->term_id ),
500 + )
501 + );
414 502 }
415 503
416 - $x->send();
504 + $response->send();
417 505 }
418 506 }