| @@ -65,9 +65,9 @@ | ||
| 65 | 65 | if ( $comment ) { |
| 66 | 66 | $identity = array( |
| 67 | 67 | 'type' => 'comment', |
| 68 | 68 | 'id' => (int) $comment->comment_ID, |
| 69 | - 'label' => wp_trim_words( $comment->comment_content, 10 ), | |
| 69 | + 'label' => wp_trim_words( openstation_strip_all_tags( $comment->comment_content ), 10 ), | |
| 70 | 70 | ); |
| 71 | 71 | |
| 72 | 72 | $post_id = (int) $comment->comment_post_ID; |
| 73 | 73 | $post_type = $post_id ? get_post_type( $post_id ) : false; |
| @@ -433,9 +433,12 @@ | ||
| 433 | 433 | /** |
| 434 | 434 | * The related-entity pass: attach the `related` navigation items to a |
| 435 | 435 | * (post-identity-filter) content identity. Shared by the page-render |
| 436 | 436 | * builder above and the REST recompute endpoint the editor |
| 437 | - * save-watcher hits (where `$screen` is `null`). | |
| 437 | + * save-watcher hits (where `$screen` is `null`). Also where the labels | |
| 438 | + * become plain text: they name windows (Preview, Revisions, Related) | |
| 439 | + * and are painted as text, where `get_the_title()`'s entities | |
| 440 | + * (`’`) read literally. | |
| 438 | 441 | * |
| 439 | 442 | * @internal |
| 440 | 443 | * |
| 441 | 444 | * @param array|null $identity Filtered identity, or `null`. |
| @@ -448,8 +451,11 @@ | ||
| 448 | 451 | function openstation_window_related_attach( $identity, $post, $screen ) { |
| 449 | 452 | if ( ! is_array( $identity ) ) { |
| 450 | 453 | return $identity; |
| 451 | 454 | } |
| 455 | + if ( isset( $identity['label'] ) && is_string( $identity['label'] ) ) { | |
| 456 | + $identity['label'] = openstation_plain_text_title( $identity['label'] ); | |
| 457 | + } | |
| 452 | 458 | |
| 453 | 459 | $related = array(); |
| 454 | 460 | if ( |
| 455 | 461 | $post instanceof WP_Post && |
| @@ -813,8 +819,16 @@ | ||
| 813 | 819 | $out = array(); |
| 814 | 820 | foreach ( $related as $item ) { |
| 815 | 821 | if ( ! is_array( $item ) ) { |
| 816 | 822 | continue; |
| 823 | + } | |
| 824 | + // Plain text (see `openstation_window_related_attach()`), | |
| 825 | + // decoded before the checks below so a label that was only | |
| 826 | + // markup is dropped here rather than failing the whole ref. | |
| 827 | + foreach ( array( 'label', 'groupLabel' ) as $text ) { | |
| 828 | + if ( isset( $item[ $text ] ) && is_string( $item[ $text ] ) ) { | |
| 829 | + $item[ $text ] = openstation_plain_text_title( $item[ $text ] ); | |
| 830 | + } | |
| 817 | 831 | } |
| 818 | 832 | foreach ( array( 'id', 'group', 'label', 'url' ) as $required ) { |
| 819 | 833 | // Mirror the JS engine's validation exactly (`.trim() !== ''`): |
| 820 | 834 | // a whitespace-only value passing here would fail validateRef |