PHP List Of Contents
I want to make List of contents just like in wikipedia. My code:
<?php
$str = "[H1]Top Heading[/H1] My test string [H2]My sub Heading[/H2] My second [H3]My deep Heading[/H3] string now again [H1]Top Heading[/H1] My test string [H2]My sub Heading[/H2] My second [H3]My deep Heading[/H3]";
/**
* Helper class
*/
class FaqHelper {
static $count = 1;
static $listItems = array();
static $prefix = 'faq-';
static function GetList() {
$items = '';
foreach (self::$listItems as $id => $label) {
$items .= '<li><a href="#' . self::$prefix . $id .'">' . $label . '</a></li>';
}
return '<ul><ol>'. $items .'</ul></ol>';
}
}
// the callback function
function make_faq($matches)
{
$id = FaqHelper::$count;
$label = $matches[1];
FaqHelper::$listItems[$id] = $label;
$res = '<span id="'. FaqHelper::$prefix . $id .'">' . $label . '</span>';
FaqHelper::$count++;
return $res;
}
$text = preg_replace_callback(
"#\[H1\]([^\[]+)\[/H1\]#",
"make_faq",
$str
);
$list = FaqHelper::GetList();
echo $list;
echo '<br /><br />';
echo $text;
?>
and this gives
1. Top Heading
2. Top Heading
Top Heading My test string [H2]My sub Heading[/H2] My second [H3]M开发者_如何学Cy deep Heading[/H3] string now again Top Heading My test string [H2]My sub Heading[/H2] My second [H3]My deep Heading[/H3]
but i want this results
1. Top Heading
1.1 My sub Heading
1.1.1 My deep Heading
2. Top Heading
2.1 My sub Heading
2.1.1 My deep Heading
So on ... Top Heading My test string My sub Heading My second My deep Heading string now again Top Heading My test string My sub Heading My second My deep Heading string now again
The basic theory is this.
When you hit your first [H1], you increment the counter to 1. When you hit the h2, your second level counter is incremented to 1. When you hit the h3, your third level counter is incremented to 1.
This will obviously output 1.1.1.
Now when you hit the next h1, they sub levels (ie not the main level) are reset to 0, and then the first level is incremented to 2. You hit the h2, and it goes to 1 again... Then you have first level 2, sub 1, sub 1 = 2.1.1.
Note that this code will only support 3 levels of headings. I'm aware that this solution doesn't scale endlessly and does not support recursive parsing, but unfortunately I don't have time to create the perfect solution for SO questions.
My extended solution based on your last question is below. Please test it and see if it works as expected. Note that I've made the regex that matches the [H1][/H1] tags in case-sensitive so [h1][/h1] also works now.
Again, I apologize if I'm slow or the results are not perfect but I can't be making your entire project, you'll need to do some research yourself, learn it and then do it. Also as the code develops and thickens it will take more time to make further extensions and maintain it, of which I don't always have the capacity to do.
Enjoy!
<?php
$str = "
[h1]Header 1[/h1]Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vitae rutrum tellus. Vestibulum nec nisl eu enim venenatis ornare. Suspendisse a nunc nibh, quis placerat urna. Pellentesque nec odio est. [h2]Header 2[/h2]Morbi et orci non nulla lobortis convallis. Curabitur vestibulum, felis auctor posuere posuere, mauris neque vulputate tellus, vel luctus urna sapien vitae sapien. [h2]Header 2-2[/h2] Integer accumsan lobortis euismod. Integer vitae tempor nisl.
[h1]Header 1[/h1]Mauris varius dolor nec risus viverra egestas. Suspendisse potenti. Nunc consectetur faucibus metus, nec sagittis felis pellentesque non. Ut mattis ligula non [h2]Header 2[/h2] purus vehicula sed tempus risus porttitor. Nullam eget arcu[h3]Header 3[/h3] at mi pulvinar pellentesque eu sed ipsum. Fusce vel laoreet sem. Duis hendrerit ligula iaculis felis hendrerit euismod vel ut mauris. Pellentesque tempus velit et velit cursus sodales. Sed adipiscing vulputate nibh sed venenatis. Quisque sit amet ante velit. Donec dui lectus, ultricies quis interdum eget, elementum vitae nibh. Nullam nec sapien purus, laoreet porta elit. Nam luctus elit sit amet est ultricies eget varius diam ullamcorper. Sed commodo viverra lobortis. Vivamus semper blandit arcu semper pellentesque. Duis interdum tincidunt nisl eget mollis.
[h1]Header 1[/h1]Suspendisse laoreet, tortor sed viverra pellentesque, enim felis tempus ante, sit amet dignissim leo augue non ipsum. Ut eu risus erat. Donec pellentesque ligula ac est tincidunt ullamcorper. [h2]My paragraph again[/h2] Pellentesque eget diam lacus, nec ornare urna. Nulla a interdum augue. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce et justo turpis. ";
class FaqHeading
{
var $heading_level;
var $id;
var $label;
var $children = array();
var $parent = null;
function __construct($heading_level, $id, $label)
{
$this->heading_level = (int) $heading_level;
$this->id = (int) $id;
$this->label = $label;
}
function AddChild(FaqHeading $child)
{
if ($child->heading_level <= $this->heading_level) {
return; // cannot add higher or equal leveld headings as children
}
$child->parent = $this;
$this->children[] = $child;
}
function HasChildren()
{
return (bool) $this->children;
}
}
class FaqHeadingList
{
var $headings = array();
var $current = null;
var $prefix;
function __construct($prefix)
{
$this->prefix = $prefix;
}
function AddHeading($heading_level, $id, $label)
{
$elem = new FaqHeading($heading_level, $id, $label);
if ($this->current == null || $heading_level == 1) {
$this->headings[] = $elem;
} else if ($heading_level == 2 && ($this->current->heading_level == 1)) {
$this->current->AddChild($elem);
} else if ($heading_level == 2 && ($this->current->heading_level == 2)) {
$this->current->parent->AddChild($elem);
} else if ($heading_level == 2 && ($this->current->heading_level == 3)) {
$this->current->parent->parent->AddChild($elem);
} else if ($heading_level == 3 && ($this->current->heading_level == 1)) {
$this->current->AddChild($elem);
} else if ($heading_level == 3 && ($this->current->heading_level == 2)) {
$this->current->AddChild($elem);
} else if ($heading_level == 3 && ($this->current->heading_level == 3)) {
$this->current->parent->AddChild($elem);
}
$this->current = $elem;
}
function ToString()
{
$str = '<ol>';
foreach ($this->headings as $h1)
{
if ($h1->heading_level == 1)
{
$str .= '<li>'. $this->CreateLink($h1->id, $h1->label);
if ($h1->hasChildren())
{
$str .= '<ol>';
foreach ($h1->children as $h2)
{
$str .= '<li>' . $this->CreateLink($h2->id, $h2->label);
if ($h2->hasChildren())
{
$str .= '<ol>';
foreach ($h2->children as $h3)
{
$str .= '<li>'. $this->CreateLink($h3->id, $h3->label) .'</li>';
}
$str .= '</ol>';
}
$str .= '</li>';
}
$str .= '</ol>';
}
$str .= '</li>';
}
}
$str .= '</ol>';
return $str;
}
function CreateLink($id, $label)
{
return '<a href="#' . $this->prefix . $id .'">' . $label . '</a>';
}
}
/**
* Helper class
*/
class FaqHelper
{
static $count = 1;
static $headingList;
static $prefix = 'faq-';
static function Init()
{
self::$headingList = new FaqHeadingList(self::$prefix);
}
static function ReplaceCallback($matches)
{
$id = self::$count;
$heading_level = $matches[1];
$label = $matches[2];
self::$headingList->AddHeading($heading_level, $id, $label);
$res = '<span id="'. self::$prefix . $id .'">' . $label . '</span>';
self::$count++;
return $res;
}
}
FaqHelper::init();
$text = preg_replace_callback(
"#\[H([0-9]+)\]([^\[]+)\[/H\\1\]#i",
array('FaqHelper', "ReplaceCallback"),
$str
);
$list = FaqHelper::$headingList->ToString();
echo $list;
echo '<br /><br />';
echo nl2br($text);
?>
Should output:
1. Header 1
1. Header 2
2. Header 2-2
2. Header 1
1. Header 2
1. Header 3
3. Header 1
1. My paragraph again
Header 1Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vitae rutrum tellus. Vestibulum nec nisl eu enim venenatis ornare. Suspendisse a nunc nibh, quis placerat urna. Pellentesque nec odio est. Header 2Morbi et orci non nulla lobortis convallis. Curabitur vestibulum, felis auctor posuere posuere, mauris neque vulputate tellus, vel luctus urna sapien vitae sapien. Header 2-2 Integer accumsan lobortis euismod. Integer vitae tempor nisl.
Header 1Mauris varius dolor nec risus viverra egestas. Suspendisse potenti. Nunc consectetur faucibus metus, nec sagittis felis pellentesque non. Ut mattis ligula non Header 2 purus vehicula sed tempus risus porttitor. Nullam eget arcuHeader 3 at mi pulvinar pellentesque eu sed ipsum. Fusce vel laoreet sem. Duis hendrerit ligula iaculis felis hendrerit euismod vel ut mauris. Pellentesque tempus velit et velit cursus sodales. Sed adipiscing vulputate nibh sed venenatis. Quisque sit amet ante velit. Donec dui lectus, ultricies quis interdum eget, elementum vitae nibh. Nullam nec sapien purus, laoreet porta elit. Nam luctus elit sit amet est ultricies eget varius diam ullamcorper. Sed commodo viverra lobortis. Vivamus semper blandit arcu semper pellentesque. Duis interdum tincidunt nisl eget mollis.
Header 1Suspendisse laoreet, tortor sed viverra pellentesque, enim felis tempus ante, sit amet dignissim leo augue non ipsum. Ut eu risus erat. Donec pellentesque ligula ac est tincidunt ullamcorper. My paragraph again Pellentesque eget diam lacus, nec ornare urna. Nulla a interdum augue. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce et justo turpis.
精彩评论