3

I am having a filter for the content that adds a Table of Contents at the top of my posts. I took the basic idea from an answer at Stack Exchange itself.

I add the filter as follows:

add_filter('the_content', array('TableOfContents', 'writeTOC'), 100);

And until here it is fine, but the problem comes in another function. There is a function in my plugin that takes the first 144 characters of the given post and coverts it into the Meta Description. Now due to the filter mentioned above, the Meta Description doesn't contain the actual content of my post.

        $meta = apply_filters('the_content', $post->post_content);
        $meta = strip_tags($meta);
        $meta = strip_shortcodes($meta );
        $meta = str_replace(array("\n", "\r", "\t"), ' ', $meta);
        $meta = substr($meta, 0, 144);

Rather, my meta description has the first 144 characters including the Table of Contents.

I want to exclude the Table of Contents from my Meta Description, but re-positioning the code did no help.

Below I have attached the full code:

<?php
function Milyin_Head(){ 

global $post; 
if (!is_page()) {   
    if (!is_singular() ) {return; }
    elseif (!empty( $post->post_excerpt)) {
        $meta = $post->post_excerpt ;   
} 
    else {
        // THIS IS MY PROBLEM LINE, i USE Apply Filters for post content....
        $meta = apply_filters('the_content', $post->post_content);
        $meta = strip_tags($meta);
        $meta = strip_shortcodes($meta );
        $meta = str_replace(array("\n", "\r", "\t"), ' ', $meta);
        $meta = substr($meta, 0, 175);
echo '<meta name="description" content="'. $meta . '"/>'; 
echo '<meta name="og:description" content="'. $meta . '"/>';
echo '<meta name="twitter:description" content="'. $meta . '"/>';
}
}
else {
echo '<meta name="description" content="Milyin Devotes to Make A World Having Vast Majority Of People Who are Passionate About There Work, Who feel proud to have different Thoughts, Beliefs and Opinions. Milyin Supports all those who Improve Society and bring a change."/>'; 
echo '<meta name="og:description" content="Milyin Devotes to Make A World Having Vast Majority Of People Who are Passionate About There Work, Who feel proud to have different Thoughts, Beliefs and Opinions. Milyin Supports all those who Improve Society and bring a change."/>';
echo '<meta name="twitter:description" content="Milyin Devotes to Make A World Having Vast Majority Of People Who are Passionate About There Work, Who feel proud to have different Thoughts, Beliefs and Opinions. Milyin Supports all those who Improve Society and bring a change."/>';

}
 }
add_action('wp_head', 'Milyin_Head');


//This Function is Now Over, the Next Function Generates the Table Of Content

// Below is the Table Of Content Class, i added this for the sake of someone who wants to actually understand and in depth analyse my code. Its better to just move to bottom where i Apply The Filter

class TableOfContents {

    /**
     * Counts the occurence of header elements in Wordpress content
     * 
     * @param type $content
     * @return null|boolean|array
     */
    static function hasToc($tiers, $content) {

        $pattern = '/<h[1-' . $tiers . ']*[^>]*>(.*?)<\/h([1-' . $tiers . '])>/';
        $return = array();
        if (empty($content))
            return null;

        if (!preg_match_all($pattern, $content, $return)) {
            return false;
        }
        return $return;
    }

