Displaying every image from a WordPress post - php

The goal is to have wordpress spit out or echo all of the images from a custom post format I've created. I'm new to PHP and I am not looking to use any 3rd party plugins, maybe a fix to the code provided below please.
All of the solutions I've came across from here (stackoverflow) or from google does not work or spits out ALL of the images I've ever uploaded from the media library, which I do not want. Most solutions provided are for "display the first image" which I know of and works, but I would like all of the images from a post.
Here's the closest code that sort of worked a couple of times but it deforms my layout, then goes back to displaying one image:
function displayPostImg() {
global $post, $posts;
$first_img = '';
ob_start();
ob_end_clean();
$output = preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches);
$first_img = $matches[0][0];
return $first_img;
}
And the call I use to paste into my custom post php:
<?php echo displayPostImg(); ?>
As stated above, existing solutions do not work. Any help with a clear explination of what I am doing wrong will be a massive help.
EDIT
#corvidism Thanks for the further explanations man. I did have a look in the dev tools and the "return implode" seems to be taking it OUT of the loop, causing the layout issue. Your solution does show the post images/attachments I am after but I can't seem to fix this unfortuntaly. There seems to be this go to solution that's meant to do the same thing. This sadly echoes every image from the media library. Combining your code with this one below has gotten me close but if I come across a solution, I'll post it here for others:
$args = array(
'post_type' => 'attachment',
'posts_per_page' => -1,
'post_status' =>'any',
'post_parent' => $post->ID );
$attachments = get_posts( $args );
if ( $attachments ) {
foreach ( $attachments as $attachment ) {
echo apply_filters( 'the_title' , $attachment->post_title );
the_attachment_link( $attachment->ID , false );
}
}
EDIT #2: Solution
After messing around with various solutions, I found something that works. Try it out:
function grab_those_images( $post ) {
$content_post = $post->post_content;
$search_post = '~src="[^"]*"~';
preg_match_all( $search_post, $content_post, $imgs );
$no_of_pics = count($imgs[0]);
if ( $no_of_pics > 0 ) {
for ( $i=0; $i < $no_of_pics ; $i++ ) {
$string=$imgs[0][$i];
$string=trim( $string );
$length=strlen( $string );
$image_path=substr_replace( substr( $string, 5, $length ),"",-1 );
echo '<img src="';
echo $image_path;
echo '" />';
}
}
}

The function you're using contains buffer manipulation functions (ob_start() and ob_end_clean()), which and are most likely conflicting with something else in your template (probably something that's also using them, usually plugins).
Unless you're also searching for images inserted as post meta (which I assume you're not), you will find all images in a post inside the $post->post_content property. You can use preg_match_all on it to find the images.
You should pass the post content to your function as a parameter instead of accessing the global $post object. This will make things more reliable and easier to debug. (Global objects are generally frowned upon in PHP development, which is something to keep in mind if you plan to use PHP more generally than just for WordPress.)
This is how your function could look:
function getAllImagesInPost($postContent) {
preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $postContent, $matches);
// This regex function searches for <img> tags and uses a capture group
// for the image source url. It will search the whole supplied string,
// in this case post content. It returns results into the $matches variable.
$image_tags = $matches[0];
// This is an array containing all the regex matches.
$image_urls = $matches[1];
// This is an array containing all the capture group matches.
return implode('',$image_tags);
// implode() creates a string from an array of strings/numbers.
}
In your template file, the usage depends on whether or not you're in the loop. In the loop you can work with the $post object and use either $post->post_content or get_the_content() (both will get you the post content as a string):
echo getAllImagesInPost(get_the_content());
Outside of the loop you will first need to get the post (e.g. get_post($somePostID);).
Addition 1:
You must pass a variable to the function, so you can't use WordPress template functions such as the_content(). These echo directly to the page and return true or something else useless (in this case, anyway). General WP rule is that if it starts with the_ it echoes, if it starts get_the_ it returns.
Addition 2:
To display only the images from your post and no other content, you simply don't use any other content template tag in your template file. (E.g. no the_content()).
Addition 3:
I suspect your problem isn't caused by the function itself but by how/where you're calling it. But if this function does cause changes in your layout, it's 99% the regex returning broken HTML (not likely but possible, depending on your input).
The way to debug this is to inspect the page with browser dev tools and look for broken tags or other weirdness. If you see that, you need to find what exactly happens by testing the function on various input. Feed it a hard-coded string, make a test post with just text/image/anything else, until you know what's happening. If you determine that the regex is the culprit, you can try fixing it yourself or search the internet for a better one (no judgement, regex is pain).

Related

Fixing Mismatched Image Class in Existing Posts

