Closed E-VANCE closed 1 year ago
Hi @E-VANCE,
Could you please explain in more detail how exactly you're using this class to generate this <picture>
tag and how you're adding it to wpp_get_mostpopular()
so I can reproduce the issue you're describing?
Hi @cabrerahector,
sure thing – this is the relevant part in the filter markup:
if(has_post_thumbnail($post->id)) {
if($i > 2) {
$output .= '<div class="thumb lg:flex-shrink-0 lg:mr-4">' . ResponsivePics::get_picture(get_post_thumbnail_id($post->id), "xs:640 360|f, md:240 180|f, lg:100 100|f", "swiper-lazy", true);
$output .= '<div class="swiper-lazy-preloader"></div></div>';
} else {
$output .= '<div class="thumb lg:flex-shrink-0 lg:mr-4">' . ResponsivePics::get_picture(get_post_thumbnail_id($post->id), "xs:640 360|f, md:240 180|f, lg:100 100|f") . '</div>';
}
}
You can see the whole widget in action here: https://profashionals.de/ (= the "Meistgelesen"-widget in the sidebar).
Just wondering what has changed since v5.3.5
to this regard and how I can "protect" the <picture>
-tags from being re-written... Thought about obfuscating / encoding the relevant parts but that seems like the wrong approach 😄
I was hoping to see more of a "copy & paste" thing so I don't need to write code to reproduce the issue 😅 (and I'm pretty sure the issue template includes a "Steps to reproduce" section precisely for this.)
Anyways, I'll try using your code and get back to you as soon as I can.
@cabrerahector
OK, no worries – didn't know what you were aiming for... Steps for reproducing this:
/**
* Alter 'WordPress Popular Posts' HTML output
*
* @param array $popular_posts
* @param array $instance
* @return string
*/
function custom_popular_posts_html($popular_posts, $instance) {
$output = '<div class="wrapper">';
// Loop over the array of popular posts objects
foreach($popular_posts as $post) {
$output = '<div class="item">';
// Image
if(has_post_thumbnail($post->id)) {
$image = ResponsivePics::get_picture(get_post_thumbnail_id($post->id), '0:150 150|f');
var_dump($image); // Debug
$output .= '<div class="thumb">';
$output .= $image;
$output .= '</div>';
}
$output .= '<div class="title">' . $post->title . '</div>';
$output .= '</div>';
}
$output .= '</div>';
return $output;
}
add_filter('wpp_custom_html', 'custom_popular_posts_html', 10, 2);
Haven't tested this but should be fairly straight forward.
Alright, so the reason why <picture>
tags are being stripped out of the HTML output is due to the usage of wp_kses_allowed_html(). This is a core WordPress function that basically provides a list of "allowed" HTML tags, that is HTML tags -and attributes- that are considered to be safe to use (as in that are unlikely to be exploited by malicious users).
To improve security when using the [wpp]
shortcode (the wpp_get_mostpopular()
function is actually a wrapper that uses this shortcode internally to render posts outside post/page content), and as you may have already guessed by now, WordPress Popular Posts started using this function since version 5.3.6. And so it happens that wp_kses_allowed_html()
doesn't include <picture>
nor <source>
in the list of "allowed" tags. Now you know why this is happening :P
Fortunately, wp_kses_allowed_html()
does include filter hooks so you can modify the list of allowed HTML tags. To save you some time, this is what you want:
/**
* Modifies wp_kses_allowed_html() to allow the usage of picture tags.
*
* @see https://developer.wordpress.org/reference/functions/wp_kses_allowed_html/
*
* @author Hector Cabrera
* @param array $allowedposttags
* @param string $context
* @return array $allowedposttags
*/
function wp5560_kses_allow_picture_tags($allowedposttags, $context) {
$allowedposttags['picture'] = [];
$allowedposttags['source'] = [
'media' => true,
'srcset' => true
];
return $allowedposttags;
}
add_filter('wp_kses_allowed_html', 'wp5560_kses_allow_picture_tags', 10, 2);
Hey @cabrerahector,
many many thanks for looking into this and helping out here – really appreciate it. And all the effort you are putting into providing WPP as a great tool for so many developers...!
And so it happens that
wp_kses_allowed_html()
doesn't include<picture>
nor<source>
in the list of "allowed" tags. Now you know why this is happening :P
Completely makes sense and above all an easily applied fix 🚀
Have a great holiday time and thanks again.
Describe the bug I am using the
wpp_custom_html()
-filter in order to output custom HTML for our most viewed posts widget. We are using an image generation helper class called Responsive.pics which renders a<picture>
-tag like this:After upgrading from
v5.3.5
to bothv5.5.1
as well as the latestv6.1.1
our custom markup breaks in the sense that there is some filtering happening and the<picture>
-tag gets stripped completely whilst only the<img>
-tag is being used.This in turn renders the whole output unusable and I would expect to not have the custom markup be filtered at all...
Could the image filtering be excluded from touching custom markup via the
wpp_custom_html()
-filter? Or is there a setting I could use? Tried altering the backend image settings, checked the wiki and the source code but couldn't find anything that would apply here.Screenshots
Let me know if you need more details / system specs – omitted those here since I thought you'd know what causes this and it's unrelated to our specific environment...
Thanks so much for your effort!