    /**
     * Generates a table of content only when singular pages are being viewed
     * 
     * @param type $tiers
     * @param type $text
     */
    static function generateTableOfContents($tiers, $content, $draw = TRUE, $return = array()) {

        if (!is_singular())
            return $content;


        $content = $toc . $content;
        $searches = array();
        $replaces = array();
        $return = (is_array($return) && !empty($return) ) ? $return : TableOfContents::hasToc($tiers, $content);

        if ($draw && !empty($return)):
             $toc = '<div class="Milyin-Container">';
            $toc .= "<span style=\"font-size:18px;\">Table of Contents</span>";
            $toc .= "<span style=\"float:right; width: 30px;height: 30px;margin: 5px;\" data-toggle=\"collapse\" data-target=\".list\">";
    $toc .= '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"><g><g><path d="M491.318,235.318H20.682C9.26,235.318,0,244.577,0,256s9.26,20.682,20.682,20.682h470.636    c11.423,0,20.682-9.259,20.682-20.682C512,244.578,502.741,235.318,491.318,235.318z"/></g></g><g><g><path d="M491.318,78.439H20.682C9.26,78.439,0,87.699,0,99.121c0,11.422,9.26,20.682,20.682,20.682h470.636    c11.423,0,20.682-9.26,20.682-20.682C512,87.699,502.741,78.439,491.318,78.439z"/></g></g><g><g><path d="M491.318,392.197H20.682C9.26,392.197,0,401.456,0,412.879s9.26,20.682,20.682,20.682h470.636    c11.423,0,20.682-9.259,20.682-20.682S502.741,392.197,491.318,392.197z"/></g></g></svg></span>' ;
            $toc .= "<div class=\"list collapse\">";
            $toc .= "<ul class=\"parent start\">";
            $tags = reset($return);
            $titles = $return[1];
            $url = $return[1];
            $levels = end($return);
            $_level = 2;
            $chapters = array('0','0','0','0','0','0');

            $count = 0;
            foreach ($tags as $i => $htag) {
                $count++;
                $attributes = array();
                $href = $url[$i];
                    $href = strtolower($href);
                    strip_tags($href);
                    $href = preg_replace("/[^a-z0-9_\s-]/", "", $href);
                    $href = preg_replace("/[\s-]+/", " ", $href);
                    $href = preg_replace("/[\s_]/", "-", $href);


                $newId = 'id="' . $href . '"';
                $newhtag = $newId . '>';
                $htagr = str_replace('>' . $titles[$i], "\t" . $newhtag  . $titles[$i], $htag);
                $searches[] = $htag;
                $replaces[] = $htagr;


                if ((int)$levels[$i] === (int)$_level):
                        $chapters[$_level-1] = ((int)$chapters[$_level-1]+1);
                        $chapter = implode('.', array_slice($chapters, 1, ($levels[$i]-1)  ) );
                        $toc .= '<li><span>' . strval($chapter) . '</span> <a href="#' . $href . '">' . $titles[$i] . '</a></li>';
                endif;

                if ($levels[$i] > $_level) {
                    $_steps = ((int) $levels[$i] - (int) $_level);

                    for ($j = 0; $j < $_steps; $j++):
                        $toc .= '<ol class="continue">';
                        $chapters[$levels[$i]-1+$j] = (int)$chapters[$levels[$i]-1+$j]+1;
                        $_level++;
                    endfor;
                    $chapter = implode('.', array_slice($chapters, 1, ($levels[$i]-1)  ) );
                        $toc .= '<li><a href="#' . $href . '">' . $titles[$i] . '</a></li>';
                }

                if ($levels[$i] < $_level) {

                    $_steps = ((int) $_level - (int) $levels[$i]);
                    $chapters[$levels[$i]-1] = (int)$chapters[$levels[$i]-1]+1;
                    $_olevel = $_level;
                    for ($j = 0; $j < $_steps; $j++):
                        $chapters[$levels[$i]+$j] = 0;
                        $toc .= '</ol>';
                        $_level--;
                    endfor;

                    $chapters[$_olevel-1] = 0;
                    $chapter = implode('.', array_slice($chapters, 1, ($levels[$i]-1)  ) );

                        $toc .= '<li><a href="#' . $href . '">' . $titles[$i] . '</a></li>';

                }
            }
            $toc .= '</ul>';
            $toc .= '</div></div><div class="clear"></div>';
            $content = str_replace($searches, $replaces, $content);
            $content = $toc . $content;
        endif;

        return $content;
    }

    /**
     * Appends the table of content to the $content
     * AKA. Executes our filter
     * 
     * @param type $content
     * @return type
     */
    static function writeToc($content) {

        $content = TableOfContents::generateTableOfContents(4, $content, TRUE);
        return $content;
    }

}

add_filter('the_content', array('TableOfContents', 'writeTOC'), 100);

// The Above Line Adds the Table Of Content Before The Post Content
// Problem is that in the first function of code, i want it to exclude this filter. I don't want the Table Of Content text to become my Meta Description


?>

2

You can temporarily detach the function from the hook.

    // THIS IS MY PROBLEM LINE, i USE Apply Filters for post content....

    $priority = has_filter('the_content', ['TableOfContents', 'writeTOC'] );
    if ( $priority !== false )
        remove_filter('the_content', ['TableOfContents', 'writeTOC'], $priority );

    $meta = apply_filters('the_content', $post->post_content);

    if ( $priority !== false )
        add_filter('the_content', ['TableOfContents', 'writeTOC'], $priority );


    $meta = strip_tags($meta);
    $meta = strip_shortcodes($meta );

Codex:

| improve this answer | |
  • Hey Thanks, man it solved my purpose in first attempt – Aditya Agarwal Dec 12 '19 at 10:53
0

There might be a better way to do this, but without knowing the full extent of the process (other than the ToC), here's a quick and simple way that might solve the problem.

Before the content is filtered for the ToC, why not put the original content into a variable you can pick up later?

I edited your code an added a static variable $pre_toc_content. Then, when the generateTableOfContents() function is run, at the beginning before anything else is done to it, the unfiltered content is put into the variable.

