How to detect if manual excerpt exists in WordPress? - php

I need to show excerpts of different lengths, so I use
function custom_excerpt($length) {
get_the_content();
... clean up and trim
return $excerpt;
}
however, I want to detect if a manual excerpt was entered in order to use that instead of the custom one. Is there a way to do this?
I tried by using
$wp_excerpt = get_the_excerpt();
But that returns the manual excerpt, and if the manual excerpt is empty, it automatically generates an excerpt of 55 characters, which doesn't help, because it will always be "true" (can't check if empty).
The reason for approaching it this way is because I have multiple excerpts on a single page (different lengths), and if the length needed is longer than the WordPress excerpt (55), I want to show my excerpt, unless a manual excerpt was written, in which case I want to show that.
It would be perfect if I could simply
if ( manual_excerpt() == true ) {
}

You need only replace the excerp_length wordpress default function, just follow the above code, then you can call this custom function and set the length:
<?php
// custom excerpt length
function custom_excerpt_length( $length = 20 ) {
return $length;
}
add_filter( 'excerpt_length', 'custom_excerpt_length', 999 );
?>
ANSWER UPDATED II
Using inside a function:
<?php
function custom_excerpt( $length = 55 ) {
if( $post->post_excerpt ) {
$content = get_the_excerpt();
} else {
$content = get_the_content();
$content = wp_trim_words( $content , $length );
}
return $excerpt;
}
?>

This is an old question but I was looking for this, ended up here and didn't see the following function in the answers. To know if a post has a custom excerpt you can use the has_excerpt function:
<?php has_excerpt( $id ); ?>
Where $id is the post id. If non is given then the current post id will be used.

Check if the post_excerpt slot in the post object is empty or not:
global $post;
if( '' == $post->post_excerpt )
{
// this post does NOT have a manual excerpt
}
To turn this into a function:
function so19935351_has_manual_excerpt( $post )
{
if( '' == $post->post_excerpt )
return false;
return true;
}

Related

Yootheme Pro - Wordpress: Get content of page before it is displayed

I'm writing a simple plugin for wordpress that changes a single word on a page or a post to make it bold.
For example: vlbs -> vlbs
It works fine for normal Wordpress pages and posts with this code:
defined('ABSPATH') or die('You can\'t enter this site');
class VLBS {
function __construct() {
}
function activate() {
flush_rewrite_rules();
}
function deactivate() {
flush_rewrite_rules();
}
function unstinstall() {
}
function new_content($content) {
return $content = str_replace('vlbs','<strong style="color:#00a500">vlbs</strong>', $content);
}
}
if(class_exists('VLBS')){
$VLBS = new VLBS();
}
add_filter('the_content', array($VLBS, 'new_content'));
//activation
register_activation_hook(__FILE__, array($VLBS, 'activate'));
//deactivation
register_deactivation_hook(__FILE__, array($VLBS, 'deactivate'));
However, it does not work on a page built with Yootheme Pro Pagebuilder. Whatever is done within the function new_content() is processed after the content has already been loaded. Thus, I cannot manipulate it before it is displayed to the user.
So the question would be: How can I get the content of a page before it is displayed? Is there an equivalent to Wordpress' 'the_content'?
Any help is really appreciated! Thank you very much in advance.
Best regards
Fabian
Yootheme: 1.22.5
Wordpress: 5.2.4
PHP: 7.3
Browser: Tested on Chrome, Firefox, Edge, Internet Explorer
In your code, do you are sure it's the good usage of add_filter content ?
In the doc, the 2nd parameter is string, not array:
add_filter( 'the_content', 'filter_the_content_in_the_main_loop' );
function filter_the_content_in_the_main_loop( $content ) {
// Check if we're inside the main loop in a single post page.
if ( is_single() && in_the_loop() && is_main_query() ) {
return $content . esc_html__("I'm filtering the content inside the main loop", "my-textdomain");
}
return $content;
}
In wordpress, the_content function display the content. There is an other function for get_the_content
Go to your page file and get the content. You can use str_replace and echo the new content after.
Example single.php :
if ( $query->have_posts() ) :
while( $query->have_posts() ) : $query->the_post();
$content = get_the_content();
$new_content = str_replace(search, replace, $content);
echo $new_content;
endwhile;
endif;
If it is not possible for you, try to use the output buffer functions. If you need use this functions, I say it and I developpe more this part. But test the solution above before.
Oh, and it exist a special community for WP where your question will more pertinent : https://wordpress.stackexchange.com/

