Add Missing Image Dimensions when Updating/Saving Post - php

I would like to automatically add missing image dimensions (width/height) to images (internal/external) when post is updated/saved. I found a way to do it when page is loaded but obviously it slows down the loading of the page.
This is original code. When added to the functions it does the job by adding image dimensions.
function add_img_size($content){
$pattern = '/<img [^>]*?src="(https?:\/\/[^"]+?)"[^>]*?>/iu';
preg_match_all($pattern, $content, $imgs);
foreach ( $imgs[0] as $i => $img ) {
if ( false !== strpos( $img, 'width=' ) && false !== strpos( $img, 'height=' ) ) {
continue;
}
$img_url = $imgs[1][$i];
$img_size = #getimagesize( $img_url );
if ( false === $img_size ) {
continue;
}
$replaced_img = str_replace( '<img ', '<img ' . $img_size[3] . ' ', $imgs[0][$i] );
$content = str_replace( $img, $replaced_img, $content );
}
return $content;
}
add_filter('the_content','add_img_size');
I tried editing it by using add_action save_post/pre_post_update but it does nothing.
add_action('save_post','add_img_size');
function add_img_size($post_id){
What am i missing? Can someone help me edit it so it adds image dimensions when post is updated/saved? Seemed simpler than it is..

function set_image_dimensions( $id, $post ) {
if ( ! wp_is_post_revision( $post ) ){
remove_action('save_post', 'set_image_dimensions', 10, 2 );
$content = $post->post_content;
$pattern = '/<img [^>]*?src="(https?:\/\/[^"]+?)"[^>]*?>/iu';
preg_match_all($pattern, $content, $imgs);
foreach ( $imgs[0] as $i => $img ) {
if ( false !== strpos( $img, 'width=' ) && false !== strpos( $img, 'height=' ) ) {
continue;}
$img_url = $imgs[1][$i];
$img_size = #getimagesize( $img_url );
if ( false === $img_size ) {
continue;}
$replaced_img = str_replace( '<img ', '<img ' . $img_size[3] . ' ', $imgs[0][$i] );
$content = str_replace( $img, $replaced_img, $content );
}
$post->post_content = $content;
wp_update_post( $post );
add_action( 'save_post', 'set_image_dimensions', 10, 2 );
}}
add_action( 'save_post', 'set_image_dimensions', 10, 2 );
This works as i wanted. Adds missing image dimension on update.
In the end when i started with post_content and ended with wp_update_post had no errors to deal with and it didn't work. The culprit was using $content = $post->post_content; instead the other way around the second time.
Got around infinite loop with help of link Shoelaced posted.

Related

Why html_entity_decode won't bring formatted HTML in WordPress?

I have this shortcode:
I do this shortcode in template, I tried several WordPress themes, and it does not return HTML, but just text in continuous row.
I used this shortcode way abck and it worked, I do not know what happened meanwhile in a year so it does not work in WordPress anymore.
Anyone has a clue?
function paywall_level_b( $atts, $content = null ) {
$post = get_queried_object();
if ( function_exists( 'pmpro_has_membership_access' )) {
// Check if the user has access to the post.
$hasaccess = pmpro_has_membership_access( $post->ID );
// Display Content if the user has access to the post.
if( ! empty( $hasaccess ) ) {
$content = apply_filters('the_content', get_the_content());
echo $content;
// Display Text if the user has no access to the post, but is logged in.
} elseif ( is_user_logged_in() ) {
$content = apply_filters('the_content', get_the_content());
$sentences = explode(".", $content);
$first_slice = implode(".", array_splice($sentences, 0, 5));
$second_slice = implode(".", array_splice($sentences, 0));
echo '<div class="non-paywall">'. html_entity_decode ( $first_slice ) .'.</div><div class="pmpro_content_message">Text</div>';
// Display Text if the user has no access to the post, and is not logged in.
} else {
$content = apply_filters('the_content', get_the_content());
$sentences = explode(".", $content);
$first_slice = implode(".", array_splice($sentences, 0, 5));
$second_slice = implode(".", array_splice($sentences, 0));
echo '<div class="non-paywall">'. html_entity_decode ( $first_slice ) .'.</div><div class="pmpro_content_message">Text 2</div>';
}
}
}
add_shortcode( 'paywall_level_b', 'paywall_level_b' );

Please what Am i doing wrong, getting Notice of Undefined variable in PHP 8

I got a Warning message on my WordPress site trying to insert a featured image after the first paragraph. It worked perfectly without warning or error in PHP7.4 but got the below warning on PHP 8.1
Please would need some help thanks in advance.
Warning: Undefined variable $post in /www/wwwroot/.../wp-content/themes/..../functions.php on line 7
Warning: Attempt to read property "ID" on null in /www/wwwroot/.../wp-content/themes/...../functions.php on line 7
add_filter( 'the_content', 'insert_featured_image', 20 );
function insert_featured_image( $content ) {
$feat_img = get_the_post_thumbnail($post->ID, 'post-single');
if ( is_single() && ! is_admin() ) {
return prefix_insert_after_paragraph( '<div class="top-featured-image">' . $feat_img . '</div>', 1, $content );
}
return $content;
}
// Parent Function that makes the magic happen
function prefix_insert_after_paragraph( $insertion, $paragraph_id, $content ) {
$closing_p = '</p>';
$paragraphs = explode( $closing_p, $content );
foreach ($paragraphs as $index => $paragraph) {
if ( trim( $paragraph ) ) {
$paragraphs[$index] .= $closing_p;
}
if ( $paragraph_id == $index + 1 ) {
$paragraphs[$index] .= $insertion;
}
}
return implode( '', $paragraphs );
}
You're trying to access a $post variable through $post->ID tho you didn't define it before.
We could first fetch the post object through get_post() then retrieve the ID, but we can do better. We can use get_the_ID() to retrieve the post ID.
<?php
add_filter( 'the_content', function ( $content ) {
if ( ! is_admin() && is_single() ) {
$thumbnail = get_the_post_thumbnail( get_the_ID(), 'post-single' );
return prefix_insert_after_paragraph( '<div class="top-featured-image">' . $thumbnail . '</div>', 1, $content );
};
return $content;
}, 20 );

Get first paragraph in wordpress

I have a problem with getting the first form the_excerpt();
Function acutally works but only for first post. I added in functions.php
function get_first_paragraph(){
global $post;
$str = wpautop( get_the_content() );
$str = substr( $str, 0, strpos( $str, '</p>' ) + 4 );
$str = strip_tags($str, '<a><strong><em>');
return '<p>' . $str . '</p>';
}
I'm calling this funcion in index.php inside The Loop <?php echo get_first_paragraph(); ?>
I have no idea why it pulls only for first post...
you can put this code in function.php file in your theme,
Get first paragraph
function awesome_excerpt($text, $raw_excerpt) {
if( ! $raw_excerpt ) {
$content = apply_filters( 'the_content', get_the_content() );
$text = substr( $content, 0, strpos( $content, '</p>' ) + 4 );
}
return $text;
}
add_filter( 'wp_trim_excerpt', 'awesome_excerpt', 10, 2 );
For more information, you can follow the reference link WORDPRESS THE_EXCERPT SHOW ONLY FIRST PARAGRAPH
That code didn't work for me in Gutenberg times. So I've used part of that code and did some searching and come up with this solution. Hope it helps.
function get_paragraph_content($paragraph_number){
global $post;
$i = 0;
$paragraph = '';
if ( has_blocks( $post->post_content ) ) {
$blocks = parse_blocks( $post->post_content );
foreach( $blocks as $block ) {
if( 'core/paragraph' === $block['blockName']){
$paragraph = render_block($block);
if (++$i == $paragraph_number) break;
}
}
$paragraph = substr( $paragraph, 0, strpos( $paragraph, '</p>' ) + 4 );
$paragraph = strip_tags($paragraph, '<a><strong><em>');
}
return $paragraph;
}

Add attribute to wp_get_attachment_image

I'm trying to add an attribute to the result of wp_get_attachment_image.
I want to use jquery lazyload to handle loading of my post thumbnails and to do that I need to add a data-original= attribute to the <img> tag wp_get_attachment_image is creating.
I've tried:
$imgsrc = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), "full" );
$imgsrc = $imgsrc[0];
$placeholderimg = wp_get_attachment_image( 2897, "full", array('data-original'=>$imgsrc) );
But it doesn't add the data attribute as I expected.
<img class="attachment-full" width="759" height="278" alt="..." src="..."></img>
Looking at the wp_get_attachment_image function it would seem that this ought to work though:
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '') {
$html = '';
$image = wp_get_attachment_image_src($attachment_id, $size, $icon);
if ( $image ) {
list($src, $width, $height) = $image;
$hwstring = image_hwstring($width, $height);
if ( is_array($size) )
$size = join('x', $size);
$attachment =& get_post($attachment_id);
$default_attr = array(
'src' => $src,
'class' => "attachment-$size",
'alt' => trim(strip_tags( get_post_meta($attachment_id, '_wp_attachment_image_alt', true) )), // Use Alt field first
'title' => trim(strip_tags( $attachment->post_title )),
);
if ( empty($default_attr['alt']) )
$default_attr['alt'] = trim(strip_tags( $attachment->post_excerpt )); // If not, Use the Caption
if ( empty($default_attr['alt']) )
$default_attr['alt'] = trim(strip_tags( $attachment->post_title )); // Finally, use the title
$attr = wp_parse_args($attr, $default_attr);
$attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment );
$attr = array_map( 'esc_attr', $attr );
$html = rtrim("<img $hwstring");
foreach ( $attr as $name => $value ) {
$html .= " $name=" . '"' . $value . '"';
}
$html .= ' />';
}
return $html;
}
Where am I going wrong?
[update] Sometimes it just takes a fresh pair of eyes to spot the idiocy... Thanks to hobo I realised I simply missed out a parameter in my function call :D :P
I haven't tested, but I think the problem is your array should be the fourth argument to wp_get_attachment_image, not the third.
So
$placeholderimg = wp_get_attachment_image( 2897, "full", array('data-original'=>$imgsrc) );
should be
$placeholderimg = wp_get_attachment_image( 2897, "full", false, array('data-original'=>$imgsrc) );
assuming you're happy with the default value (false) of the $icon argument.
I personally solved this problem doing a string replacement:
$imgsrc = wp_get_attachment_image_src( get_post_thumbnail_id($post->ID), "full" );
$imgsrc = $imgsrc[0];
$placeholderimg = wp_get_attachment_image( 2897, "full" );
$placeholderimg = str_replace( "<img ", "<img data-original='$imgsrc'", $placeholderimg );
It's not an elegant solution but it can work in some contexts (for example, you may have the attributes saved in a string and not as an array as in your case).