You can pick up the unfiltered content to use later, instead of the filtered result:

    $meta = TableOfContents::$pre_toc_content;
    $meta = strip_tags($meta);
    $meta = strip_shortcodes($meta );
    $meta = str_replace(array("\n", "\r", "\t"), ' ', $meta);
    $meta = substr($meta, 0, 144);

Here's your code with the change (it's relatively minor, and commented accordingly):

<?php
function Milyin_Head(){ 

global $post; 
if (!is_page()) {   
    if (!is_singular() ) {return; }
    elseif (!empty( $post->post_excerpt)) {
        $meta = $post->post_excerpt ;   
} 
    else {
        // THIS IS MY PROBLEM LINE, i USE Apply Filters for post content....
        // $meta = apply_filters('the_content', $post->post_content);

        // Trying it here with a static variable 
        $meta = TableOfContents::$pre_toc_content;

        // Or uncomment below to use a global variable
        global $global_pre_toc_content;
        // $meta = $global_pre_toc_content;

        $meta = strip_tags($meta);
        $meta = strip_shortcodes($meta );
        $meta = str_replace(array("\n", "\r", "\t"), ' ', $meta);
        $meta = substr($meta, 0, 175);
echo '<meta name="description" content="'. $meta . '"/>'; 
echo '<meta name="og:description" content="'. $meta . '"/>';
echo '<meta name="twitter:description" content="'. $meta . '"/>';
}
}
else {
echo '<meta name="description" content="Milyin Devotes to Make A World Having Vast Majority Of People Who are Passionate About There Work, Who feel proud to have different Thoughts, Beliefs and Opinions. Milyin Supports all those who Improve Society and bring a change."/>'; 
echo '<meta name="og:description" content="Milyin Devotes to Make A World Having Vast Majority Of People Who are Passionate About There Work, Who feel proud to have different Thoughts, Beliefs and Opinions. Milyin Supports all those who Improve Society and bring a change."/>';
echo '<meta name="twitter:description" content="Milyin Devotes to Make A World Having Vast Majority Of People Who are Passionate About There Work, Who feel proud to have different Thoughts, Beliefs and Opinions. Milyin Supports all those who Improve Society and bring a change."/>';

}
 }
add_action('wp_head', 'Milyin_Head');


//This Function is Now Over, the Next Function Generates the Table Of Content

// Below is the Table Of Content Class, i added this for the sake of someone who wants to actually understand and in depth analyse my code. Its better to just move to bottom where i Apply The Filter

class TableOfContents {

    /**
     * A container for the unfiltered content.
     */
    static $pre_toc_content;

    /**
     * Counts the occurence of header elements in Wordpress content
     * 
     * @param type $content
     * @return null|boolean|array
     */
    static function hasToc($tiers, $content) {

        $pattern = '/<h[1-' . $tiers . ']*[^>]*>(.*?)<\/h([1-' . $tiers . '])>/';
        $return = array();
        if (empty($content))
            return null;

        if (!preg_match_all($pattern, $content, $return)) {
            return false;
        }
        return $return;
    }

