Skip to Content
Menu

excerpt()

A smart excerpt function that allows customization per instance (rather than globally across the whole website).

PHP April 7, 2021

Usage

PHP
nebula()->excerpt($options)

Parameters

$options
(Optional) (Array) An array of options.
Default: See below

Parameter Notes

id
An ID to pull the text from. This can be passed as a string or int. A WP_Post object could also be passed here instead.
Default: Current post ID

text
The text to shorten. If an ID is passed this uses that post’s excerpt or content.
Default: Post excerpt/content

characters
The maximum number of characters.
Default: false

words
The maximum length of the text in words.
Default: 55

length
Used for dynamic length by passing “dynamic”, otherwise an alias of “words”.
Default: false

min
The minimum length of a dynamic sentence.
Default: 0

ellipsis
Whether or not to add an ellipsis to shorten text.
Default: false

url
The URL to link to. If the “more” option is set (including default value), the link uses the permalink of the post.
Default: Post permalink

wp_more
Listen for the <!--more--> tag within the post. This tag can override the more parameter by using: <!--more Keep Reading-->
Default: true

more
The text that is linked to the URL after the excerpt.
Default: “Read More &raquo;”

button
Turn the “more” text into a button (rather than just a link).
Default: false

strip_shortcodes
Whether to strip WordPress shortcodes from the excerpt.
Default: true

strip_tags
Whether to strip HTML tags from the excerpt.
Default: true

wrap_links
Wrap URLs in <a> tags.
Default: false

Request or provide clarification »

Examples

Inside the loop (or outside the loop for current post/page)

PHP
<?php echo nebula()->excerpt(array('length' => 20, 'ellipsis' => true)); ?>

Outside the loop

PHP
<?php echo nebula()->excerpt(array('id' => 572, 'length' => 20, 'ellipsis' => true)); ?>

Custom excerpt

PHP
<?php echo nebula()->excerpt(array('text' => 'Lorem ipsum <strong>dolor</strong> sit amet.', 'more' => 'Continue &raquo;', 'length' => 3, 'ellipsis' => true, 'strip_tags' => true)); ?>

Using an ACF field

PHP
<?php echo nebula()->excerpt(array('text' => get_field('some_text_field', 33), 'length' => 50, 'ellipsis' => false, 'more' => false)); ?>

Use as a meta description ending with a sentence

