Ask your WordPress questions! Pay money and get answers fast! (more info)

Filter the_content on CPT - fetch images from children posts WordPress

  • SOLVED

Hi!

I'm using a plugin on my site that apply some things on images inside the_content.

Now I'm building a new function on the site, where I have a parent post of one custom post type (open_list), and children to this post from another custom post type (user_images).

In the template for the parent custom post type I used this function to fetch the children posts:

<?php
// WP_Query arguments
$args = array (
'parent' => $post->ID,
'posts_per_page' => '-1',
'post_type' => 'user_images',
'post_status' => 'publish',
'orderby' => array('meta_value_num' => 'DESC', 'date' => 'DESC'),
);

// The Query
$query = new WP_Query( $args );

// The Loop
$counter = 0;
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
$query->the_post();
$counter++;
?>
<h2><?php echo '#' . $counter . '.'; ?> <?php the_title(); ?></h2>
<?php the_post_thumbnail('large', array('class' => 'alignnone wp-image')); ?>
<?php
}
} else {
// no posts found
}

// Restore original Post Data
wp_reset_postdata();
?>


The problem with is that these images is fetched outside the_content, which makes the plugin I mentioned before useless.

So, instead I need the following:

Apply a filter to the parent custom post type (open_list) and fetch the attachments from the children posts.

I tried with the function below, but with no luck. But I'm posting it below so that you hopefully can understand better what I'm after...

function new_default_content($content) {
global $post;
if ($post->post_type == 'open_list') {
$children = get_children(array(
'post_parent' => $post->ID,
'post_status' => 'inherit',
'post_type' => 'attachment' // I have also tried with user_images here
));
if ( !empty( $children )){
foreach ( $children as $attachment_id => $attachment ) {
$url = wp_get_attachment_url( $attachment->ID, false );
$content_attach .= '<a href="' . $url . '" download="' . $url . '"> ' . $title . '</a>';
}
}

$content .= $content_attach;
}
return $content;
}
add_filter('the_content', 'new_default_content');


<strong>Edit: </strong>The only contents of every post is an image, a title and some assigned categories. So it might work to for instance fetch the attachment of every post, but it's important that I can also post the title of each post, like on the first code that I posted.

Thanks!

// Jens.

Answers (2)

2015-09-29

Andrea P answers:

I have to say that I am not sure about your posts parent->child relationship, cause I am not sure that you can set a post from a different post type, to be a parent of a post.

but in general I have understood that you want to edit the content of the parent post, so that the other plugin can hook the images in it.
the problem with the approach of your second code is that the_content hook is acting only when displaying, so that the actual content is intact and you just add something right before printing on the page. your plugin is probably acting earlier on, and so it doesn't find the images.

with this in mind, I think you should use the "save_post" hook, so that every time you update the parent post, the filter will rebuild the post content, by grabbing all the featured images from the children.

just as a first (quite blind) attempt, you should use something like this code (in functions.php):


<?php

add_action( 'save_post', 'rewrite_content_based_on_children', 10, 3 );

function rewrite_content_based_on_children($post_id, $post, $update){

// If this isn't our post_type, don't go further
if ( 'open_list' != $post->post_type ) {
return;
}

// retrieve the children
$args = array (
'parent' => $post_id,
'posts_per_page' => '-1',
'post_type' => 'user_images',
'post_status' => 'publish',
'orderby' => array('meta_value_num' => 'DESC', 'date' => 'DESC'),
);

// The Query
$child_query = new WP_Query( $args );

// The Loop
$counter = 0;
$new_content = "";
if ( $child_query->have_posts() ) :
while ( $child_query->have_posts() ) : $child_query->the_post();
$counter++;
$class = 'wp-image-'.get_the_ID();
unset($thumb);
$thumb = get_the_post_thumbnail("large", array("class" => $class));
$new_content .= '<h2>#' . $counter . '.' . get_the_title() . '</h2>' . $thumb .'<br/>' ;
endwhile;
endif;

// if we have found images, update the content
if ( !empty($new_content) ){
// unhook this function so it doesn't loop infinitely
remove_action( 'save_post', 'rewrite_content_based_on_children', 10, 3 );
// update the post, which calls save_post again
wp_update_post( array( 'ID' => $post_id, 'post_content' => $new_content ) );
// re-hook this function
add_action( 'save_post', 'rewrite_content_based_on_children', 10, 3 );
}

}


Jens Filipsson comments:

Yes, it is possible to use a custom post type as parent to another custom post type, I have a working example. The first code actually works, but since the plugin listens to the_content, it's not working.

Problem is, I have a custom field on every post, with a voting function that is used to order the images in a list. Every list item is a child custom post type.