    /**
     * Generates a table of content only when singular pages are being viewed
     * 
     * @param type $tiers
     * @param type $text
     */
    static function generateTableOfContents($tiers, $content, $draw = TRUE, $return = array()) {

        if (!is_singular())
            return $content;

        $content = $toc . $content;
        $searches = array();
        $replaces = array();
        $return = (is_array($return) && !empty($return) ) ? $return : TableOfContents::hasToc($tiers, $content);

        if ($draw && !empty($return)):
             $toc = '<div class="Milyin-Container">';
            $toc .= "<span style=\"font-size:18px;\">Table of Contents</span>";
            $toc .= "<span style=\"float:right; width: 30px;height: 30px;margin: 5px;\" data-toggle=\"collapse\" data-target=\".list\">";
    $toc .= '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve"><g><g><path d="M491.318,235.318H20.682C9.26,235.318,0,244.577,0,256s9.26,20.682,20.682,20.682h470.636    c11.423,0,20.682-9.259,20.682-20.682C512,244.578,502.741,235.318,491.318,235.318z"/></g></g><g><g><path d="M491.318,78.439H20.682C9.26,78.439,0,87.699,0,99.121c0,11.422,9.26,20.682,20.682,20.682h470.636    c11.423,0,20.682-9.26,20.682-20.682C512,87.699,502.741,78.439,491.318,78.439z"/></g></g><g><g><path d="M491.318,392.197H20.682C9.26,392.197,0,401.456,0,412.879s9.26,20.682,20.682,20.682h470.636    c11.423,0,20.682-9.259,20.682-20.682S502.741,392.197,491.318,392.197z"/></g></g></svg></span>' ;
            $toc .= "<div class=\"list collapse\">";
            $toc .= "<ul class=\"parent start\">";
            $tags = reset($return);
            $titles = $return[1];
            $url = $return[1];
            $levels = end($return);
            $_level = 2;
            $chapters = array('0','0','0','0','0','0');

            $count = 0;
            foreach ($tags as $i => $htag) {
                $count++;
                $attributes = array();
                $href = $url[$i];
                    $href = strtolower($href);
                    strip_tags($href);
                    $href = preg_replace("/[^a-z0-9_\s-]/", "", $href);
                    $href = preg_replace("/[\s-]+/", " ", $href);
                    $href = preg_replace("/[\s_]/", "-", $href);


                $newId = 'id="' . $href . '"';
                $newhtag = $newId . '>';
                $htagr = str_replace('>' . $titles[$i], "\t" . $newhtag  . $titles[$i], $htag);
                $searches[] = $htag;
                $replaces[] = $htagr;


                if ((int)$levels[$i] === (int)$_level):
                        $chapters[$_level-1] = ((int)$chapters[$_level-1]+1);
                        $chapter = implode('.', array_slice($chapters, 1, ($levels[$i]-1)  ) );
                        $toc .= '<li><span>' . strval($chapter) . '</span> <a href="#' . $href . '">' . $titles[$i] . '</a></li>';
                endif;

                if ($levels[$i] > $_level) {
                    $_steps = ((int) $levels[$i] - (int) $_level);

                    for ($j = 0; $j < $_steps; $j++):
                        $toc .= '<ol class="continue">';
                        $chapters[$levels[$i]-1+$j] = (int)$chapters[$levels[$i]-1+$j]+1;
                        $_level++;
                    endfor;
                    $chapter = implode('.', array_slice($chapters, 1, ($levels[$i]-1)  ) );
                        $toc .= '<li><a href="#' . $href . '">' . $titles[$i] . '</a></li>';
                }

                if ($levels[$i] < $_level) {

                    $_steps = ((int) $_level - (int) $levels[$i]);
                    $chapters[$levels[$i]-1] = (int)$chapters[$levels[$i]-1]+1;
                    $_olevel = $_level;
                    for ($j = 0; $j < $_steps; $j++):
                        $chapters[$levels[$i]+$j] = 0;
                        $toc .= '</ol>';
                        $_level--;
                    endfor;

                    $chapters[$_olevel-1] = 0;
                    $chapter = implode('.', array_slice($chapters, 1, ($levels[$i]-1)  ) );

                        $toc .= '<li><a href="#' . $href . '">' . $titles[$i] . '</a></li>';

                }
            }
            $toc .= '</ul>';
            $toc .= '</div></div><div class="clear"></div>';
            $content = str_replace($searches, $replaces, $content);
            $content = $toc . $content;
        endif;

        return $content;
    }

    /**
     * Appends the table of content to the $content
     * AKA. Executes our filter
     * 
     * @param type $content
     * @return type
     */
    static function writeToc($content) {

        // Put original $content into a var you can pick up later
        self::$pre_toc_content = $content;

        // Or alternatively, use a global
        global $global_pre_toc_content;
        $global_pre_toc_content = $content;

        $content = TableOfContents::generateTableOfContents(4, $content, TRUE);
        return $content;
    }

}

add_filter('the_content', array('TableOfContents', 'writeTOC'), 100);

// The Above Line Adds the Table Of Content Before The Post Content
// Problem is that in the first function of code, i want it to exclude this filter. I don't want the Table Of Content text to become my Meta Description


?>
| improve this answer | |
  • Hey Thanks for helping. Urs seems a good idea to assign a variable to the content before adding TOC. But for me, it didnt work. Upon checking the output was just content="" – Aditya Agarwal Dec 11 '19 at 13:38
  • I edited the answer though to move where it would load the content into $pre_toc_content to do it in the writeTOC() function instead. That might work (better)? I usually work with instantiated classes instead of static, so I'm not 100% sure I've got it right. – butlerblog Dec 11 '19 at 14:11
  • Sorry for late reply it doesnt work, can't we simply remove the filter, then execute the function and then add the filter again... Or can't we assign it as a global variable. I think trying some thing different may help... – Aditya Agarwal Dec 11 '19 at 15:56
  • Assigning it as a global would be similar, so that would/should work. – butlerblog Dec 11 '19 at 16:15
  • I am new to php, so request u to help me with that... How can we do it.... should i just do global $toc = the_content(); – Aditya Agarwal Dec 11 '19 at 16:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.