After migrating my wordpress site, I found out that the image class of some of my images in the existing posts are mismatched. However, I am not able to figure out any automated method to fix the issue.
As we all know, when an image is inserted in a post, wordpress would assign an image class and generate some markups automatically like this:
<img class=" size-full wp-image-YYYYY aligncenter" src="https://......XXXXX.jpg">
which the YYYYY in the “wp-image-” code is exactly the ID of the image.
However, in my site, probably due to some errors occurred during migration, the image ID of some of my images are off by a bit. For example, the original image ID 10000 is now 10002 in my new site. However, in the post content, the markup of the image is still wp-image-10000. This creates a problem that the image class associated is mismatched from the correct image id, and the images are such not responsive.
The obvious fix of this problem is to update the wp-image-YYYYY code to the correct image ID in the posts (i.e. changing wp-image-10000 to wp-image-10002). Or else, I could just reinsert the image into the post and wordpress would reassign a correct image class accordingly. However, given that I have hundreds of existing posts and thousands of existing images, it is not possible for me to check if the image class of each image is correct manually.
While I don't know anything about coding, I have tried to run the code in the below website, and tried to twist the code from if ( !$has_class ) to if ( $has_class ) to fit my scenario, which it does not work at all:
https://letswp.io/add-attachment-id-to-the-class-of-wordpress-images/
I would be very grateful if someone could provide an automated solution to my problem. Thank you very much.
From the code mentioned in the link, you can make more tweaks that my fix your issue, since you do not need to append but rather replace the class.
function lwp_attachment_id_class( $attr, $attachment ) {
$class_attr = isset( $attr['class'] ) ? $attr['class'] : '';
$has_class = preg_match(
'/wp\-image\-[0-9]+/',
$class_attr,
$matches
);
// Check if the image is missing the class
if ( $has_class ) {
$new_class = sprintf( ' wp-image-%d', $attachment->ID );
foreach($matches as $match)
$attr['class'] = str_replace($match, $new_class, $attr['class']);
}
return $attr;
}
add_filter(
'wp_get_attachment_image_attributes', 'lwp_attachment_id_class', 10, 2
);

WordPress - Overwriting/Filtering get_header_image_tag

I want to change the output for get_header_image_tag function to output the exact HTML that I want to. I also want to be able to add data to the output such as new srcset that have not been covered...
I have tried to use apply_filters get_header_image_tag to test it out but couldn't get it to work:
apply_filters('get_header_image_tag', "<img src>", get_custom_header(), ['url' => 'test']);
echo get_header_image_tag();
I am pretty convinced that my understanding of how the apply_filters works might be the issue there... I've been reading about it but I can't get my head around the parameters. Most of the examples I have found online used only a hook and a single value.
The way I understood it, I want the output to be <img src=url> by using the data in get_custom_header() and replacing the URL attribute with 'test'.
However, what is being outputted is the default get_header_image_tag. I've also tried to directly echo the apply_filters:
echo apply_filters('get_header_image_tag', "<img src>", get_custom_header(), ['url' => 'test']);
But then, only <img src> is outputted...
You are totally right, it is your understanding on how to use wordpress filters that is the issue :)
You are applying a filter when using apply_filters(). To add your own filter to the get_header_image_tag hook you have to use add_filter(). Here is an example on how adding a filter should look like:
// define the get_header_image_tag callback
function filter_get_header_image_tag( $html, $header, $attr ) {
// make filter magic happen here...
return $html;
};
// add the filter
add_filter( 'get_header_image_tag', 'filter_get_header_image_tag', 10, 3 );
Here is an example on how you can control the full output of get_header_image_tag:
function header_image_markup($html, $header, $attr) {
return '<figure><img src="'.$attr['src'].'" width="'.$attr['width'].'" height="'.$attr['height'].'" alt="'.$attr['alt'].'" srcset="'.$attr['srcset'].'" sizes="'.$attr['sizes'].'"></figure>';
}
add_filter('get_header_image_tag', 'header_image_markup', 20, 3);
But, what version of WP are you using? I'm pretty sure srcset is supported in the get_header_image_tag() as it appeared when I was using it just now.

Push metadata in array wordpress

