I have found out how to add a short description to the thumbnails for products in WooCommerce, but how do I truncate them to a certain length, say 30 characters.
All the answers to do with editing the functions.php file dont mention where in the file to put the code.
My code in my functions.php file is:
add_action('woocommerce_after_shop_loop_item_title','add_title_description',9);
function add_title_description(){
echo get_post_meta($product->id, 'title-description', true)? '<span class="title-description">' . get_post_meta($product->id, 'title-description', true) . '</span><br />' : '';
}
use substr()
add_action('woocommerce_after_shop_loop_item_title','add_title_description',9);
function add_title_description()
{
$titleDescription = get_post_meta($product->id, 'title-description', true);
if( !empty($titleDescription) )
{
if( strlen($titleDescription) > 30 )
$titleDescription = substr($titleDescription, 30);
printf('<span class="title-description">%s</span><br />', $titleDescription);
}
}
My implementation grabbing the first 2 sentences instead of a character count.
/**
* Echo Truncated String
*
* #param string $string
* #return string
*/
function add_title_description( $titleDescription ) {
global $product;
$titleDescription = get_post_meta( $product->id, 'title-description', true );
// combine first 2 sentences
$sentence = preg_split( '/(\.|!|\?)\s/', $titleDescription, 3, PREG_SPLIT_DELIM_CAPTURE );
echo $titleDescription ? '<span class="title-description">' . $sentence[0] . $sentence[3] . '</span><br />' : '';
}
add_action( 'woocommerce_after_shop_loop_item_title', 'add_title_description', 4, 1 );
I added this:
function wcs_excerpt_length( $length ) {
return 15;
}
add_filter( 'product_description_length', 'wcs_excerpt_length' );
Related
i need to add product link url (of external affiliate) under long description in woocommerce single product page. how to do? thank you
I put this code in functions.php but it doesn't print the url near the description.
add_filter( 'the_content', 'shorten_product_long_descrition', 20 );
function shorten_product_long_description( $content ){
// Only for single product pages
if( ! is_product() ) return $content;
// Set the limit of words
$limit = 13;
if (str_word_count($content, 0) > $limit) {
$arr = str_word_count($content, 2);
$pos = array_keys($arr);
$text = '<p>' . substr($content, 0, $pos[$limit]) . "..<a href='" . esc_url( $product_url ) . "' class='goto_more_offer_tab button'>...continue reading</a></p>";
$content = force_balance_tags($text); // needed
}
return $content;
}
One can control the WP default (Automatic) excerpt length of a WP post using the using the following snippet within functions.php;
From the WP Codex
// . Post excerpt adjustment (Auto)
// . ==============================
function wpdocs_custom_excerpt_length( $length ) {
return 20;
}
add_filter( 'excerpt_length', 'wpdocs_custom_excerpt_length', 999 );
My question is how do you limit the manual one?
You know, the exerpt specifically added by the user themselves?
(*) There is an 8 year old question here, that does provide some context but given the current year and progress WP has made I want to post the question again and receive some clarity on the subject.
Added Context: (Edited: 12 March 2019)
It's not that the original answer to the question posted earlier doesn't work, all be it seems, really clunky. I'm looking for a more simple & robust answer using exerpt_length filter. Rather than using something like the following to trim the text; (If Possible)
function excerpt($limit) {
return wp_trim_words(get_the_excerpt(), $limit);
}
We have by default in core, the following filtering:
add_filter( 'get_the_excerpt', 'wp_trim_excerpt' );
but within wp_trim_excerpt() the trimming is only applied on the post's content, when there's no manual excerpt set.
Here's an untested suggestion for a custom filtering:
add_filter( 'get_the_excerpt', function( $excerpt, $post ) {
if ( has_excerpt( $post ) ) {
$excerpt_length = apply_filters( 'excerpt_length', 55 );
$excerpt_more = apply_filters( 'excerpt_more', ' ' . '[…]' );
$excerpt = wp_trim_words( $excerpt, $excerpt_length, $excerpt_more );
}
return $excerpt;
}, 10, 2 );
to apply the similar trimming on manual excerpts.
Hope you can adjust this further to your needs.
Try this, I got this code from here: https://www.wpexplorer.com/wordpress-excerpt-length/
add_filter( 'excerpt_length', function($length) {
return 20;
} );
This pair of functions will give you control over the excerpt length, including the manual excerpt which is returned if available, otherwise the "excerpt-ized" post_content gets returned. These go in your theme functions file:
function get_excerpt_by_id($post_id, $length = NULL) {
$length = isset($length) ? $length : apply_filters('excerpt_length', 32);
$p = get_post($post_id);
return $p->post_excerpt ? build_excerpt_by_length($p->post_excerpt, $length) : build_excerpt_by_length($p->post_content, $length);
}
function build_excerpt_by_length($content, $length = 32) {
$excerpt = strip_tags(strip_shortcodes($content));
$words = explode(' ', $excerpt, $length + 1);
$words = array_slice($words, 0, $length);
$result = trim(implode(' ', $words));
$result = preg_replace('/\W*$/', '', $result);
$more = apply_filters('excerpt_more', '…');
if ($result !== '') $result = $content === $result ? $result : $result . $more;
return $result;
}
Then in your templates you can use by calling:
get_excerpt_by_id($your_post_id, $preferred_excerpt_length);
You can try the following code
$excerpt = get_the_excerpt();
$excerpt = substr( $excerpt, 0, 180 );
$excerpt_description = substr( $excerpt, 0, strrpos( $excerpt, ' ' ) );
echo $excerpt_description;
Is it possible to remove the first word from the product title in WooCommerce? I've found some php code but I can't figure it out at the moment.
echo substr(strstr("Remove First Word"," "), 1);
That should echo "First Word". How would I do that for the WooCommerce product title? I appreciate all the help!
For product title in single product pages and archives pages:
add_filter( 'the_title', 'custom_the_title', 10, 2 );
function custom_the_title( $title, $post_id ){
$post_type = get_post_field( 'post_type', $post_id, true );
if( $post_type == 'product' || $post_type == 'product_variation' )
$title = substr( strstr( $title, ' ' ), 1 );
return $title;
}
Code goes in function.php file of your active child theme (or active theme).
Tested and works.
The product title uses WordPress function get_the_title() or the_title() to be displayed (as woocommerce product is a custom post type)… so the correct filter hook to be used is "the_title".
But it will not really handle html tags (as this are something else in the templates).
For cart and checkout pages:
add_filter( 'woocommerce_cart_item_name', 'customizing_cart_item_name', 10, 3);
function customizing_cart_item_name( $item_name, $cart_item, $cart_item_key ) {
$product = $cart_item['data'];
$product_permalink = $product->is_visible() ? $product->get_permalink( $cart_item ) : '';
$product_name = $product->get_name();
$product_name = substr( strstr( $product_name, ' ' ), 1 );
if ( $product_permalink && is_cart() ) {
return sprintf( '%s', esc_url( $product_permalink ), $product_name );
} elseif ( ! $product_permalink && is_cart() ) {
return $product_name . ' ';
} else {
return $product_name;
}
}
Code goes in function.php file of your active child theme (or active theme).
Tested and works.
use this:
$str = "Remove First Word";
$words = explode(' ', $str);
unset($words[0]);
echo join(' ', $words);
The explode function returns an array with each words.
The unset function remove the first word contained in the array $words.
Finally, join print all $words joined by space .
demo
Could you try using this?
if ( ! function_exists( 'woocommerce_template_loop_product_title' ) ) {
/**
* Removes first word in WooCommerce product_title
* #var $tag
*/
function woocommerce_template_loop_product_title() {
$tag = is_product_taxonomy() || is_shop() ? 'h2' : 'h3';
echo apply_filters( 'woocommerce_template_loop_product_title', '<' . $tag . ' class="woocommerce-loop-product__title">' . substr(strstr(get_the_title()," "), 1) . '</' . $tag . '>');
}
/**
* Removes first word in WooCommerce product page product_title
* #var $tag
*/
function woocommerce_single_product_summary() {
$tag = 'h1';
echo apply_filters(woocommerce_single_product_summary, '<' . $tag . ' class="product_title entry-title">' . substr(strstr(get_the_title()," "), 1) . '</' . $tag . '>');
}
}
Hopefully this works out for you, haven't tested it.
I have created my own custom word limit function in wordpress. I need a way to ignore the shortcode as part of the word count. I don't want to strip it out but ignore shortcodes as part of the word count. Otherwise if you choose a number say 15 and the shortcode is in any part of that 15 word limit then the page will fatal error.
function my_word_limit($limit) {
$content = explode(' ', get_the_content(), $limit);
if (count($content)>=$limit) {
array_pop($content);
$content = implode(" ",$content).'...';
} else {
$content = implode(" ",$content);
}
$content = apply_filters('the_content', $content);
return $content;
}
This is the shortcode I would be using for example.
[di-video-logged-out]<iframe src="https://www.youtube.com/embed/LEIu8gba634" width="854" height="480"></iframe>[/di-video-logged-out]
Trim content and limit with certain count word
( Keep shortcode on output even content trimmed, you can tweak also if you don't )
Here my approach with use wp_trim_word of the content and filter wp_trim_word. Also, you can use this function wpso36236774_trim_words into such as $post->post_content or get_the_content directly ( without filter ). Usage was commented inside code.
add_filter( 'wp_trim_words', 'wpso36236774_trim_words', 10, 4 );
/* Trims text to a certain number of words.
* #author Jevuska
* #version 1.0.1
*
* Kepp shortcode if exist in text.
* Combination function of strip_shortcodes and wp_trim_words
* Default $num_words = 55
*
** USAGE
** Using directly
** wpso36236774_trim_words( $text, 56 )
** wpso36236774_trim_words( $text, 56, null, false, false, true ) - return array
** Shortcode hidden if $num_words is not set or if set with value = 55 with 4 arguments
**
** Use wp_trim_words
** wp_trim_words( $text, $num_words = 56 )
** Fire wp_trim_words
** Shortcode hidden if $num_words is not set or $num_words = 55
** Position always in bottom
** add_filter( 'wp_trim_words', 'wpso36236774_trim_words', 10, 4 );
*
* #param string $text Text to trim.
* #param int $num_words The number of words to trim the text to. Default 5.
* #param string $more An optional string to append to the end of the trimmed text, e.g. ….
* #param string $original_content The text before it was trimmed.
* #param mix $pos Shortcode Position. You can set 'top' value if using directly
* #param boolean $count Get word count
* #return string The text after the filter witch $num_words
* #return array If using directly and parameter $count set to true
*/
function wpso36236774_trim_words( $text, $num_words = 55, $more = null, $original_content = false, $pos = false, $count = false )
{
if ( null === $more)
$more = ' ' . '[…]';
$shortcode = $strip_shortcode = true;
if ( ! $original_content )
$original_content = $text;
$text = $original_content;
/* Check existing shortcode
*
*/
if ( false === strpos( $text, '[' ) )
$strip_shortcode = false;
global $shortcode_tags;
if ( empty( $shortcode_tags ) || ! is_array( $shortcode_tags ) )
$strip_shortcode = false;
/* Strip content from shortcode
*
*/
if ( $strip_shortcode )
{
preg_match_all( '#\[([^<>&/\[\]\x00-\x20=]++)#', $text, $matches );
$tagnames = array_intersect( array_keys( $shortcode_tags ), $matches[1] );
if ( ! empty( $tagnames ) )
{
$text = do_shortcodes_in_html_tags( $text, true, $tagnames );
$pattern = get_shortcode_regex( $tagnames );
preg_match_all( "/$pattern/", $text, $match );
if ( ! empty( $match[0] ) && is_array( $match[0] ) )
{
$shortcode = '';
$length = count( $match[0] );
for ( $i = 0 ; $i < $length; $i++ )
$shortcode .= do_shortcode( $match[0][ $i ] ); //match shortcode
}
$text = preg_replace_callback( "/$pattern/", 'strip_shortcode_tag', $text );
$text = unescape_invalid_shortcodes( $text );
}
}
/* Hide shortcode
* Base on count function arguments
*
*/
if ( func_num_args() == 1 || ( func_num_args() == 4 && 55 == $num_words ) )
$shortcode = '';
/* Split content into array words
*
*/
$text = wp_strip_all_tags( $text );
/*
* translators: If your word count is based on single characters (e.g. East Asian characters),
* enter 'characters_excluding_spaces' or 'characters_including_spaces'. Otherwise, enter 'words'.
* Do not translate into your own language.
*/
if ( strpos( _x( 'words', 'Word count type. Do not translate!' ), 'characters' ) === 0 && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) )
{
$text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' );
preg_match_all( '/./u', $text, $words_array );
$limit_words_array = array_slice( $words_array[0], 0, $num_words + 1 );
$full_words_array = $words_array[0];
$sep = '';
}
else
{
$limit_words_array = preg_split( "/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY );
$full_words_array = explode( ' ', preg_replace( "/[\n\r\t ]+/", ' ', $text ) );
$sep = ' ';
}
/* Check word count base on $num_words
*
*/
$word_count = count( $full_words_array );
if ( $word_count >= $num_words )
{
array_pop( $limit_words_array );
$text = implode( $sep, $limit_words_array );
$text .= $more;
/* keep shortcode if exists and set position ( top or bottom text )
*
*/
switch( $pos )
{
case 'top' :
$text = $shortcode . $text;
break;
default :
$text .= $shortcode;
break;
}
}
else
{
$text = apply_filters( 'the_content', $original_content );
}
if ( $count )
return array(
'text' => $text,
'count' => $word_count
);
return $text; //output
}
Let me know if any issue about this code. Tweak as you need and I hope this helps.
UPDATE
Fix multiple shortcode
Hide shortcode option base on total argument
Patch $pos for additional shortcode position top and bottom text ( func directly only ). For another positon, you must set class and css for your shortcode.
At the moment i have a function and a filter which shortens titles if they are longer than 25characters and appends the triple dot '...'
However, it appends the dots to all the titles. How can i get the following code to run only if the title is longer than 25 characters?
function japanworm_shorten_title( $title ) {
$newTitle = substr( $title, 0, 25 ); // Only take the first 25 characters
return $newTitle . " …"; // Append the elipsis to the text (...)
}
add_filter( 'the_title', 'japanworm_shorten_title', 10, 1 );
You can use PHP's strlen: http://php.net/manual/en/function.strlen.php
Your code would go like:
function japanworm_shorten_title( $title ) {
if (strlen($title) > 25){
$title = substr( $title, 0, 25 ).'…';
}
return $title;
}
add_filter( 'the_title', 'japanworm_shorten_title', 10, 1 );