Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions includes/class-default-image.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public static function init() {
add_filter( 'attachment_fields_to_save', [ __CLASS__, 'save_attachement_settings' ], 10, 2 );
add_filter( 'attachment_fields_to_edit', [ __CLASS__, 'add_attachment_field' ], 10, 2 );
add_action( 'template_redirect', [ __CLASS__, 'handle_not_found_image' ] );
add_action( 'wp_head', [ __CLASS__, 'add_404_image_handler_function' ] );
add_filter( 'the_content', [ __CLASS__, 'add_onerror_to_images' ] );
}

/**
Expand Down Expand Up @@ -86,5 +88,54 @@ public static function save_attachement_settings( $post, $attachment ) {

return $post;
}

/**
* Add JavaScript function to handle 404 images.
* If an image is served from a different domain, the `template_redirect` action won't catch a 404.
* Adding a JS fallback ensures all images will have the default applied.
*
* Note that a better approach would be to use `img.addEventListener` here, instead of
* adding the `onerror` attribute in `add_onerror_to_images` method, but
* the event listener way for some reason did not work in testing. This solution
* is less elegant, but more robust.
*/
public static function add_404_image_handler_function() {
$default_image_url = get_option( self::OPTION_NAME );
if ( ! empty( $default_image_url ) ) {
echo '<script>
function newspackHandleImageError(img) {
if (!img.dataset.defaultImageHandled) {
img.dataset.defaultImageHandled = true;
img.src = "' . esc_js( $default_image_url ) . '";
}
}
</script>';
}
}

/**
* Add the onerror attribute to all img elements in the content.
*
* @param string $content The post content.
* @return string Modified content with onerror attributes.
*/
public static function add_onerror_to_images( $content ) {
$content = preg_replace_callback(
'/<img[^>]+>/i',
function ( $matches ) {
if ( strpos( $matches[0], 'onerror=' ) === false ) {
return preg_replace(
'/<img/',
'<img onerror="if (typeof newspackHandleImageError === \'function\') newspackHandleImageError(this);"',
$matches[0],
1
);
}
return $matches[0];
},
$content
);
return $content;
}
}
Default_Image::init();