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).
Related
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.
I'm using Removing link from product thumbnail on cart page answer code to remove the permalink from the thumbnail image on the cart page.
Now I would like to wrap the thumbnail in a span or another element. I would like to leave the cart thumbnail intact. Is there a hook for this? I don't use a theme but a plugin.
Currently I am using the following code
function custom_woocommerce_cart_item_thumbnail($a) {
$class = 'attachment-shop_thumbnail wp-post-image'; // Default cart thumbnail class.
$src = 'dummy';
// Construct your img tag.
$a = '<img';
$a .= ' src="' . $src . '"';
$a .= ' class="' . $class . '"';
$a .= ' />';
// Output.
return $a;
}
add_filter( 'woocommerce_cart_item_thumbnail', 'custom_woocommerce_cart_item_thumbnail', 10, 3 );
Someone who can guide me on how to apply this?
The cart/cart.php template file contains (line 65-75)
<td class="product-thumbnail">
<?php
$thumbnail = apply_filters( 'woocommerce_cart_item_thumbnail', $_product->get_image(), $cart_item, $cart_item_key );
if ( ! $product_permalink ) {
echo $thumbnail; // PHPCS: XSS ok.
} else {
printf( '%s', esc_url( $product_permalink ), $thumbnail ); // PHPCS: XSS ok.
}
?>
</td>
This ensures the output of the thumbnail with associated HTML code
The woocommerce_cart_item_thumbnail filter hook, first paramater contains $_product->get_image()
Which then leads us to the next code
/**
* Returns the main product image.
*
* #param string $size (default: 'woocommerce_thumbnail').
* #param array $attr Image attributes.
* #param bool $placeholder True to return $placeholder if no image is found, or false to return an empty string.
* #return string
*/
public function get_image( $size = 'woocommerce_thumbnail', $attr = array(), $placeholder = true ) {
$image = '';
if ( $this->get_image_id() ) {
$image = wp_get_attachment_image( $this->get_image_id(), $size, false, $attr );
} elseif ( $this->get_parent_id() ) {
$parent_product = wc_get_product( $this->get_parent_id() );
if ( $parent_product ) {
$image = $parent_product->get_image( $size, $attr, $placeholder );
}
}
if ( ! $image && $placeholder ) {
$image = wc_placeholder_img( $size, $attr );
}
return apply_filters( 'woocommerce_product_get_image', $image, $this, $size, $attr, $placeholder, $image );
}
which in turn invokes other functions.
However, because you want to keep the product thumbnail intact and wrap it in span tags, you can just use.
function filter_woocommerce_cart_item_thumbnail( $product_image, $cart_item, $cart_item_key ) {
// Wrap the thumbnail in a span
$product_image = '<span>' . $product_image . '</span>';
return $product_image;
}
add_filter( 'woocommerce_cart_item_thumbnail', 'filter_woocommerce_cart_item_thumbnail', 10, 3 );
Note: if you want to change something in the element you can use the str_replace PHP function
Like:
$image = '<img src="myimage.jpg" width="500" height="600">';
Result before:
<img src="myimage.jpg" width="500" height="600">
With str_replace:
// Replace <img with <span><img
$image = str_replace( '<img', '<span><img', $image );
Result after:
<span><img src="myimage.jpg" width="500" height="600">
Another option is to overwrite the template file (see the answer you already referred to on how to apply), so in conjunction with that answer would
if ( ! $product_permalink ) {
echo $thumbnail; // PHPCS: XSS ok.
} else {
printf( '%s', esc_url( $product_permalink ), $thumbnail ); // PHPCS: XSS ok.
}
Become
echo '<span>' . $thumbnail . '</span>';
In WPBakery, I've mapped out a module which requires an image:
public function image_html($atts) {
extract(
shortcode_atts(
array(
'image' => '',
),
$atts
)
);
$getImage = shortcode_atts(
array(
'image' => 'image',
),
$atts
);
$image_ids = explode(',',$getImage['image']);
foreach($image_ids as $image_id) {
$images = wp_get_attachment_image_src($image_id, 'full');
$image = $images[0];
$thumb_id = get_post_thumbnail_id(get_the_ID());
$alt = get_post_meta($thumb_id, '_wp_attachment_image_alt', true);
}
}
I've used wp_get_attachment_image_src to get the attached image alt text, but it doesn't seem to work. And yes, the image does have alt text in WordPress > Media > Alternative Text.
The markup is as follows:
<img src="<?php echo $image; ?>" alt="<?php echo $alt; ?>" />
$image appears fine, $alt shows up empty.
Try with alternative way :
$thumb_id = get_post_meta( get_the_ID(), '_thumbnail_id', true );
I have this code where I'm trying to display all three images attached to visual composer's custom "attach_images" element type that has param "macimgs". The problem is that only the last one image will display and if I inspect the container that holds images, I see only one image inside instead of three.
Any ideas of what to modify here?
$gallery = shortcode_atts(
array(
'macimgs' => 'macimgs',
), $atts );
$image_ids=explode(',',$gallery['macimgs']);
$image_no = 1;
foreach( $image_ids as $image_id ){
$images = wp_get_attachment_image_src( $image_id, 'full' );
$output ='
<img src="'. $images[0] .'" alt="" />
';
$image_no++;
}
return $output;
}
i think you forget to concatenate the $output variable.
try this code
$gallery = shortcode_atts(
array(
'macimgs' => 'macimgs',
), $atts );
$image_ids = explode(',',$gallery['macimgs']);
$output = '';
$image_no = 1;
foreach( $image_ids as $image_id ){
$images = wp_get_attachment_image_src( $image_id, 'full' );
$output .='<img src="'. $images[0] .'" alt="" />';
$image_no++;
}
return $output;
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..