This is why I need to fetch the children.


Andrea P comments:

so basically what you need is to place the featured images from the children posts, into the content of the parent post, is this correct?

or do you need something else?

because the above code should update your parent post content (post type 'open_list' ), every time you click "save" on a post of that type.
and it will loop all its children from the post type 'user_images', and for each of them, it will add a string into the parent content, displaying the counter, the children post title, and its featured image.


Jens Filipsson comments:

Yes, this is great!

But will I still be able to order the children by a custom field value? You can say that the images "compete" and are ordered based on the number of votes they get, stored in a custom field. So it has to be dynamical, since the visitors can change the scores by voting on each image (post)


Jens Filipsson comments:

I'm sorry if I provided too little information, it's a bit hard to explain all parts in a bit complex project like this :)


Jens Filipsson comments:

Basically, the ideal thing would be to have like an extra query, a bit like my first code snippet, where I can modify what's fetched, and then apply to the end of the_content.

Not sure if that's possible?


Andrea P comments:

the above code will query the childs and order them, and then print them into the content in the order they had when you clicked "save" on the parent post.

so, no, the list in the parent won't change order till you actually click again "update" within the parent post editor..

but honestly, I'm thinking that there might be a much easier solution..
I mean, why do you need the list to be actually printend in the content?

can't you just create a single-open_list.php (template file which display the single posts from the post type open_list) add a sub-loop which will grab the children and display the image in the correct order? basically using your first loop..

you talked about a plugin which " apply some things on images inside the_content". which plugin is this? what is it doing exaclty?


Jens Filipsson comments:

Actually Andra, your last post here pointed me in the right direction. When adding the image to the post content of the children post, I actually can get the plugin to work on the image.

Thanks a lot for making me see clear. Will vote the award to you! (easiest 20 bucks ever?)

2015-09-29

dimadin answers:

Well, it is not clear to me what you want to do.

In the first code snippet, you have WP_Query loop where you list titles and featured images (post thumbnails) of all child 'user_images' posts of current post. I believe that this code goes somewhere for singular view.

In second code snippet, you modify 'the_content' filter output to list links to 'attachment' child posts.

I don't see how are those two related since you are not using 'the_content' filter anywhere in the first snippet. To better clarify, you should list step by step tutorial what is and how listed on page you want to display this.

(By the way, in second code snippet, before if ( !empty( $children )){ line, you should place something like $content_attach = ''; because $content_attach isn't defined anywhere.)


Jens Filipsson comments:

I need to create something like the first code snippet, but add it to the_content on the open_list post type.

As I write:

<em>The problem with is that these images is fetched outside the_content, which makes the plugin I mentioned before useless.</em>


Jens Filipsson comments:

To be a bit more clear:

I want to fetch images form the child posts as if they were part of the parent post, by adding them to the_content. If possible, it would be awesome to have the image id attached as a class (wp-image-IMAGE_ID_HERE)


Jens Filipsson comments:

And the second code was just a bad attempt, but kept it so that you could see what I was aiming for...


dimadin comments:

OK, lets try like this.

- You loop through all posts of 'user_images' post type (that are children of some other posts, not understandable which one of which post type)
- Below each of those 'user_images' posts, you want to list all posts of 'attachment' post that are children of that post

If it is not like this, flow that you have, because it is still confusing. For example, we don't what is relationship of 'user_images' and 'open_list' post type etc.


Jens Filipsson comments:

As I write above:

<em>I have a parent post of one custom post type (open_list), and children to this post from another custom post type (user_images).</em>

So the <strong>parent</strong> is the <em>open_list</em> post, and the <strong>children</strong> are <em>user_images</em>.

We need to loop through the user_images post type that are children to the current post parent (open_list) and display the image and title from this post.

There will only be one image for every post if that helps.


dimadin comments:

OK, I am getting this part and first code snippet will do this.

But, if I understood, you need to pass that image to 'the_content' filter so that it can be used by another plugin which then modifies images.

If this is case, have you this: instead of line

the_post_thumbnail('large', array('class' => 'alignnone wp-image'));

to use line like this?

echo apply_filters( 'the_content', get_the_post_thumbnail('large', array('class' => 'alignnone wp-image')) );


Jens Filipsson comments:

Yes, I need to add the images to the_content with a filter. Not sure how the code would look like though?


dimadin comments:

Have you tried previous code that I have posted?

Code example that I have posted triggers 'the_content' filter so all of registered callback functions are used. In that filter, only string is passed, and if any function needs to access post data, global post is used, and since you are placing it in a WP_Query it should have proper post variable.