PHP
<?php echo nebula()->excerpt(array('length' => 'dynamic', 'characters' => 160, 'more' => '', 'ellipsis' => false, 'strip_tags' => true)); ?>
Was this page helpful? Yes No


    A feedback message is required to submit this form.


    Please check that you have entered a valid email address.

    Enter your email address if you would like a response.

    Thank you for your feedback!

    Source File

    Located in /libs/Functions.php on line 820.

    2 Hooks

    Find these filters and actions in the source code below to hook into them. Use do_action() and add_filter() in your functions file or plugin.

    Filters
    "pre_nebula_excerpt"
    "nebula_excerpt_defaults"
    Need a new filter hook? Request one here.

    Actions
    This function has no action hooks available. Request one?

    Note: This function contains 1 to-do comment.

    PHP
            public function excerpt($options=array()){
                $override = apply_filters('pre_nebula_excerpt', null, $options);
                if ( isset($override) ){return $override;}
    
                $defaults = apply_filters('nebula_excerpt_defaults', array(
                    'id' => false,
                    'text' => false,
                    'paragraphs' => false, //Allow paragraph tags in the excerpt //@todo "Nebula" 0: currently not working
                    'characters' => false,
                    'words' => get_theme_mod('nebula_excerpt_length', 55),
                    'length' => false, //Used for dynamic length, otherwise an alias of "words"
                    'min' => 0, //Minimum length of dynamic sentence
                    'ellipsis' => false,
                    'url' => false,
                    'more' => get_theme_mod('nebula_excerpt_more_text', __('Read More', 'nebula') . ' &raquo;'),
                    'wp_more' => true, //Listen for the WP more tag
                    'btn' => false, //Alias of "button"
                    'button' => false,
                    'strip_shortcodes' => true,
                    'strip_tags' => true,
                    'wrap_links' => false,
                    'shorten_urls' => false, //Currently only works with wrap_links
                ));
    
                $data = array_merge($defaults, $options);
    
                //Establish text
                if ( empty($data['text']) ){
                    if ( !empty($data['id']) ){
                        if ( is_object($data['id']) && get_class($data['id']) == 'WP_Post' ){ //If we already have a WP_Post class object
                            $the_post = $data['id'];
                        } elseif ( intval($data['id']) ){ //If an ID is passed
                            $the_post = get_post(intval($data['id']));
                        }
                    } else {
                        $the_post = get_post(get_the_ID());
                    }
    
                    if ( empty($the_post) ){
                        return false;
                    }
    
                    if ( !empty($the_post->post_excerpt) ){
                        $data['text'] = $the_post->post_excerpt;
                    } else {
                        $data['text'] = $the_post->post_content;
                        if ( $data['wp_more'] ){
                            $wp_more_split = get_extended($the_post->post_content); //Split the content on the WordPress <!--more--> tag
                            $data['text'] = $wp_more_split['main'];
    
                            if ( preg_match('/<!--more(.*?)?-->/', $the_post->post_content, $matches) ){ //Get the custom <!--more Keep Reading--> text. RegEx from: https://core.trac.wordpress.org/browser/tags/4.8/src/wp-includes/post-template.php#L288
                                if ( !empty($matches[1]) ){
                                    $data['more'] = strip_tags(wp_kses_no_null(trim($matches[1])));
                                }
                            }
                        }
                    }
                }
    
                //Strip Newlines
                $data['text'] = str_replace(array("\r\n", "\r", "\n"), " ", $data['text']); //Replace newline characters (keep double quotes)
                $data['text'] = preg_replace('/\s+/', ' ', $data['text']); //Replace multiple spaces with single space
    
                //Strip Shortcodes
                if ( $data['strip_shortcodes'] ){
                    $data['text'] = strip_shortcodes($data['text']);
                } else {
                    $data['text'] = preg_replace('~(?:\[/?)[^/\]]+/?\]~s', ' ', $data['text']);
                }
    
                //Strip Tags
                if ( $data['strip_tags'] ){
                    $allowable_tags = ( !empty($data['paragraphs']) )? 'p' : '';
                    $data['text'] = strip_tags($data['text'], $allowable_tags);
                }
    
                //Apply string limiters (words or characters)
                if ( !empty($data['characters']) && intval($data['characters']) ){ //Characters
                    $limited = $this->string_limit_chars($data['text'], intval($data['characters'])); //Returns array: $limited['text'] is the string, $limited['is_limited'] is boolean if it was limited or not.
                    $data['text'] = trim($limited['text']);
                } elseif ( (!empty($data['words']) && intval($data['words'])) || (!empty($data['length']) && intval($data['length'])) ){ //Words (or Length)
                    $word_limit = ( !empty($data['length']) && intval($data['length']) )? intval($data['length']) : intval($data['words']);
                    $limited = $this->string_limit_words($data['text'], $word_limit); //Returns array: $limited['text'] is the string, $limited['is_limited'] is boolean if it was limited or not.
                    $data['text'] = trim($limited['text']);
                }
    
                //Apply dynamic sentence length limiter
                if ( $data['length'] === 'dynamic' ){
                    $last_punctuation = -1;
                    foreach ( array('.', '?', '!') as $punctuation ){
                        if ( strrpos($data['text'] . ' ', $punctuation . ' ') ){
                            $this_punctuation = strrpos($data['text'] . ' ', $punctuation . ' ')+1; //Find the last punctuation (add a space to the end of the string in case it already ends at the punctuation). Add 1 to capture the punctuation, too.
    
                            if ( $this_punctuation > $last_punctuation ){
                                $last_punctuation = $this_punctuation;
                            }
                        }
                    }
    
                    if ( $last_punctuation >= $data['min'] ){
                        $data['text'] = substr($data['text'], 0, $last_punctuation); //Remove everything after the last punctuation in the string.
                    }
                }
    
                //Check here for links to wrap
                if ( $data['wrap_links'] ){
                    $data['text'] = preg_replace('/(\(?(?:(http|https|ftp):\/\/)?(?:((?:[^\W\s]|\.|-|[:]{1})+)@{1})?((?:www.)?(?:[^\W\s]|\.|-)+[\.][^\W\s]{2,4}|localhost(?=\/)|\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?::(\d*))?([\/]?[^\s\?]*[\/]{1})*(?:\/?([^\s\n\?\[\]\{\}\#]*(?:(?=\.)){1}|[^\s\n\?\[\]\{\}\.\#]*)?([\.]{1}[^\s\?\#]*)?)?(?:\?{1}([^\s\n\#\[\]]*))?([\#][^\s\n]*)?\)?)(?![^<]*<\/)/i', '<a class="nebula-excerpt-url" href="$1">$1</a>', $data['text']); //Capture any URL not within < and </ using a negative lookahead (so it plays nice in case strip_tags is false)
                }
    
                //Shorten visible URL text
                if ( $data['shorten_urls'] ){
                    $data['text'] = preg_replace_callback('/(<a.+>)(.+)(<\/a>)/', function($matches){
                        $output = $matches[1];
                        if ( strlen($matches[2]) > 20 ){
                            $short_url = str_replace(array('http://', 'https://'), '', $matches[2]);
                            $url_directories = explode('/', $short_url);
                            $short_url = $url_directories[0];
                            if ( count($url_directories) > 1 ){
                                $short_url .= '/...';
                            }
                            $output .= $short_url;
                        } else {
                            $output .= $matches[2];
                        }
                        $output .= $matches[3];
                        return $output;
                    }, $data['text']);
                }
    
                //Ellipsis
                if ( $data['ellipsis'] && !empty($limited['is_limited']) ){
                    $data['text'] .= '&hellip;';
                }
    
                //Link
                if ( !empty($data['more']) ){
                    if ( empty($data['url']) ){ //If has "more" text, but no link URL
                        $data['url'] = ( !empty($data['id']) )? get_permalink($data['id']) : get_permalink(get_the_id()); //Use the ID if available, or use the current ID.
                    }
    
                    //Button
                    $btn_class = '';
                    if ( $data['button'] || $data['btn'] ){
                        $button = ( $data['button'] )? $data['button'] : $data['btn'];
                        $btn_class = ( is_bool($button) )? 'btn btn-brand' : 'btn ' . $data['button'];
    
                        $data['text'] .= '<br /><br />';
                    }
    
                    $data['text'] .= ' <a class="nebula_excerpt ' . $btn_class . '" href="' . $data['url'] . '">' . $data['more'] . '</a>';
                }
    
                return $data['text'];
            }
    

    Override

    To override this PHP function, use this hook in your child theme or plugin ("my_custom" can be changed):

    PHP
    add_filter('pre_nebula_excerpt', 'my_custom_excerpt', 10, 2); //The last integer must be 1 more than the actual parameters
    function my_custom_excerpt($null, $options){ //$null is required, but can be ignored
        //Write your own code here
    
        return true; //Return true to prevent the original function from running afterwords
    }

    You can completely disable this PHP function with a single line actions:

    PHP
     add_filter('pre_nebula_excerpt', '__return_false');