How to make wordpress function working only on single & NOT for pages

I'm struggling with one thing. I've got such wordpress function:
function wpq_insert_attachment_data($data, $postarr){
if (!is_single() ) {
$posttitle = get_the_title( $postarr['post_parent'] );
$data['post_title'] = $posttitle;
$data['post_name'] = $posttitle;
return $data;
}}
add_filter( 'wp_insert_attachment_data', 'wpq_insert_attachment_data', 10, 2 );
It works superb but it covers all single/custom post type/pages etc. Is there any way to EXCLUDE pages from that function? I've tried sorting it out with is_single() yet without success.
Use is_singular in your statement to target specific post types.
Can also do an array to include or exclude.
If (! is_singular()) ..... or.....
(! is_singular(array('page','food',foo')))
Then it will only run on the singles for whichever post type you're targeting.
Looks like you just need to tweak your conditional statement:
if (!is_single() ) {
Should become:
if (!is_page() ) {
Load the function only on specific page, add your page id in is_page(id_here) :
function wpq_insert_attachment_data($data, $postarr){
if ( is_page(page_id)){
$posttitle = get_the_title( $postarr['post_parent'] );
$data['post_title'] = $posttitle;
$data['post_name'] = $posttitle;
return $data;
}
}
add_filter( 'wp_insert_attachment_data', 'wpq_insert_attachment_data', 10, 2 );
you can also add your page slug instead of id like :
if ( is_page('slug'))
Or exclude page(s)
if ( !is_page('slug'))
if ( !is_page(array('slug-1', 'slug-2') )

Wordpress wp_link_pages top and bottom of post

I've got wp_link_pages added to the bottom of my posts using this in functions.php:
function custom_pagination( $content ) {
if( is_singular() ) {
$content .= wp_link_pages('echo=0');
}
return $content;
}
add_filter( 'the_content','custom_pagination', 1 );
However this only adds it to the bottom but I'd also like to add them to the top of the post how would I go about achieving this? I'm having to use the function method due to also using jetpack related posts (Which the links appear below it if I don't use this method).
Thanks!
Your script is appending (i.e. .=) the wp_link_pages. Instead, you could do something like:
function custom_pagination( $content ) {
if( is_singular() ) {
$content = wp_link_pages('echo=0') . $content . wp_link_pages('echo=0');
}
return $content;
}
add_filter( 'the_content','custom_pagination', 1 );

different excerpt length on wordpress

I want to register a custom length of excerpt on my wordpress plugin. If I add my custom excerpt length on my plugin and if user's theme have another custom excerpt length registered, will they make conflict? I noticed that fucntion name will be different but the filter's tag will be same('excerpt_length').
So, please let me clear about that.
Here is my excerpt length's code.
function custom_excerpt_length( $length ) {
return 40;
}
add_filter( 'excerpt_length', 'custom_excerpt_length');
Thanks.
I use this for a highly customized excerpt output (modified from Aaron Russell's code). It won't conflict with anything else you have. You can remove text values at will. It basically removes any filters for the excerpt output and overrides them.
// better excerpt output
function improved_trim_excerpt($text) {
global $post;
if ( '' == $text ) {
$text = get_the_content('');
$text = apply_filters('the_content', $text);
$text = str_replace('\]\]\>', ']]>', $text);
$text = preg_replace('#<script[^>]*?>.*?</script>#si', '', $text);
$text = strip_tags($text, '<p>');
$excerpt_length = 40;
$words = explode(' ', $text, $excerpt_length + 1);
if (count($words)> $excerpt_length) {
array_pop($words);
array_push($words, '... [<a href="' . get_permalink(). '" >Read More</a>]');
$text = implode(' ', $words);
}
}
return $text;
}
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'improved_trim_excerpt');
If you use a function called custom_excerpt_length() and so does the theme, then you could have a conflict on the function name, but not the call to add_filter(). To mitigate the former you can either use an uncomment prefix (myplugin_custom_excerpt_length() for example) or better yet use a class to protect the namespace like $myplugin->custom_excerpt_length().
Adding multiple callbacks to actions/filters in WordPress won't cause a conflict, per se. If there are multiple actions/filters they are run in the order of their priority, which is the third argument to these functions. To give your filter hook a better chance of running last and thus be the value is used, set it to a high priority such as 999 - or at least higher than the function hooked to the filter you want to override, or lower than the default of 10 if you only want to set it if something else does. You can use this same class to add other actions/filters as well.
if ( ! class_exists( 'MyPlugin' ) ):
class MyPlugin(){
private $priority = 999;
private $excerpt_length = 40;
function __construct(){
// Use an array to pass $this and the function to add_filter()
add_filter( 'excerpt_length', array( $this, 'custom_excerpt_length' ) , $this->priority );
}
// The function name won't conflict since it is in the context of $this->excerpt_length()
function custom_excerpt_length( $length ){
return $this->excerpt_length;
}
}
new MyPlugin();
endif; // class_exists()

Filter to check for keyword and display sidebar content accordingly

Within Wordpress, is it possible to read the content of a post and look for keywords, then display sidebar content accordingly? Example:
If post content contains the word 'cheese' then don't display sidebar advert, otherwise do.
For extra information, I have >500 posts so would not want to add a tag or custom field to every post.
I'd include examples of code but I'm really not sure whether to start with a regex in functions.php and if so, what do I then look for in the sidebar code?
Thanks in advance.
UPDATE 1 - Stripos seems faster than regex for this purpose Stripos on php.net so I used this.
UPDATE 2 - My current setup...
In index.php (or page.php etc depending on theme):
<?php
if( has_keyword() ) {
get_sidebar( 'special' );
} else {
get_sidebar( 'normal' );
}
?>
and in functions.php
function has_keyword ()
{
global $post;
$mywords = array('word1', 'word2', 'word3');
foreach($mywords as $word){
// return false if post content does not contain keyword
if( ( stripos( $post->post_content, $word ) === false ) ) {
return false;
};
};
// return true if it does
return true;
}; //end function
I need to get the foreach function working, there is something wrong in there. I tried to use 'break' on successfully finding a word but I need to return 'false' as well, that's why I added the if condition. Not sure how to do this.
You could use PHP's stripos. Define a custom conditional tag in functions.php:
function has_keyword( $keyword )
{
// only check on single post pages
if( ! is_singular() )
return false;
global $post;
// return false if post content does not contain keyword
if( ( stripos( $post->post_content, $keyword ) === false ) )
return false;
// return true if it does
return true;
}
Then, in your template file:
if( has_keyword( 'my_keyword' ) )
get_sidebar( 'normal' );
else
get_sidebar( 'special' );
update
To check for multiple keywords (see comments):
function has_keyword()
{
if( ! is_singular() )
return false;
global $post;
$keywords = array( 'ham', 'cheese' );
foreach( $keywords as $keyword )
if( stripos( $post->post_content, $keyword ) )
return true;
return false;
}
If you want to verify against a list of words, you could use this function below, which will return false if any of the words are found in your $content else it will return true. So as to say go ahead and display them ads.
function displayAds($content){
$words = array('cheese', 'ham', 'xxx');
foreach($words as $word){
if(preg_match('/\s'.$word.'\s/i', $content)){
return FALSE;
};
};
return TRUE;
};
then in your index.php you can do as your outloud thinking in your Update. Naturally changing function names to reflect your choice of naming.
you can also use preg_match to find exact keyword match in the string like
function check_keyword($keyword){
global $post;
if(!is_single() ){
return false;
}else{
$result = preg_match('/\b('.$keyword.')\b/', $post->post_content);
if($result){
return true;
}else{
return false;
}
}
}
To get side_bar
Call check_keyword()
if (check_keyword('cheese')) {
get_sidebar('cheese');
} else {
get_sidebar('no-ads');
}
See for reference preg_match()
Hope it makes sense

Categories