I'm still pinned against wordpress it seems. I added the widget 'Archives' to my sidebar and once more, the html output is crap, it basically has this structure:
<li>text - (# of posts)</li>
I want to transform it into:
<li>text <small># of posts</small>
Unlike with plugins however, I wasn't able to find the line that creates the html output in the php pages suggested/mentioned by the wordpress community, namely functions.php, widgets.php and default-widgets.php
I've googled every possible keyword combination on the matter and I was unable to find something relevant.
All help is appreciated
Regards
G.Campos
Check out general-template.php. Two functions wp_get_archives and get_archives_link. You'd have to hack wp_get_archives to change what gets loaded in $text. The post count gets loaded into the $after variable which placed outside the link in get_archives_link. Instead of this:
$text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($arcresult->month), $arcresult->year);
if ( $show_post_count )
$after = ' ('.$arcresult->posts.')' . $afterafter;
something like this:
$text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($arcresult->month), $arcresult->year);
if ( $show_post_count )
$text= $text.' <small>'.$arcresult->posts.'</small>';
That's just for the Monthly archive. You'd have to make modifications on the Yearly, Weekly and Daily blocks.
Edit: Easiest way to exclude the <small> element from the link's title is to load it up in a separate variable in each block and then pass it into a modified get_archives_link. In the example above, right after $text gets loaded up just load that value into $title:
$text = sprintf(__('%1$s %2$d'), $wp_locale->get_month($arcresult->month), $arcresult->year);
$title = $text;
if ( $show_post_count )
$text= $text.' <small>'.$arcresult->posts.'</small>';
$output .= get_archives_link($url, $text, $format, $before, $after, $title);
Then modify get_archives_link:
function get_archives_link($url, $text, $format = 'html', $before = '', $after = '', $title = '') {
$text = wptexturize($text);
if($title == '')
$title = $text;
$title_text = esc_attr($title);
$url = esc_url($url);
if ('link' == $format)
$link_html = "\t<link rel='archives' title='$title_text' href='$url' />\n";
elseif ('option' == $format)
$link_html = "\t<option value='$url'>$before $text $after</option>\n";
elseif ('html' == $format)
$link_html = "\t<li>$before<a href='$url' title='$title_text'>$text</a>$after</li>\n";
else // custom
$link_html = "\t$before<a href='$url' title='$title_text'>$text</a>$after\n";
$link_html = apply_filters( "get_archives_link", $link_html );
return $link_html;
}
Add this code inside your theme functions.php file, It will wrap post archive counts inside span tag. In below code example I wrapped counts in span tag, you can add or modify it according to your requirement.
function wrap_archive_count($links) {
$links = str_replace('</a> (', '<span class="archive-count">', $links);
$links = str_replace(')', '</span></a>', $links);
return $links;
}
add_filter('get_archives_link', 'wrap_archive_count');
Related
I am trying to make excerpts end with a sentence, for a specific post type on my website, but for some reason, it is also effecting page excerpts and I cannot understand why.
function vhr_variable_length_excerpt($text, $w_length, $finish_sentence){
global $post;
if ( $post->post_type == 'poi' ) {
//Word length of the excerpt. This is exact or NOT depending on your '$finish_sentence' variable.
$w_length = 20; /* Change the Length of the excerpt. The Length is in words. */
//1 if you want to finish the sentence of the excerpt (No weird cuts).
$finish_sentence = 1; // Put 0 if you do NOT want to finish the sentence.
$tokens = array();
$out = '';
$word = 0;
//Divide the string into tokens; HTML tags, or words, followed by any whitespace.
$regex = '/(<[^>]+>|[^<>\s]+)\s*/u';
preg_match_all($regex, $text, $tokens);
foreach ($tokens[0] as $t){
//Parse each token
if ($word >= $w_length && !$finish_sentence){
//Limit reached
break;
}
if ($t[0] != '<'){
//Token is not a tag.
//Regular expression that checks for the end of the sentence: '.', '?' or '!'
$regex1 = '/[\?\.\!]\s*$/uS';
if ($word >= $w_length && $finish_sentence && preg_match($regex1, $t) == 1){
//Limit reached, continue until ? . or ! occur to reach the end of the sentence.
$out .= trim($t);
break;
}
$word++;
}
//Append what's left of the token.
$out .= $t;
}
return trim(force_balance_tags($out));
}
}
function vhr_excerpt_filter($text){
global $post;
if ( $post->post_type == 'poi' ) {
//Get the full content and filter it.
$text = get_the_content('');
$text = strip_shortcodes( $text );
$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]>', $text);
//If you want to Allow SOME tags:
$allowed_tags = '<p>,<a>,<strong>,<b>'; /* Here I am allowing p, a, strong tags. Separate tags by comma. */
$text = strip_tags($text, $allowed_tags);
//Create the excerpt.
$text = vhr_variable_length_excerpt($text, $w_length, $finish_sentence);
return $text;
}
}
//Hooks the 'vhr_excerpt_filter' function to a specific (get_the_excerpt) filter action.
add_filter('get_the_excerpt', 'vhr_excerpt_filter', 5);
It doesn't effect any of my other custom post types, just the one I specify in the function, and then all pages on the website. It still effects my pages, even if I change the logic to something like = poi && != page as well. Any ideas why this would also be effecting pages? Is there an easier way to make this happen?
Thanks!
There is a multitudes of ways we can approach it. Taking the time to write a custom excerpt instead on relying on Wordpress is one of them...
We can count sentences by targeting end-of-sentence period.
function get_sentence_tally_excerpt( $content = '', $tally = 2, $stitches = '' ) {
$buffer = array_slice( explode( '.', sanitize_text_field( $content ) ), 0, $tally );
$filter = array_filter( array_map( 'trim', $buffer ), 'strlen' );
$excerpt = join( '. ', $filter ) . '.';
return esc_attr( $excerpt . $stitches );
};
You can specify what type of content should be 'truncated' and by how many sentences. On the front-end we can call our function get_tally_excerpt() like so:
<?= get_sentence_tally_excerpt( get_the_content() ); ?> //... 2 sentences by DEFAULT
<?= get_sentence_tally_excerpt( get_the_content(), 1 ); ?> //... 1 sentences ONLY
<?= get_sentence_tally_excerpt( get_the_content(), 5, '[...]' ); ?> //... 5 sentences ONLY with stitches at the end.
I want to highlight the search term in the content result in WordPress.
I tried some functions for title, excerpt and content highlight. Title and excerpt working fine but in content its not working fine. it disturb my content layout.
My actual layout is
And after using function for highlight search term in content. It looks like this
The function which i use title highlight is
function search_title() {
$title = get_the_title();
$keys = implode('|', explode(' ', get_search_query()));
$content = strip_tags($content);
$title = preg_replace('/(' . $keys .')/iu', '<strong class="search-highlight">\0</strong>', $title);
echo $title;
}
And the function which i use for content is
function search_content() {
$content = get_the_content();
$keys = implode('|', explode(' ', get_search_query()));
// $content = strip_tags($content);
$content = preg_replace('/(' . $keys .')/iu', '<strong class="search-highlight">\0</strong>', $content);
$content = preg_replace('~(?:\[/?)[^/\]]+/?\]~s', '', $content);
echo '<p>' . $content . '</p>';
}
Its working fine but break my layout.
I tried some of the jquery methods too. but no luck.
Shaban try this code your search.php and remove search_content() from functions.php
Get the search term by this code.
<?php echo $str = esc_html( get_search_query( false ) ); ?>
and then write jquery in same file with contains: function. like this
$( ".content-column:contains('<?php echo $str ?>')" ).css( "background", "Yellow" );
That's it :)
Hope this will help you
I'm working on a WordPress theme where I need to truncate the post at a certain number of words. I understand how to use the_excerpt(), however this strips out all the paragraph breaks, links, etc. which is NOT the desired effect. I tried using jQuery Succinct and applying that to the_content() -- that maintained the formatting, but it cut off in the middle of a paragraph so I had an open <p> that then broke the rest of the layout. The client does not want to use the option to manually insert a "more" tag into the post.
Is there a way I can do this either via PHP or jQuery?
You have to create your own excerpt function. I have written one that keeps all html tags in tact and also cut the excerpt at the end of a sentence just after the chosen amount of words.
You need to remove the original excerpt filter first and add your new one. Add this to your functions.php
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'pietergoosen_custom_wp_trim_excerpt');
Now add this below
function pietergoosen_custom_wp_trim_excerpt($pietergoosen_excerpt) {
global $post;
$raw_excerpt = $pietergoosen_excerpt;
if ( '' == $pietergoosen_excerpt ) {
$pietergoosen_excerpt = get_the_content('');
$pietergoosen_excerpt = strip_shortcodes( $pietergoosen_excerpt );
$pietergoosen_excerpt = apply_filters('the_content', $pietergoosen_excerpt);
$pietergoosen_excerpt = str_replace(']]>', ']]>', $pietergoosen_excerpt);
//Set the excerpt word count and only break after sentence is complete.
$excerpt_word_count = 75;
$excerpt_length = apply_filters('excerpt_length', $excerpt_word_count);
$tokens = array();
$excerptOutput = '';
$count = 0;
// Divide the string into tokens; HTML tags, or words, followed by any whitespace
preg_match_all('/(<[^>]+>|[^<>\s]+)\s*/u', $pietergoosen_excerpt, $tokens);
foreach ($tokens[0] as $token) {
if ($count >= $excerpt_word_count && preg_match('/[\?\.\!]\s*$/uS', $token)) {
// Limit reached, continue until ? . or ! occur at the end
$excerptOutput .= trim($token);
break;
}
// Add words to complete sentence
$count++;
// Append what's left of the token
$excerptOutput .= $token;
}
$pietergoosen_excerpt = trim(force_balance_tags($excerptOutput));
$excerpt_end = ' ' . ' » ' . sprintf(__( 'Read more about: %s »', 'pietergoosen' ), get_the_title()) . '';
$excerpt_more = apply_filters('excerpt_more', ' ' . $excerpt_end);
$pos = strrpos($pietergoosen_excerpt, '</');
if ($pos !== false)
// Inside last HTML tag
$pietergoosen_excerpt = substr_replace($pietergoosen_excerpt, $excerpt_end, $pos, 0);
else
// After the content
$pietergoosen_excerpt .= $excerpt_end;
return $pietergoosen_excerpt;
}
return apply_filters('pietergoosen_custom_wp_trim_excerpt', $pietergoosen_excerpt, $raw_excerpt);
}
Is it possible to filter out only the shortcode from the post and then run the shortcode?
My page looks like this:
[summary img="images/latest.jpg"]
This here is the summary
[/summary]
Lots of text here...
And i just want to display the shortcode on a specific page.
Tried using regular expressions, but they dont seem to work:
$the_query = new WP_Query('category_name=projects&showposts=1');
//loop
while ( $the_query->have_posts() ) : $the_query->the_post();
echo '<b>';
the_title();
echo '</b>';
echo '<p>';
$string = get_the_content();
if (preg_match("[\\[[a-zA-Z]+\\][a-zA-Z ]*\\[\/[a-zA-Z]+\\]]", $string , $matches)) {
echo "Match was found <br />";
echo $matches[0];
}
echo '</p>';
endwhile;
Any idéas?
EDIT:
Found a temporary solution.
while ( $the_query->have_posts() ) : $the_query->the_post();
$content = str_replace(strip_shortcodes(get_the_content()),"",get_the_content());
echo do_shortcode($content);
endwhile;
I saw that wordpress had a function for striping shortcodes but not for strip content. So i replaced the stripped content string from the whole post to get just the shortcode. The only bad thing about this that the shortcodes have to be in the beginning of the posts.
Better answer is:
$pattern = get_shortcode_regex();
preg_match('/'.$pattern.'/s', $post->post_content, $matches);
if (is_array($matches) && $matches[2] == 'the_shortcode_name') {
$shortcode = $matches[0];
echo do_shortcode($shortcode);
}
It will search through the post content for a shortcode called “the_shortcode_name”. If it finds it, it will store the shortcode in the $matches variable. Easy to run it from there.
I've had the following problems with these answers:
regex pattern not containing all registered shortcode tags
inability to get all shortcodes from the post
.. and my solution is:
// Return all shortcodes from the post
function _get_shortcodes( $the_content ) {
$shortcode = "";
$pattern = get_shortcode_regex();
preg_match_all('/'.$pattern.'/uis', $the_content, $matches);
for ( $i=0; $i < 40; $i++ ) {
if ( isset( $matches[0][$i] ) ) {
$shortcode .= $matches[0][$i];
}
}
return $shortcode;
}
Use it like so:
<?php echo do_shortcode( _get_shortcodes( get_the_content() ) ) ?>
Search wherever your shortcode position is on your content
Example :
[my_shortcode]
[my_shortcode_2]
or
[my_shortcode_2]
[my_shortcode]
Functions.php
function get_shortcode($code,$content) {
$pattern = get_shortcode_regex();
preg_match_all('/'.$pattern.'/s',$content,$matches);
if(is_array($matches) && isset($matches[2]) && in_array($code,$matches[2])) {
$index = array_search($code,$matches[2]);
$shortcode = $matches[0][$index];;
return do_shortcode($shortcode);
} else {
return false;
}
}
Using example :
$content = $post->post_content;
$my_shortcode = get_shortcode('my_shortcode',$content);
$my_shortcode_2 = get_shortcode('my_shortcode_2',$content);
echo $my_shortcode;
if($my_shortcode){ // if shortcode#1 found so echo shortcode#2 after
echo $my_shortcode_2;
}
use this regex
preg_match('/\[summary[^\]]*](.*)\[\/summary[^\]]*]/uis', $string , $matches)
$match[1] should be your text
Edit: ok to match any combination of tags
use
/\[([^\]]+)\](.*?)\[\/\1\]/uis
but if you have nested tags you might need to parse the matches again recursively. However if it is a wordpress free text i think you might get too complex cases that a simple script can handle
You can do this using the get_shortcode_regex() function to get the regex for all registered shotcodes in your blog, apply that to the content to get an array of shortcodes found in that content, then call the appropriate callback to process the one you want.
So inside a loop somewhere it would be something like:
$pattern = get_shortcode_regex();
$matches = array();
preg_match_all("/$pattern/s", get_the_content(), $matches);
var_dump($matches); //Nested array of matches
//Do the first shortcode
echo preg_replace_callback( "/$pattern/s", 'do_shortcode_tag', $matches[0][0] );
This will execute the first shortcode found in the post, obviously in practice you want to check that you've got one!
As it says in the title, I'm looking for multiple excerpt lengths in WordPress.
I understand you can do this in functions.php:
function twentyten_excerpt_length( $length ) {
return 15;
}
add_filter( 'excerpt_length', 'twentyten_excerpt_length' );
What I want to know is how you can have multiple of these each returning different numerical values so I can get short excerpts for sidebar loops, longer excerpts for featured loops, and the longest excerpt for the main article.
Something like using these in the templates:
<?php the_excerpt('length-short') ?>
<?php the_excerpt('length-medium') ?>
<?php the_excerpt('length-long') ?>
Cheers,
Dave
How about...
function excerpt($limit) {
$excerpt = explode(' ', get_the_excerpt(), $limit);
if (count($excerpt) >= $limit) {
array_pop($excerpt);
$excerpt = implode(" ", $excerpt) . '...';
} else {
$excerpt = implode(" ", $excerpt);
}
$excerpt = preg_replace('`\[[^\]]*\]`', '', $excerpt);
return $excerpt;
}
function content($limit) {
$content = explode(' ', get_the_content(), $limit);
if (count($content) >= $limit) {
array_pop($content);
$content = implode(" ", $content) . '...';
} else {
$content = implode(" ", $content);
}
$content = preg_replace('/\[.+\]/','', $content);
$content = apply_filters('the_content', $content);
$content = str_replace(']]>', ']]>', $content);
return $content;
}
then in your template code you just use..
<?php echo excerpt(25); ?>
from: http://bavotasan.com/tutorials/limiting-the-number-of-words-in-your-excerpt-or-content-in-wordpress/
As for now, you can upgrade Marty's reply:
function excerpt($limit) {
return wp_trim_words(get_the_excerpt(), $limit);
}
You can also define custom 'read more' link this way:
function custom_read_more() {
return '... <a class="read-more" href="'.get_permalink(get_the_ID()).'">more »</a>';
}
function excerpt($limit) {
return wp_trim_words(get_the_excerpt(), $limit, custom_read_more());
}
This is what I came up with.
Add this to your functions.php
class Excerpt {
// Default length (by WordPress)
public static $length = 55;
// So you can call: my_excerpt('short');
public static $types = array(
'short' => 25,
'regular' => 55,
'long' => 100
);
/**
* Sets the length for the excerpt,
* then it adds the WP filter
* And automatically calls the_excerpt();
*
* #param string $new_length
* #return void
* #author Baylor Rae'
*/
public static function length($new_length = 55) {
Excerpt::$length = $new_length;
add_filter('excerpt_length', 'Excerpt::new_length');
Excerpt::output();
}
// Tells WP the new length
public static function new_length() {
if( isset(Excerpt::$types[Excerpt::$length]) )
return Excerpt::$types[Excerpt::$length];
else
return Excerpt::$length;
}
// Echoes out the excerpt
public static function output() {
the_excerpt();
}
}
// An alias to the class
function my_excerpt($length = 55) {
Excerpt::length($length);
}
It can be used like this.
my_excerpt('short'); // calls the defined short excerpt length
my_excerpt(40); // 40 chars
This is the easiest way that I know of to add filters, that are callable from one function.
I was looking for this feature as well and most of the functions here are good and flexible.
For my own case I was looking for a solution that shows a different excerpt length only on specific pages. I'm using this:
function custom_excerpt_length( $length ) {
return (is_front_page()) ? 15 : 25;
}
add_filter( 'excerpt_length', 'custom_excerpt_length', 999 );
Paste this code inside the themes functions.php file.
You can add to your functions.php file this function
function custom_length_excerpt($word_count_limit) {
$content = wp_strip_all_tags(get_the_content() , true );
echo wp_trim_words($content, $word_count_limit);
}
Then call it in your template like this
<p><?php custom_length_excerpt(50); ?>
The wp_strip_all_tags should prevent stray html tags from breaking the page.
Documentation on functions
get_the_content
wp_trim_words
wp_strip_all_tags
Going back to Marty's reply:
I know it's been well over a year since this reply got published, but it's better late than never. For this to work with limits of over the WordPress default of 55, you need to replace this line:
$excerpt = explode(' ', get_the_excerpt(), $limit);
with this line:
$excerpt = explode(' ', get_the_content(), $limit);
Otherwise, the function only works with an already trimmed-down piece of text.
I think we can now use wp_trim_words see here.
Not sure what extra data escaping and sanitization needed to use this function, but it looks interesting.
Here an easy way to limit the content or the excerpt
$content = get_the_excerpt();
$content = strip_tags($content);
echo substr($content, 0, 255);
change get_the_excerpt() by get_the_content() if you want the contents.
Regards
I would do like this :
function _get_excerpt($limit = 100) {
return has_excerpt() ? get_the_excerpt() : wp_trim_words(strip_shortcodes(get_the_content()),$limit);
}
Usage :
echo _get_excerpt(30); // Inside the loop / query
Why ?
If has_excerpt should return given excerpt
It not, So trim words / strip shortcodes from the_content
I thing it is possible to create a short code , i did not try it but i wrote for you the main idea about its structure
function twentyten_excerpt_length($atts,$length=null){
shortcode_atts(array('exlength'=>'short'),$atts);
if(!isset($atts['exlength']) || $atts['exlength'] == 'short') {
return 15;
}elseif( $atts['exlength'] == 'medium' ){
return 30; // or any value you like
}elseif( $atts['exlength'] == 'long' ){
return 45; // or any value you like
}else{
// return nothing
}
}
add_shortcode('the_excerpt_sc','twentyten_excerpt_length');
so you can use it like so
[the_excerpt_sc exlength="medium"]
I know this is a really old thread, but I just struggled with this problem and none of the solutions I found online worked properly for me. For one thing my own "excerpt_more"-filter was always cut off.
The way I solved it is ugly as hell, but it's the only working solution I could find. The ugliness involves modifying 4 lines of WP core(!!) + the use of yet another global variable (although WP already does this so much I don't feel too bad).
I changed wp_trim_excerpt in wp-includes/formatting.php to this:
<?php
function wp_trim_excerpt($text = '') {
global $excerpt_length;
$len = $excerpt_length > 0 ? $excerpt_length : 55;
$raw_excerpt = $text;
if ( '' == $text ) {
$text = get_the_content('');
$text = strip_shortcodes( $text );
$text = apply_filters('the_content', $text);
$text = str_replace(']]>', ']]>', $text);
$excerpt_length = apply_filters('excerpt_length', $len);
$excerpt_more = apply_filters('excerpt_more', ' ' . '[…]');
$text = wp_trim_words( $text, $excerpt_length, $excerpt_more );
}
$excerpt_length = null;
return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
}
The only new stuff is the $excerpt_length and $len bits.
Now if I want to change the default length I do this in my template:
<?php $excerpt_length = 10; the_excerpt() ?>
Changing core is a horrible solution so I'd love to know if someone comes up with something better.
Be careful using some of these methods. Not all of them strip the html tags out, meaning if someone inserts a link to a video (or url) in the first sentence of their post, the video (or link) will show up in the excerpt, possibly blowing up your page.
I wrote an article about using custom excerpt length in WordPress.
There area a number of ways to limit & control post excerpt length.
Limit post excerpt length or post content length using number of words.
Limiting excerpt length to a number of characters.
Limit post summary by adding ‘read more’ tag.
Enabling custom excerpt to write your own summary for each post.
Control Excerpt Length using Filters
I hope this will help you a lot.