This i built to assist me on my main site. Sometimes, there might be external images when you copy a bulk of text from a website or document. This will help pull the external images into the media library, and update your post body. You can use WPCodeBox or FluentSnippets to Run this easily without installing any plugin for this specific purpose.
<?php
/**
* Plugin Name: RR β Import External Images on Save
* Description: On save (draft/publish), sideload external <img> to Media Library, rewrite src, and set alt/title/description from filename.
* Version: 1.1.0
*/
if ( ! defined( 'ABSPATH' ) ) { exit; }
add_action( 'save_post', 'rr_import_external_images_on_save', 10, 3 );
function rr_import_external_images_on_save( $post_id, $post, $update ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) return;
if ( empty( $post ) || empty( $post->post_content ) ) return;
rr_require_media_libs();
$ptype = get_post_type( $post );
if ( ! post_type_supports( $ptype, 'editor' ) ) return;
$content = $post->post_content;
$attrs = rr_extract_img_srcs( $content ); // [ raw ' src=".."' => url ]
if ( empty( $attrs ) ) return;
$site_host = wp_parse_url( home_url(), PHP_URL_HOST );
$map = get_post_meta( $post_id, '_rr_extimg_map', true );
if ( ! is_array( $map ) ) $map = [];
$changed = false;
foreach ( $attrs as $raw => $src ) {
if ( ! wp_http_validate_url( $src ) ) continue;
$host = wp_parse_url( $src, PHP_URL_HOST );
if ( ! $host || strcasecmp( $host, $site_host ) === 0 ) continue; // already local
$new_url = $map[ $src ] ?? '';
if ( empty( $new_url ) ) {
$existing_id = attachment_url_to_postid( $src );
if ( $existing_id ) {
rr_fill_attachment_texts_if_empty( $existing_id, $src );
$new_url = wp_get_attachment_url( $existing_id );
} else {
$attach_id = rr_sideload_image_as_attachment( $src, $post_id );
if ( is_wp_error( $attach_id ) || ! $attach_id ) continue;
$new_url = wp_get_attachment_url( $attach_id );
}
if ( $new_url ) $map[ $src ] = $new_url;
}
if ( $new_url && $new_url !== $src ) {
// Replace ONLY the src attribute string. Keep the preceding space.
$content = str_replace( $raw, ' src="' . esc_url( $new_url ) . '"', $content );
$changed = true;
}
}
if ( $changed ) {
remove_action( 'save_post', 'rr_import_external_images_on_save', 10 );
wp_update_post( [ 'ID' => $post_id, 'post_content' => $content ] );
update_post_meta( $post_id, '_rr_extimg_map', $map );
add_action( 'save_post', 'rr_import_external_images_on_save', 10, 3 );
}
}
/**
* Match ONLY the src="..." attribute inside <img>, keeping the leading space for safe replacement.
* Returns [ raw_attr => url ] where raw_attr looks like: ' src="https://..."'
*/
function rr_extract_img_srcs( string $html ) : array {
$results = [];
if ( preg_match_all( '#<img\b[^>]*\K\s+src=("|\')([^"\']+)\1#i', $html, $m, PREG_SET_ORDER ) ) {
foreach ( $m as $match ) {
$results[ $match[0] ] = trim( html_entity_decode( $match[2] ) );
}
}
return $results;
}
/**
* Sideload image and set texts from filename.
*/
function rr_sideload_image_as_attachment( string $url, int $post_id ) {
$id = media_sideload_image( $url, $post_id, null, 'id' );
if ( is_wp_error( $id ) ) return $id;
// Generate sizes.
$path = get_attached_file( $id );
if ( $path ) {
$meta = wp_generate_attachment_metadata( $id, $path );
if ( $meta ) wp_update_attachment_metadata( $id, $meta );
}
update_post_meta( $id, '_rr_source_url', esc_url_raw( $url ) );
// Set title, alt, caption, description from filename.
rr_fill_attachment_texts_if_empty( $id, $url );
return (int) $id;
}
/**
* If attachment text fields are empty, fill from a humanized filename.
*/
function rr_fill_attachment_texts_if_empty( int $attach_id, string $fallback_url = '' ) : void {
$path = get_attached_file( $attach_id );
$base = '';
if ( $path && file_exists( $path ) ) {
$pi = pathinfo( $path );
$base = $pi['filename'] ?? '';
}
if ( ! $base && $fallback_url ) {
$pi = pathinfo( wp_parse_url( $fallback_url, PHP_URL_PATH ) ?? '' );
$base = $pi['filename'] ?? '';
}
$label = rr_humanize_filename( $base );
if ( $label === '' ) return;
// Title.
$att = get_post( $attach_id );
if ( $att && $att->post_title === '' ) {
wp_update_post( [
'ID' => $attach_id,
'post_title' => $label,
] );
}
// Alt text.
$alt = get_post_meta( $attach_id, '_wp_attachment_image_alt', true );
if ( $alt === '' ) {
update_post_meta( $attach_id, '_wp_attachment_image_alt', $label );
}
// Caption (excerpt) and Description (content).
$cur_caption = get_post_field( 'post_excerpt', $attach_id );
if ( $cur_caption === '' ) {
wp_update_post( [
'ID' => $attach_id,
'post_excerpt' => $label,
] );
}
$cur_desc = get_post_field( 'post_content', $attach_id );
if ( $cur_desc === '' ) {
wp_update_post( [
'ID' => $attach_id,
'post_content' => $label,
] );
}
}
/**
* Turn "my-photo_2025-08-29" into "My Photo 2025 08 29".
*/
function rr_humanize_filename( string $name ) : string {
$name = urldecode( $name );
$name = preg_replace( '/[_\-]+/u', ' ', $name );
$name = preg_replace( '/\s+/u', ' ', $name );
$name = trim( $name );
if ( $name === '' ) return '';
// Title case safely.
if ( function_exists( 'mb_convert_case' ) ) {
$name = mb_convert_case( $name, MB_CASE_TITLE, 'UTF-8' );
} else {
$name = ucwords( strtolower( $name ) );
}
return sanitize_text_field( $name );
}
/**
* Ensure media functions exist in snippet context.
*/
function rr_require_media_libs() : void {
if ( ! function_exists( 'download_url' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) {
require_once ABSPATH . 'wp-admin/includes/image.php';
}
if ( ! function_exists( 'media_sideload_image' ) ) {
require_once ABSPATH . 'wp-admin/includes/media.php';
}
}
This is a simple code snippet to send a notification when his/her comment is replied by someone. Does not need to have a plugin for this. Here is the code.
<?php
/**
* RR - Email Parent on Comment Reply (v1.4 AOL-safe)
* PHP 8.1+, WP 6.5+. Works with FluentSMTP.
*/
$rrcpr_cfg = [
'allowed_post_types' => [], // e.g. ['post','toolkit']
'skip_if_same_author' => true,
'include_reply_content' => true,
'include_parent_link' => true,
'include_parent_excerpt'=> true,
'from_email' => '[email protected]',
'from_name' => 'RuhaniRabin.com',
'subject_tpl' => '[{site}] New reply to your comment on "{post}" by {replier}',
'body_intro' => 'Hi {parent_name}, you received a reply to your comment on β{post}β.',
'add_reply_to' => true,
'enable_global_from_filters' => true,
];
if ( ! function_exists( 'rrcpr_send_parent_reply_email' ) ) :
function rrcpr_send_parent_reply_email( $comment_id ) {
global $rrcpr_cfg;
if ( get_comment_meta( $comment_id, '_rrcpr_parent_notified', true ) ) return;
$comment = get_comment( $comment_id );
if ( ! $comment || empty( $comment->comment_parent ) ) return;
$post = get_post( (int) $comment->comment_post_ID );
if ( ! $post ) return;
$post_type = get_post_type( $post );
if ( ! $post_type || ! post_type_supports( $post_type, 'comments' ) ) return;
if ( ! empty( $rrcpr_cfg['allowed_post_types'] ) && ! in_array( $post_type, $rrcpr_cfg['allowed_post_types'], true ) ) return;
$parent = get_comment( (int) $comment->comment_parent );
if ( ! $parent ) return;
$to = trim( (string) $parent->comment_author_email );
if ( ! $to || ! is_email( $to ) ) return;
if ( ! empty( $rrcpr_cfg['skip_if_same_author'] ) ) {
$reply_email = trim( (string) $comment->comment_author_email );
if ( $reply_email && strcasecmp( $reply_email, $to ) === 0 ) return;
}
$site_name = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES );
$post_title = get_the_title( $post ) ?: '(no title)';
$replier = $comment->comment_author ?: 'Someone';
$parent_name = $parent->comment_author ?: 'there';
$reply_link = get_comment_link( $comment );
$parent_link = get_comment_link( $parent );
$subject = trim( wp_strip_all_tags( strtr( (string) $rrcpr_cfg['subject_tpl'], [
'{site}' => $site_name,
'{post}' => $post_title,
'{replier}' => $replier,
] ) ) );
if ( $subject === '' ) $subject = sprintf( '[%s] New reply to your comment', $site_name ?: 'Website' );
$intro = strtr( (string) $rrcpr_cfg['body_intro'], [
'{parent_name}' => $parent_name,
'{post}' => $post_title,
] );
// Very safe HTML only.
$allowed = [
'a' => [ 'href' => [], 'title' => [], 'rel' => [], 'target' => [] ],
'p' => [],
'br' => [],
'strong' => [],
'em' => [],
'code' => [],
'blockquote' => [],
];
$reply_html = '';
if ( ! empty( $rrcpr_cfg['include_reply_content'] ) && ! empty( $comment->comment_content ) ) {
$clean = wp_kses( make_clickable( $comment->comment_content ), $allowed );
$reply_html = '<p><strong>New reply:</strong></p><blockquote>' . $clean . '</blockquote>';
}
$parent_excerpt_html = '';
if ( ! empty( $rrcpr_cfg['include_parent_excerpt'] ) && ! empty( $parent->comment_content ) ) {
$excerpt = wp_html_excerpt( wp_strip_all_tags( $parent->comment_content ), 240, 'β¦' );
$parent_excerpt_html = '<p><strong>Your comment excerpt:</strong></p><blockquote>' . esc_html( $excerpt ) . '</blockquote>';
}
// Links duplicated: as anchor and as visible full URL text.
$reply_anchor = '<a href="' . esc_url( $reply_link ) . '">View the reply</a>';
$reply_full = '<p>' . esc_html( $reply_link ) . '</p>';
$parent_anchor = '';
$parent_full = '';
if ( ! empty( $rrcpr_cfg['include_parent_link'] ) ) {
$parent_anchor = '<a href="' . esc_url( $parent_link ) . '">View your original comment</a>';
$parent_full = '<p>' . esc_html( $parent_link ) . '</p>';
}
$message = '<div style="font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;line-height:1.6;font-size:15px;color:#222">';
$message .= '<p>' . esc_html( $intro ) . '</p>';
$message .= $reply_html . $parent_excerpt_html;
$message .= '<p>' . $reply_anchor . '</p>' . $reply_full;
if ( $parent_anchor ) {
$message .= '<p>' . $parent_anchor . '</p>' . $parent_full;
}
$message .= '<p style="color:#666;font-size:12px;margin-top:16px">Youβre receiving this because someone replied to your comment on ' . esc_html( $site_name ) . '.</p>';
$message .= '</div>';
$headers = [ 'Content-Type: text/html; charset=UTF-8' ];
$from_email = sanitize_email( $rrcpr_cfg['from_email'] );
$from_name = sanitize_text_field( $rrcpr_cfg['from_name'] ?: $site_name );
if ( $from_email ) $headers[] = 'From: ' . $from_name . ' <' . $from_email . '>';
if ( ! empty( $rrcpr_cfg['add_reply_to'] ) && is_email( $comment->comment_author_email ) ) {
$headers[] = 'Reply-To: ' . sanitize_text_field( $replier ) . ' <' . sanitize_email( $comment->comment_author_email ) . '>';
}
$ct = function() { return 'text/html; charset=UTF-8'; };
add_filter( 'wp_mail_content_type', $ct );
$sent = wp_mail(
apply_filters( 'rrcpr_email_to', $to, $comment, $parent, $post ),
apply_filters( 'rrcpr_email_subject', $subject, $comment, $parent, $post ),
apply_filters( 'rrcpr_email_message', $message, $comment, $parent, $post ),
apply_filters( 'rrcpr_email_headers', $headers, $comment, $parent, $post )
);
remove_filter( 'wp_mail_content_type', $ct );
if ( $sent ) add_comment_meta( $comment_id, '_rrcpr_parent_notified', time(), true );
}
add_action( 'comment_post', function( $comment_id, $approved ) {
if ( (int) $approved === 1 ) rrcpr_send_parent_reply_email( $comment_id );
}, 10, 2 );
add_action( 'transition_comment_status', function( $new_status, $old_status, $comment ) {
if ( 'approved' === $new_status && 'approved' !== $old_status && $comment && ! empty( $comment->comment_ID ) ) {
rrcpr_send_parent_reply_email( (int) $comment->comment_ID );
}
}, 10, 3 );
// Global From fallback.
if ( ! function_exists( 'rrcpr_mail_from' ) && ! empty( $rrcpr_cfg['enable_global_from_filters'] ) ) {
function rrcpr_mail_from( $from ) { global $rrcpr_cfg; $c = sanitize_email( $rrcpr_cfg['from_email'] ); return $c ?: $from; }
function rrcpr_mail_from_name( $name ) { global $rrcpr_cfg; $s = wp_specialchars_decode( get_bloginfo( 'name' ), ENT_QUOTES ); $c = sanitize_text_field( $rrcpr_cfg['from_name'] ?: $s ); return $c ?: $name; }
add_filter( 'wp_mail_from', 'rrcpr_mail_from' );
add_filter( 'wp_mail_from_name', 'rrcpr_mail_from_name' );
}
endif;
SEOPress works out of the box is Google Search Console entry is a URL based entry (eg. www.domain .com format) but if the entry is based on sc-domain only - you will need a small patch to make SEOPress work properly.
<?php
//In case you use a property domain with Google Search console
function sp_search_console_base_url($site_url)
{
//default: site_url();
return "sc-domain:ruhanirabin.com";
}
add_filter("seopress_search_console_base_url", "sp_search_console_base_url");
//In case you use a property domain with Google Search console
function sp_inspect_url_home_url($home_url)
{
//default: get_home_url();
return "sc-domain:ruhanirabin.com";
}
add_filter("seopress_inspect_url_home_url", "sp_inspect_url_home_url");
