@@ -818,11 +818,15 @@ public function notices() {
818818 // If we have notices to display, we move forward.
819819 if ( ! empty ( $ message ) ) {
820820 krsort ( $ message ); // Sort messages.
821- $ rendered = '' ; // Display all nag messages as strings.
821+ $ rendered = '' ;
822+
823+ // As add_settings_error() wraps the final message in a <p> and as the final message can't be
824+ // filtered, using <p>'s in our html would render invalid html output.
825+ $ line_template = '<span style="display: block; margin: 0.5em 0.5em 0 0; clear: both;">%s</span> ' . "\n" ;
822826
823827 // If dismissable is false and a message is set, output it now.
824828 if ( ! $ this ->dismissable && ! empty ( $ this ->dismiss_msg ) ) {
825- $ rendered .= ' <p><strong> ' . wp_kses_post ( $ this ->dismiss_msg ) . ' </strong></p> ' ;
829+ $ rendered .= sprintf ( $ line_template , wp_kses_post ( $ this ->dismiss_msg ) ) ;
826830 }
827831
828832 // Grab all plugin names.
@@ -836,11 +840,19 @@ public function notices() {
836840 }
837841 unset( $ plugin_slug );
838842
839- $ count = count ( $ plugin_group );
840- $ last_plugin = array_pop ( $ linked_plugins ); // Pop off last name to prep for readability.
841- $ imploded = empty ( $ linked_plugins ) ? '<em> ' . $ last_plugin . '</em> ' : '<em> ' . ( implode ( ', ' , $ linked_plugins ) . '</em> ' . esc_html__ ( 'and ' , 'tgmpa ' ) . ' <em> ' . $ last_plugin . '</em> ' );
842-
843- $ rendered .= '<p> ' . sprintf ( translate_nooped_plural ( $ this ->strings [ $ type ], $ count , 'tgmpa ' ), $ imploded , $ count ) . '</p> ' ;
843+ $ count = count ( $ plugin_group );
844+ $ linked_plugins = array_map ( array ( 'TGM_Utils ' , 'wrap_in_em ' ), $ linked_plugins );
845+ $ last_plugin = array_pop ( $ linked_plugins ); // Pop off last name to prep for readability.
846+ $ imploded = empty ( $ linked_plugins ) ? $ last_plugin : ( implode ( ', ' , $ linked_plugins ) . ' ' . esc_html_x ( 'and ' , 'plugin A *and* plugin B ' , 'tgmpa ' ) . ' ' . $ last_plugin );
847+
848+ $ rendered .= sprintf (
849+ $ line_template ,
850+ sprintf (
851+ translate_nooped_plural ( $ this ->strings [ $ type ], $ count , 'tgmpa ' ),
852+ $ imploded ,
853+ $ count
854+ )
855+ );
844856 }
845857 unset( $ type , $ plugin_group , $ linked_plugins , $ count , $ last_plugin , $ imploded );
846858
@@ -860,7 +872,8 @@ public function notices() {
860872
861873 $ action_links = array_filter ( (array ) $ action_links ); // Remove any empty array items.
862874 if ( is_array ( $ action_links ) && ! empty ( $ action_links ) ) {
863- $ rendered .= apply_filters ( 'tgmpa_notice_rendered_action_links ' , '<p> ' . implode ( ' | ' , $ action_links ) . '</p> ' );
875+ $ action_links = sprintf ( $ line_template , implode ( ' | ' , $ action_links ) );
876+ $ rendered .= apply_filters ( 'tgmpa_notice_rendered_action_links ' , $ action_links );
864877 }
865878
866879 // Register the nag messages and prepare them to be processed.
@@ -1835,14 +1848,15 @@ public function process_bulk_actions() {
18351848 echo '<div id="message" class="error"><p> ' , wp_kses_post ( $ activate ->get_error_message () ), '</p></div> ' ;
18361849
18371850 } else {
1838- $ count = count ( $ plugin_names ); // Count so we can use _n function.
1839- $ last_plugin = array_pop ( $ plugin_names ); // Pop off last name to prep for readability.
1840- $ imploded = empty ( $ plugin_names ) ? '<strong> ' . $ last_plugin . '</strong> ' : '<strong> ' . ( implode ( ', ' , $ plugin_names ) . '</strong> ' . esc_html__ ( 'and ' , 'tgmpa ' ) . ' <strong> ' . $ last_plugin . '</strong>. ' );
1851+ $ count = count ( $ plugin_names ); // Count so we can use _n function.
1852+ $ plugin_names = array_map ( array ( 'TGM_Utils ' , 'wrap_in_strong ' ), $ plugin_names );
1853+ $ last_plugin = array_pop ( $ plugin_names ); // Pop off last name to prep for readability.
1854+ $ imploded = empty ( $ plugin_names ) ? $ last_plugin : ( implode ( ', ' , $ plugin_names ) . ' ' . esc_html_x ( 'and ' , 'plugin A *and* plugin B ' , 'tgmpa ' ) . ' ' . $ last_plugin );
18411855
18421856 printf (
18431857 '<div id="message" class="updated"><p>%1$s %2$s.</p></div> ' ,
18441858 esc_html ( _n ( 'The following plugin was activated successfully: ' , 'The following plugins were activated successfully: ' , $ count , 'tgmpa ' ) ),
1845- wp_kses_post ( $ imploded )
1859+ $ imploded // xss: ok
18461860 );
18471861
18481862 // Update recently activated plugins option.
@@ -2499,6 +2513,37 @@ class TGM_Utils {
24992513 */
25002514 public static $ has_filters ;
25012515
2516+
2517+ /**
2518+ * Wrap an arbitrary string in <em> tags. Meant to be used in combination with array_map().
2519+ *
2520+ * @since 2.5.0
2521+ *
2522+ * @static
2523+ *
2524+ * @param string $string
2525+ *
2526+ * @return string
2527+ */
2528+ public static function wrap_in_em ( $ string ) {
2529+ return '<em> ' . wp_kses_post ( $ string ) . '</em> ' ;
2530+ }
2531+
2532+ /**
2533+ * Wrap an arbitrary string in <strong> tags. Meant to be used in combination with array_map().
2534+ *
2535+ * @since 2.5.0
2536+ *
2537+ * @static
2538+ *
2539+ * @param string $string
2540+ *
2541+ * @return string
2542+ */
2543+ public static function wrap_in_strong ( $ string ) {
2544+ return '<strong> ' . wp_kses_post ( $ string ) . '</strong> ' ;
2545+ }
2546+
25022547 /**
25032548 * Helper function: Validate a value as boolean
25042549 *
0 commit comments