Applying meta keys in search result
Since I need to take on a different approach to get my data in javascript from wordpress, I am trying to apply (as follow up on my post earlier today (https://stackoverflow.com/questions/34873986/javascript-for-each-custom-post-type-wordpress)) metadata to my query so it will spit out the right information. This is practically harder than I thought, cause I preferly want it in one query. I been googling now for quite a while, cause I had hoped I wasn't the only one with this problem. I cant seem to find a relevant answer to my problem
Case
Since I was being pointed to the fact javascript and php dont play nice, I was beginning to explore a different way. It requires me to get the results on forehand before I push this into javascript via a json_encode. So far this is running fine, except for one tiny thing. When asking in WP_query I cant get any meta data, which is the part I really need, since that contain map information for my google maps. So is there a way I can query that before I push this through?
<?php
$args = array(
'post_type' => 'hotels',
);
$query = new WP_Query( $args );
echo '<pre>';
print_r($query->posts);
echo '</pre>'
?>
<script type="text/javascript">
var post_info = <?php echo json_encode($query->posts); ?>;
<script>
So far I managed to check what is been given, but I sume, I cant get this via wp_query. Is there another way to actually get the data I need? Or is there a way I can push the meta data in the array with each single post, so I can acces it in Javascript?
Are you looking for get_post_meta() ? https://developer.wordpress.org/reference/functions/get_post_meta/
But you will have to call get_post_meta on each post :/
EDIT :
<?php
foreach($query->posts as $post) {
$post->meta = get_post_meta($post->ID);
}
?>

wordpress php str_replace function with variables not quite there

I'm pretty new to PHP so perhaps lacking some basics so here goes.
For WordPress I've a function for replacing some text from a TablePress table. The function worked fine when I used code along these lines:
function replace_stuff($text) {
if (is_front_page() || is_page('2611') || is_child('2611')) {
$replace_magic = array(
//text to search => text to replace
'dog' => 'cat',
'mouse' => 'elephant'
);
}
$text = str_replace(array_keys( (array)$replace_magic), $replace_magic, $text);
return $text;
}
add_filter('tablepress_table_output', 'replace_stuff');
So in that example dog would be displayed on the frontend as cat & mouse as elephant.
But now I would like to complicate things & create the strings to replace by querying fields from all posts in a custom post type "drivers".
I have come up with something like this, with the aim of finding any text that matches the post title & replacing with text from a custom field (of all posts from my 'drivers' custom post type), but it doesn't do anything!
function replace_stuff($text) {
if (is_front_page() || is_page('2611') || is_child('2611') || get_post_type() == 'drivers') {
query_posts('post_type=drivers');
if (have_posts()) :
while (have_posts()) : the_post();
$profilenat = get_post_meta($post->ID, 'driver_nationality', true);
$profiletitle = get_the_title();
$replace_magic = array(
//text to search => text to replace
$profiletitle => $profilenat
);
endwhile;
endif;
}
$text = str_replace(array_keys( (array)$replace_magic), $replace_magic, $text);
return $text;
}
add_filter('tablepress_table_output', 'replace_stuff');
Could anyone advise me please?
Many thanks.
Firstly I think you need to replace
$replace_magic = array(
with
$replace_magic[$profiletitle] = $profilenat
Currently, if everything else works, then for every driver you are completely replacing the contents of $replace_magic with a new array, which just has that driver's details. Instead you want to add a new item to the existing array.
Going further, with this sort of problem it can be really useful to do some quick debugging to help you narrow down where the problem might be. So here it would be useful to know if the problem is really with your str_replace, or if it's actually with the code above it.
Debugging in Wordpress is worth a read, and having done that you can use error_log to output some details to debug.log inside your wp-content directory.
Before your str_replace, doing
error_log(print_r($replace_magic));
Would tell you if your query loop has worked as you intended or not.
If it hasn't, you might then put a log statement inside the loop. This will tell you if the loop contents are being executed at all (in which case the problem is with your code inside the loop), or not (in which case the problem may be with your query).
Additionally, if you haven't already I would recommend checking the WordPress Codex on query_posts. query_posts manipulates the main Wordpress query, and may give you some really unexpected results used inside a filter like this. At least consider WP_Query - and check the note about wp_reset_posts.
Hope that helps - apologies if some of it is stuff you already considered, but as you mentioned you're quite new to PHP I hope it's useful.

Word count not showing on posts?

I thought it might be an issue with a plugin I'm running, but I'm not seeing a word count on any of my posts on WP 4.0. I've deactivated all plugins, and that hasn't fixed me.
Well, not seeing is probably not very accurate - word counts are all 0, even on posts I've written pre-4.0. I'm running roughly latest PHP5.5 and MySQL 5.5 on the server, if that's at all relevant. The database looks fine on the surface, so am I missing something obfious?
You've noted that this is to be used on the frontend of the site, so you can achieve it without the use of a plugin.
Place the following code in your functions.php file:
function word_count() {
$content = get_post_field( 'post_content', $post->ID );
$word_count = str_word_count( strip_tags( $content ) );
return $word_count;
}
You can then use the function word_count() in your theme. word_count() returns the word count of the post, so you'll need to echo it out:
<?php echo word_count(); ?>

Categories