I have a widget that retrieves and displays the latest comments for a WordPress site. It displays the comment author, Gravatar, comment and date / time.
The function to display the comments is in a class.
The issue that I am having is that whenever i display this widget it messes up or conflicts with the number of comments that are returned for my WordPress theme.
Example. In the widget choose to display 5 comments. On a page on the site I have a post that has 8 comments. When the widget is enabled only 6 of those 8 comments are displayed.
If I disable the widget, all the comments display.
This is the function to display the comments
/**
* Retrieves the latest comments
*
* Shows a list of latest comments ordered by the date added
*
* #param int $limit - The number of posts to display
* #param int $chars - The number of characters to display for the post body
* #param int $size - Size of the comment Gravatar
* #param boolean $displayCommentsIcon - Whether to display the comment Gravatar
*
*/
public function aaw_get_latest_comments($display_comments_icon = true, $comments_icon_size = 50, $comments_amount = 5, $comments_chars = 35, $display_comments_date = true) {
global $comments;
$com_excerpt = '';
$aaw_comments = get_comments(array('number' => $comments_amount, 'status' => 'approve'));
if($aaw_comments){
foreach((array)$aaw_comments as $aaw_comment){
if($comments_chars > 0) {
$com_excerpt = self::aaw_snippet_text($aaw_comment->comment_content, $comments_chars);
}
echo '<li>';
if($display_comments_icon == 'true'){
echo '<a href="'.esc_url(get_comment_link($aaw_comment->comment_ID) ).'" title="'. __('Commented on: ', $this->hook). $aaw_comment->post_title.'">';
echo get_avatar($aaw_comment, $comments_icon_size);
echo '</a>';
}
echo '<div class="aaw_info">';
echo '<a href="'.esc_url(get_comment_link($aaw_comment->comment_ID) ).'" title="'. __('Commented on: ', $this->hook). $aaw_comment->post_title.'">';
echo '<i>'.strip_tags($aaw_comment->comment_author).'</i>: '.strip_tags($com_excerpt).'...';
echo '</a>';
if($display_comments_date == 'true'){
echo '<span class="aaw_meta">'.get_comment_date('j M Y',$aaw_comment->comment_ID).' '.__('at', $this->hook).' '.get_comment_date('g:i a',$aaw_comment->comment_ID).'</span>';
}
echo '</div>';
echo '</li>';
}
} else {
echo '<li>'.__('No comments available', $this->hook).'</li>'."\n";
}
}
This is how I call the function:
<?php $advanced_activity_widget->aaw_get_latest_comments($display_comments_icon == 'true' ? 'true' : 'false', $comments_icon_size, $comments_amount, $comments_chars, $display_comments_date == 'true' ? 'true' : 'false'); ?>
At first I thought is was the Gravatar causing the conflict however I removed it and it didn't make a change.
Any help would be greatly appreciated.
Thanks
EDIT:
It seems to be the get_comment_link() that is causing the problems.
If I remove both instances of that function call the widget and comments display fine.
I have tried: wp_reset_postdata(); wp_reset_query(); rewind_posts(); all to no effect.
Try adding a call to wp_reset_query() after your foreach loop.
http://codex.wordpress.org/Function_Reference/wp_reset_query
Related
I have a custom checkbox field created in Wordpress where the user can select various facilities available at a listed property.
I am building a page template using Elementor.
When I import the data from ACF, it displays as a comma separated list.
Is there any way I can instead get this to display as as a bulleted list?
Here is a code to get the output data from ACF as a bulleted list -
<?php
$arr = get_the_field('field_name');
$str = explode (",", $arr);
echo '<ul>';
foreach($str as $s){
echo '<li>'.$s.'</li>';
}
echo '</ul>';
?>
I hope this is what you are looking for.
You could try using a plugin that let's you create php code snippets and run them with a shortcode such as this: https://it.wordpress.org/plugins/insert-php/
Once you created the php snippet you could try to run it with a shortcode using Elementor's shortcode widget.
I'd slightly adjust Tahmid's excellent answer. In order to allow for empty lines (without a bullet) use this in you functions.php file:
/**
* create a ACF text field with bullets
* Empty lines stay empty
* #param string $field_name Name of the field to bullet
*/
function acf_bullets(string $field_name): void {
$format_acf_bullet = function(
string $value,
int $post_id,
array $form ):string {
if( empty($value) ) {
return '';
}
$lines = explode( "\n", $value );
$result = "<ul class=\"theme-ul\">\n";
foreach( $lines as $line) {
if( strlen($line)<=1 ) { // empty line, start a new list
$result .= "</ul><p/><ul class=\"theme-ul\">\n";
} else {
$result .= "<li>".$line."\n";
}
}
$result .= "</ul>\n";
return $result;
};
add_filter("acf/format_value/name=$field_name", $format_acf_bullet, 10, 3);
}
Call this with acf_bullets('your-fieldname-here');
Trying to figure out how I can completely exclude a category from an infinite loop code i found here: http://wplancer.com/infinite-next-and-previous-post-looping-in-wordpress/. There are some clues in the comments but i'm not sure how to actually integrate it into the code correctly. I've tried adding the category ID I want to exclude in this line, eg 'get_adjacent_post(false, '5', true')' but it doesn't seem to have any impact. Thanks in advance for any assistance!
<?php
/**
* Infinite next and previous post looping in WordPress
*/
if( get_adjacent_post(false, '', true) ) {
previous_post_link('%link', '← Previous Post');
} else {
$first = new WP_Query('posts_per_page=1&order=DESC'); $first->the_post();
echo '← Previous Post';
wp_reset_query();
};
if( get_adjacent_post(false, '', false) ) {
next_post_link('%link', 'Next Post →');
} else {
$last = new WP_Query('posts_per_page=1&order=ASC'); $last->the_post();
echo 'Next Post →';
wp_reset_query();
}; ?>
Managed to solve this by installing this plugin: https://wordpress.org/plugins/ambrosite-nextprevious-post-link-plus/ and then using the URL query style string code found on this page: http://www.ambrosite.com/plugins/next-previous-post-link-plus-for-wordpress
Final code looked like this (make sure you have the plugin installed or it won't work):
<?php previous_post_link_plus('order_by=post_date&meta_key=&loop=1&thumb=0&max_length=0&in_same_cat=0&ex_cats=24,11,10,8,9,12&ex_cats_method=strong&num_results=1&echo=1'); ?>
<?php next_post_link_plus('order_by=post_date&meta_key=&loop=1&thumb=0&max_length=0&in_same_cat=0&ex_cats=24,11,10,8,9,12&ex_cats_method=strong&num_results=1&echo=1'); ?>
I created a filter that modifies the_title() of a post, but the problem I'm having is that it's modifying every instance of the_title(). I got most of the problem sorted out with the in_the_loop() function, however any theme that has "next post" "previous post" navigation links within the loop are still having the filter applied (understandably so). How can I apply the filter to only the the_title() of the current post?
function xyz_the_title( $the_title ) {
if( !in_the_loop() )
return $the_title;
$location = get_post_meta( get_the_ID(), 'location', true );
$the_title .= ' - ' . $location;
return $the_title;
}
add_filter( 'the_title', 'xyz_the_title' );
do it with jQuery
Something like this should do the trick:
$(document).ready(function() {
$('#entry-header').text(function(i, oldText) {
return oldText === 'Popular Science' ? 'New word' : oldText;
});
});
This only replaces the content when it is Popular Science. See text in the jQuery API.
Rather than filtering the_title you could edit your template file instead and append the location to your returned the_title().
echo "<h1>" . get_the_title() . " - " . $location . "</h1>";
Ran into a similar situation and was hoping this thread could save me...
Anyways this is what I managed to do thus far in
add_filter( 'the_title', function( $title, $id ){
/**
* don't run in the backend
*/
if( is_admin() ) {
return $title;
}
/**
* invalid values received
*/
if( empty( $title ) || $id < 1 ){
return $title;
}
global $post;
if ( ! $post instanceof WP_Post ){
return $title;
}
/**
* PREVENTATIVE MEASURE...
* only apply the filter to the current page's title,
* and not to the other title's on the current page
*/
global $wp_query;
if( $id !== $wp_query->queried_object_id ){
return $title;
}
/**
* Don't run this filter if wp_head calls it
*/
if( doing_action( 'wp_head' ) ){
return $title;
}
return 'MODIFIED - '.$title;
});
Here are the shortfalls:
If you have the same post being displayed on the current page, somewhere else, it's gonna modify THAT post title as well
Currently thinking about having a look at the call stack to detect if the call is coming from the theme...
but I would suggest you find another solution bud...
Ah, didn't know it was for a plugin. In which case, I think you should be ok to use if_filter then. This checks whether the filter has been run x times on the page in question. So, we check if it has run once on the page and if so it won't run again. Also, I have assumed you only want this to run on single post pages. This is untested.
function xyz_the_title( $the_title ) {
if( is_single() AND did_filter('the_title') === 1 ) {
if( !in_the_loop() )
return $the_title;
$location = get_post_meta( get_the_ID(), 'location', true );
$the_title .= ' - ' . $location;
return $the_title;
}
}
add_filter( 'the_title', 'xyz_the_title' );
I am coding a plugin and I use a short code to render a page content. I want to change the page title. I used this:
// Change the title of the page of the charts to add the current month.
add_filter('the_title', 'charts_title', 10, 2);
function charts_title($title, $id) {
$title .= ' ' . date('F Y');
return $title;
}
But it does that for all the posts and pages. Can I do that only for the pages that contains the short code I created ? I tried to do that, but it doesn't work.
add_shortcode('charts-vote', 'charts_vote');
function charts_vote($atts) {
// Add the filter only in the short code function callback.
add_filter('the_title', 'charts_title', 10, 2);
// ... //
return $content;
}
Can someone please help me ?
I understand that the specifics of your set up may require checking for the Shortcode, but maybe a Custom Field could be used for that:
add_filter( 'the_title', 'charts_title_so_15312385', 10, 2 );
function charts_title_so_15312385( $title, $post_id )
{
// Admin area, bail out
if( is_admin() )
return $title;
// Custom field not set, bail out
$mod_title = get_post_meta( $post_id, 'mod_title', true );
if( !$mod_title )
return $title;
// Ok, modify title
$title .= ' ' . date( 'F Y' );
return $title;
}
The Shortcode could even "talk" with the Custom Field for extended configurations.
For ease of use, you could make a Custom Meta Box or use a plugin like Advanced Custom Fields.
Hello i have a website and a blog, i want to display my self hosted wordpress blog on my website.
I want to show only 3 post on my website.
I want to automatically check for any new post everytime when i reload my website, so that the recent three gets displayed only.
I want to show the complete title of my wordpress blogpost but specific letters of description.
Also the description should end up with a word not some piece of non-dictionary word ending with "..."
How this can be done, i have heard that it can be done through RSS.
Can somebody help me?
To accomplish this you need to read the RSS of the blog, from RSS you need to read the Title and the description, after reading the whole description and title you need to trim the description to your desired number of letters. After that you need to check weather the description last word has been completed or not and then you need to remove a the last word if not completed and put the "...".
First we will make a script to trim the description and to put "..." in last:-
<?php
global $text, $maxchar, $end;
function substrwords($text, $maxchar, $end='...') {
if (strlen($text) > $maxchar || $text == '') {
$words = preg_split('/\s/', $text);
$output = '';
$i = 0;
while (1) {
$length = strlen($output)+strlen($words[$i]);
if ($length > $maxchar) {
break;
}
else {
$output .= " " . $words[$i];
++$i;
}
}
$output .= $end;
}
else {
$output = $text;
}
return $output;
}
Now we will define the variables in which we store the values:-
$xml=("http://your-blog-path/rss/");
global $item_title, $item_link, $item_description;
$xmlDoc = new DOMDocument();
$xmlDoc->load($xml);
$x=$xmlDoc->getElementsByTagName('item');
Now, we will make an array and store values in it. I am only taking 3 because you have asked it the way. You can change it to anything (The number of post you want to show, put that in the loop)
for ($i=0; $i<3; $i++)
{
$item_title[$i] = $x->item($i)->getElementsByTagName('title')->item(0)->childNodes->item(0)->nodeValue;
$item_link[$i] = $x->item($i)->getElementsByTagName('link')->item(0)->childNodes->item(0)->nodeValue;
$item_description[$i] = $x->item($i)->getElementsByTagName('description')->item(0)->childNodes->item(0)->nodeValue;
}
?>
Now echo all these values, Link is the value where your user will click and he will be taken to your blog:-
FIRST RECENT POST:
<?php echo $item_title[0]; ?>
<?php echo substrwords($item_description[0],70); ?>
SECOND RECENT POST:
<?php echo $item_title[1]; ?>
<?php echo substrwords($item_description[1],70); ?>
THIRD RECENT POST:
<?php echo $item_title[2]; ?>
<?php echo substrwords($item_description[2],70); ?>
Hope this can solve your problem. By the way Nice question.
Click here for the original documentation on displaying RSS feeds with PHP.
Django Anonymous's substrwords function is being used to trim the description and to insert the ... at the end of the description if the it passes the $maxchar value.
Full Code:
blog.php
<?php
global $text, $maxchar, $end;
function substrwords($text, $maxchar, $end='...') {
if (strlen($text) > $maxchar || $text == '') {
$words = preg_split('/\s/', $text);
$output = '';
$i = 0;
while (1) {
$length = strlen($output)+strlen($words[$i]);
if ($length > $maxchar) {
break;
} else {
$output .= " " . $words[$i];
++$i;
}
}
$output .= $end;
} else {
$output = $text;
}
return $output;
}
$rss = new DOMDocument();
$rss->load('http://wordpress.org/news/feed/'); // <-- Change feed to your site
$feed = array();
foreach ($rss->getElementsByTagName('item') as $node) {
$item = array (
'title' => $node->getElementsByTagName('title')->item(0)->nodeValue,
'desc' => $node->getElementsByTagName('description')->item(0)->nodeValue,
'link' => $node->getElementsByTagName('link')->item(0)->nodeValue,
'date' => $node->getElementsByTagName('pubDate')->item(0)->nodeValue,
);
array_push($feed, $item);
}
$limit = 3; // <-- Change the number of posts shown
for ($x=0; $x<$limit; $x++) {
$title = str_replace(' & ', ' & ', $feed[$x]['title']);
$link = $feed[$x]['link'];
$description = $feed[$x]['desc'];
$description = substrwords($description, 100);
$date = date('l F d, Y', strtotime($feed[$x]['date']));
echo '<p><strong>'.$title.'</strong><br />';
echo '<small><em>Posted on '.$date.'</em></small></p>';
echo '<p>'.$description.'</p>';
}
?>
You can easily put this in a separate PHP file (blog.php) and call it inside your actual page.
Example:
social.php
<h3>Latest blog post:</h3>
<?php require 'blog.php' ?>
Also, this code is plug-n-play friendly.
Why not use the Wordpress REST API to retrieve posts -
API URL is : https://public-api.wordpress.com/rest/v1/sites/$site/posts/
where $site is the site id of your wordpress blog
or else simply use this plugin -
http://www.codehandling.com/2013/07/wordpress-feeds-on-your-website-with.html