How do I write a custom function in WordPress?

When I upload a featured image, I want to give it the a width of "100%" but only if it is over 1170px. If the width is between 1170px and 770px, I want it be get a width of "770px", otherwise the width will not be changed.
So far this code is doing what I want:
if (intval($width) >= 1170) {
$hwstring = 'width=100%';
} elseif ( (intval($width) < 1170) && (intval($width) >= 770) ) {
$hwstring = 'width=770px';
} else {
$hwstring = image_hwstring($width, 0);
};
However I have modified the media.php file inside the "wp-includes" folder which is apparently not the right way to do it. So how could I create a function that does the same thing without modifying the existing Wordpress code?
function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '') {
$html = '';
$image = wp_get_attachment_image_src($attachment_id, $size, $icon);
if ( $image ) {
list($src, $width, $height) = $image;
$hwstring = image_hwstring($width, $height);
if ( is_array($size) )
$size = join('x', $size);
$attachment =& get_post($attachment_id);
$default_attr = array(
'src' => $src,
'class' => "attachment-$size",
'alt' => trim(strip_tags( get_post_meta($attachment_id, '_wp_attachment_image_alt', true) )), // Use Alt field first
'title' => trim(strip_tags( $attachment->post_title )),
);
if ( empty($default_attr['alt']) )
$default_attr['alt'] = trim(strip_tags( $attachment->post_excerpt )); // If not, Use the Caption
if ( empty($default_attr['alt']) )
$default_attr['alt'] = trim(strip_tags( $attachment->post_title )); // Finally, use the title
$attr = wp_parse_args($attr, $default_attr);
$attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment );
$attr = array_map( 'esc_attr', $attr );
if (intval($width) >= 1170) {
$hwstring = 'width=100%';
} elseif ( (intval($width) < 1170) && (intval($width) >= 770) ) {
$hwstring = 'width=770px';
} else {
$hwstring = image_hwstring($width, 0);
};
$html = rtrim("<img $hwstring");
foreach ( $attr as $name => $value ) {
$html .= " $name=" . '"' . $value . '"';
}
$html .= ' />';
}
return $html;
}
Unfortunately there aren't any hooks for you to use to do this exactly in that function, but you can construct it yourself without modifying the core Wordpress files (which you don't want to do lest you overwrite your custom code when you upgrade). I'm kind of surprised that the wp_get_attachment_image_src() function doesn't pass the return values through filter to do exactly what you are talking about.
If you look at the top of this function, it gets the and array of $src, $width, $height by calling $image = wp_get_attachment_image_src($attachment_id, $size, $icon); You can make this same call yourself and construct your custom widths - basically copying the function into a custom version in functions.php or a custom functions plugin.
You can create a new ticket at http://core.trac.wordpress.org/newticket if you want to request this functionality to be added in a future version. The addition would be to wp_get_attachment_image_src() on line 515 (of the current trunk version of WP):
return apply_filters( 'wp_get_attachment_image_src', array( $src, $width, $height ), $attachment_id, $size, $icon );
EDIT: Ticket already exists, patch is a little weird, I submitted a new one but no guarantees as to when it will go in if it's approved..

Categories