I have created a table of content filter hook which matched the header tag and put it in the table of content div. The div
renders before the the_content
filter. But, I am trying to render it in a specific div
.
The part of single.php where I want to render the table of content is as below:
<div class="container programs">
<div class="my-4">
<h2 class="title-underline"><?php echo the_title(); ?></h2>
</div>
<div class="overview-nav">
<div>
<h3>Overview</h3>
<p><?php the_excerpt(); ?></p>
</div>
//Part where table of content should render. Unfortunately the below code does not work
<?php
if(function_exists("add_table_of_content")){
add_table_of_content();
}
?>
</div>
<?php the_content(); ?>
</div>
The function for table of content is as below:
//Table of Content
function get_toc($content) {
$headings = get_headings($content);
if(count($headings)>0){
ob_start();
echo "<div class='table-of-contents'>";
echo "<div class='heading'>";
echo toc_print($headings, 0);
echo "</div>";
echo "</div>";
return ob_get_clean();
}
return "";
}
function single_heading($heading, $flags){
if($heading['tag'] == 2 && $flags[0]){
}
elseif($heading['tag'] == 3 && $flags[1]){
}
elseif($heading['tag'] == 4 && $flags[2]){
}
elseif($heading['tag'] == 5 && $flags[3]){
}
elseif($heading['tag'] == 6 && $flags[4]){
}
else{
return "";
}
return "<li>"."<a href=#".str_replace(" ", "_", $heading['name']).">".$heading['name']."</a>"."</li>";
}
function toc_print( $a, $depth) {
$flags = array(
get_theme_mod("toc_heading2", 1),
get_theme_mod("toc_heading3", 1),
get_theme_mod("toc_heading4", 1),
get_theme_mod("toc_heading5", 1),
get_theme_mod("toc_heading6", 1),
);
$r = "<ul>";
$depth = 2;
$depth_save = 2;
foreach($a as $key => $tag){
if($tag['tag']==$depth){
$r = $r.single_heading($tag, $flags);
}
elseif($tag['tag']>$depth){
$r = $r.str_repeat("<li><ul>", $tag['tag']-$depth).single_heading($tag, $flags);
$depth = $tag['tag'];
}
else{
$r = $r.str_repeat("</ul></li>", $depth - $tag['tag']).single_heading($tag, $flags);
$depth = $tag['tag'];
}
}
$r = $r.str_repeat("</ul>", $depth-$depth_save+1);
return $r;
}
function get_headings($content) {
$headings = array();
preg_match_all("/<h([1-6])(.*)>(.*)</h[1-6]>/", $content, $matches);
for($i = 0; $i < count($matches[1]); $i++) {
$headings[$i]["tag"] = $matches[1][$i];
$att_string = $matches[2][$i];
preg_match("/id="([^"]*)"/", $att_string , $id_matches);
if(count($id_matches)>1){
$headings[$i]["id"] = $id_matches[1];
}
$att_string = $matches[2][$i];
preg_match_all("/class="([^"]*)"/", $att_string , $class_matches);
for($j = 0; $j < count($class_matches[1]); $j++) {
$headings[$i]["classes"][] = $class_matches[1][$j];
}
$headings[$i]["name"] = $matches[3][$i];
}
return $headings;
}
function headingwraps( $matches ) {
$headings = array();
if(count($matches)>2){
foreach($matches[2] as $key => $heading){
$h = "<h".$matches[1][$key]." ";
$h = $h." ".$heading." ";
$h = $h.">";
$h = $h."<span class='toc-span' id='".str_replace(" ", "_", $matches[3][$key])."'></span>";
$h = $h.$matches[3][$key];
$h = $h."<span class='toc-span-end' ></span>";
$h = $h."</h".$matches[1][$key].">";
array_push($headings, $h);
}
return $headings;
}
return $headings;
}
function add_table_of_content($content) {
if (get_post_type()!="post") return $content;
$result = preg_match_all("/<h([1-6])(.*)>(.*)</h[1-6]>/", $content, $matches);
$headingwrapped = headingwraps($matches);
$paragraphs = explode("</p>", $content);
$paragraphs_count = count($paragraphs);
$new_content = '';
for ($i = 0; $i < $paragraphs_count; $i++) {
if ($i === 0) {
$new_content .= get_toc($content);
}
$new_content .= $paragraphs[$i] . "</p>";
}
foreach($headingwrapped as $key => $headingrep){
$new_content = str_replace($matches[0][$key], $headingrep, $new_content);
}
return $new_content;
}
add_filter('the_content', 'add_table_of_content');
I tried to use add_shortcode filter hook to create a shortcode and put that shortcode to that specific div.
<?php echo do_shortocode("add_tale_of_content"); ?>
This did not work.
Updated code using shortcode
//in function.php
add_shortcode('the_content', 'add_table_of_content');
//to render in front end
<?php do_shortcode('add_table_of_content'); ?>
2
Answers
You have to use the name of the shortcode and not the name of the function.
So if you define your shortcode:
Why do you use shortcode? You can call the function directly with the below changes: