Here's my situation:
I'm redesigning an existing Wordpress site.
The new design separates all images from the actual post content and puts it in a Featured Gallery.
Currently, each post has your typical inline images in the post content.
Is this even remotely possible to extract all inline images from the post content, and create Featured Galleries with those images for each post?
In the past I've done something like the below to grab the first image in the post content, and set it as the standard featured image, but nothing like what I have to do with this dilemma.
function wpforce_featured() {
global $post;
$already_has_thumb = has_post_thumbnail($post->ID);
if (!$already_has_thumb) {
$attached_image = get_children( "post_parent=$post->ID&post_type=attachment&post_mime_type=image&numberposts=1" );
if ($attached_image) {
foreach ($attached_image as $attachment_id => $attachment) {
set_post_thumbnail($post->ID, $attachment_id);
}
}
}
} //end function
add_action('the_post', 'wpforce_featured');
add_action('save_post', 'wpforce_featured');
add_action('draft_to_publish', 'wpforce_featured');
add_action('new_to_publish', 'wpforce_featured');
add_action('pending_to_publish', 'wpforce_featured');
add_action('future_to_publish', 'wpforce_featured');
Basically the method I used was to create a one time script that I ran to move all inline images from the post to the Featured Gallery, like this:
// Loop over every post
while ( have_posts() ) : the_post();
// Get the images attached to the post.
$imageids = array();
$images = get_attached_media( 'image', $post->ID );
foreach ($images as $image) {
$imageids[] = $image->ID;
}
$comma_separated = implode(",", $imageids);
// Save them to the Featured Gallery (Got this info by digging into the Featured Gallery plugin's source code)
if ( $post->post_type == 'revision' ) {return;}
if ( get_post_meta( $post->ID, 'fg_perm_metadata', FALSE ) ) {
update_post_meta( $post->ID, 'fg_perm_metadata', $comma_separated );
} else {
add_post_meta( $post->ID, 'fg_perm_metadata', $comma_separated );
}
if ( !$comma_separated ) delete_post_meta( $post->ID, 'fg_perm_metadata' );
endwhile;
// Reset Query
wp_reset_query();
Then, I created a function that removes all images in the post content, which I placed in functions.php:
function remove_images( $content )
{
$content =
preg_replace(
array('{<a(.*?)(wp-att|wp-content\/uploads)[^>]*><img}',
'{ wp-image-[0-9]*" /></a>}'),
array('<img','" />'),
$content
);
$content = preg_replace('/<img(.*)>/i','', $content, 1);
return $content;
}
add_filter( 'the_content', 'remove_images' );
First preg_replace removes the link around the images. Second removes the image.
the problem is if i read you correctly is that all the images are located as urls in the post content?
You can parse them:
$content = get_the_content();
$html = new DOMDocument;
$html->loadHTML($content);
//get the images
$images = $html->getElementsByTagName('img');
foreach($images as $image=>$key {
$imageurls[]=$key->attributes->getNamedItem("src")->value;//play with this cant remember how it returns object.
}
$content= preg_replace('/<img(.*)>/i','',$content,1);
echo $content;
// you also have a array of images to use.
Related
I have an issue related save_post_($post-type) hook and ACF gallery field.
I got this code snippet from somewhere. Let me explain: I created an ACF gallery field (acf-gallery is the field name) shown in Custom Post Type (cpt1 is the slug) then use this snippet to set the first image of this gallery as the featured image when saving just like what Woocommerce do.
But what if I want it to work with another Custom Post Type (let's say the slug is cpt2)? Can I use array( 'cpt1', 'cpt2' ) to replace cpt1? Is there a way to include multiple custom post types?
/* Set the first image generated by ACF gallery field as featured image */
add_action( 'save_post_cpt1', 'set_featured_image_from_gallery' );
function set_featured_image_from_gallery() {
global $post;
$post_id = $post->ID;
$images = get_field('acf_gallery', $post_id, false);
$image_id = $images[0];
if ( $image_id ) {
set_post_thumbnail( $post_id, $image_id );
}
}
I edited this snippet using save-post hook according to comments below. But I don't know if it's valid. Can someone help?
/* Set the first image generated by ACF gallery field as featured image */
add_action( 'save_post', 'set_featured_image_from_gallery' );
function set_featured_image_from_gallery($post_id) {
if (get_post_type($post_id) != array( 'cpt1', 'cpt2')) {
return;
}
$has_thumbnail = get_the_post_thumbnail($post_id);
if ( !$has_thumbnail ) {
$images = get_field('acf_gallery', $post_id, false);
$image_id = $images[0];
if ( $image_id ) {
set_post_thumbnail( $post_id, $image_id );
}
}
}
I usually use save_post hook, $post_id variable, get_post_type and in_array functions.
function set_featured_image_from_gallery($post_id)
{
$included_cpts = array('cpt1', 'cpt2', 'cpt3');
if (in_array(get_post_type($post_id), $included_cpts)) {
$has_thumbnail = get_the_post_thumbnail($post_id);
if (!$has_thumbnail) {
$images = get_field('acf_gallery', $post_id, false);
$image_id = $images[0];
if ($image_id) {
set_post_thumbnail($post_id, $image_id);
}
}
}
}
add_action('save_post', 'set_featured_image_from_gallery');
I am using CMB2 file_list for uploading photos e.g. photo gallery. On the home page I need to get only the first photo and not the entire gallery. Below is the function to get all the photo. How can i retrieve only the first photo in the list?
function cmb2_output_file_list( $file_list_meta_key, $img_size = 'medium' ) {
$files = get_post_meta( get_the_ID(), $file_list_meta_key, 1 );
echo '<div class="file-list-wrap">';
foreach ( (array) $files as $attachment_id => $attachment_url ) {
echo '<div class="file-list-image">';
echo wp_get_attachment_image( $attachment_id, $img_size );
echo '</div>';
}
echo '</div>';
}
cmb2_output_file_list( 'wiki_test_file_list', 'small' );
You'd use something like this, make sure to change the meta key to the correct one, this will get the ID and URL of first file in the list:
$file_list_meta_key = 'wiki_test_file_list';
$files = get_post_meta( get_the_ID(), $file_list_meta_key, 1 );
$first_id = key($files);
$first_url = reset($files);
I have a problem to receive the first image of the woocommerce gallery, if the post thumbnail is missing. I want to show the post thumbnail, if this is missing, the first image of the WooCommerce gallery and at least the placeholder image, if all is missing.
I found this function in the WooCommerce Codex, but I donĀ“t come on an satisfying solution. Maybe someone can help me to receive an good solution
function woocommerce_get_product_thumbnail( $size = 'shop_catalog', $deprecated1 = 0, $deprecated2 = 0 ) {
global $post;
$image_size = apply_filters( 'single_product_archive_thumbnail_size', $size );
if ( has_post_thumbnail() ) {
$props = wc_get_product_attachment_props( get_post_thumbnail_id(), $post );
return get_the_post_thumbnail( $post->ID, $image_size, array(
'title' => $props['title'],
'alt' => $props['alt'],
) );
} elseif ( wc_placeholder_img_src() ) {
return wc_placeholder_img( $image_size );
}
}
}
So, I found myself an soultion. Is not as perfect as I wished, but it works. I post this this answer, if someone is searching for an similar solution. So, this could be an way:
/* GET PRODUCT IMAGE WITH GALLERY FALLBACK
================================================== */
if ( ! function_exists( 'zet_get_prod_image_fallback_gallery' ) ) {
function zet_get_prod_image_fallback_gallery() {
global $post, $woocommerce, $product;
$image_size = apply_filters( 'single_product_archive_thumbnail_size', $size );
$thumb_gallery_ids = $product->get_gallery_attachment_ids();
if ( has_post_thumbnail() || $thumb_gallery_ids ) {
if ( has_post_thumbnail() ) {
$image_id = get_post_thumbnail_id();
} else {
$image_id = $thumb_gallery_ids[0];
}
$thumb_image = wp_get_attachment_url( $image_id, apply_filters( 'single_product_small_thumbnail_size', 'shop_thumbnail' ) );
$image_html = '<img src="'.$thumb_image.'" />';
echo $image_html;
// Get the Placeholder image
} elseif ( wc_placeholder_img_src() ) {
echo wc_placeholder_img( $image_size );
}
}
}
For users who are not so familiar with wordpress: add this snippet to your functions.php
If you want to use this fallback for your whole shop -> change the function woocommerce_template_loop_product_thumbnail() in woocommerce/content-product.php to zet_get_prod_image_fallback_gallery(). Hope it helps!
I have a running site designed in wordpress, I am trying to fetch all the images for a product that is defined in a woo commerce and display them one after the other i have tried doing the below but it didn't work out.
<?php while(the_post_thumbnail()) the_post_thumbnail(); ?>
If you want to get product gallery images anywhere. You can try this. It will fetch the images by id.
<?php
$product_id = '14';
$product = new WC_product($product_id);
$attachment_ids = $product->get_gallery_attachment_ids();
foreach( $attachment_ids as $attachment_id )
{
// Display the image URL
echo $Original_image_url = wp_get_attachment_url( $attachment_id );
// Display Image instead of URL
echo wp_get_attachment_image($attachment_id, 'full');
}
?>
If you are displaying the images in single product page.
Then
<?php
global $product;
$attachment_ids = $product->get_gallery_attachment_ids();
foreach( $attachment_ids as $attachment_id )
{
// Display the image URL
echo $Original_image_url = wp_get_attachment_url( $attachment_id );
// Display Image instead of URL
echo wp_get_attachment_image($attachment_id, 'full');
}
?>
By default in Woocommerce for alt used image file's name.
Does anyone know how to change thumbnail meta (alt and title) to show Product name?
Try this :
add_filter('wp_get_attachment_image_attributes', 'change_attachement_image_attributes', 20, 2);
function change_attachement_image_attributes( $attr, $attachment ){
// Get post parent
$parent = get_post_field( 'post_parent', $attachment);
// Get post type to check if it's product
$type = get_post_field( 'post_type', $parent);
if( $type != 'product' ){
return $attr;
}
/// Get title
$title = get_post_field( 'post_title', $parent);
$attr['alt'] = $title;
$attr['title'] = $title;
return $attr;
}
I've updated XciD's answer to a much cleaner version:
add_filter('wp_get_attachment_image_attributes', 'change_attachement_image_attributes', 20, 2);
function change_attachement_image_attributes($attr, $attachment) {
global $post;
if ($post->post_type == 'product') {
$title = $post->post_title;
$attr['alt'] = $title;
$attr['title'] = $title;
}
return $attr;
}
Unfortunately on the main image the script doesn't work for me (XciD's neither), but on the small thumbs it is. Interesting :)
Update: If I turn off the main image, then the script starts working from the second thumb!
Update 2: Ok. It was an "Oh God Please No!" situation as some bad words JS code changed the alt tag. OMG...