PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 3.6.1
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v3.6.1
4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.5.2 All 199 releases
betterdocs / includes / Shortcodes / ToC.php

ToC.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 3.6.1, at includes/Shortcodes/ToC.php

132 lines 5.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDeveloper\BetterDocs\Shortcodes;
4
5 use WPDeveloper\BetterDocs\Utils\Node;
6 use WPDeveloper\BetterDocs\Core\Shortcode;
7
8 class ToC extends Shortcode {
9 protected $html_attributes = [];
10
11 public function get_name() {
12 return 'betterdocs_toc';
13 }
14
15 public function get_style_depends() {
16 return ['betterdocs-toc'];
17 }
18
19 /**
20 * Summary of default_attributes
21 * @return array
22 */
23 public function default_attributes() {
24 return [
25 'post_type' => 'docs',
26 'post_id' => get_the_ID(),
27 'htags' => '1,2,3,4,5,6',
28 'hierarchy' => '',
29 'list_number' => '',
30 'collapsible_on_mobile' => $this->settings->get( 'collapsible_toc_mobile', false ),
31 'toc_title' => ''
32 ];
33 }
34
35 public function render( $atts, $content = null ) {
36 $this->views( 'shortcodes/toc' );
37 }
38
39 public function view_params() {
40 return [
41 'post' => get_post( $this->attributes['post_id'] )
42 ];
43 }
44
45 /**
46 * This method is responsible for re-arranging the TOC data based on hierarchy or non-hierarchy
47 *
48 * @param string $post_content
49 * @param string $htag_support
50 * @return Node|null
51 */
52 public function format_toc_data( $post_content, $htag_support, $toc_hierarchy ) {
53 $matches = [];
54
55 if ( $htag_support != '' ) {
56 preg_match_all( '/(<h([' . $htag_support . ']{1})[^>]*>).*<\/h\2>/msuU', $post_content, $matches, PREG_SET_ORDER );
57 }
58
59 if ( ! empty( $matches ) ) {
60 /*
61 |--------------------------------------------------------------------------
62 | Backtracking Algorithm Using Iteration | Main Login For Hierarchy TOC
63 |--------------------------------------------------------------------------
64 |
65 | Initially an object with key null and empty item of arrays are inserted into the stack of arrays.
66 | When inside the loop condition for the first time, the last stack value is assigned in a variable $last_data.
67 | And a new node object $new_data which is instantiated and the tag number is inserted for comparison as key, and empty items
68 | as a array are inserted into items property of the new node object. On the 'if' condition it checks, if the current tag number
69 | is smaller or equal to the last stack number. If the condition is true, the it enters into the while loop condition, which also
70 | checks if the current last stack tag number is greater or equal to the current tag number. It pops values from the stack until and unless the
71 | condition becomes false. The while loop condition becomes false only when the last stack value tag number becomes null and the last stack number is not
72 | greater or equal to the current node tag number.
73 |
74 | Backtracking occurs when the current tag_number $number[2] is less than or equal to the stacks last tag_number which is assigned as $last_data
75 |
76 | And then the last value is inserted as the new last_data, and the new_data node is inserted into the last_data node items.
77 | Additionally the $new_data is inserted into the stack to keep track of the used node. Somehow if the if condition becomes false
78 | then the stack last data is taken, and the new_data is inserted into the last_data->items and the new_data is inserted into the stack.
79 |
80 */
81
82 $dynamic_toc_title_switch = $this->settings->get( 'toc_dynamic_title' );
83 $stack = [];
84 $root = new Node();
85 $root->key = null;
86 $root->items = [];
87 $tag_counter = 0;
88
89 array_push( $stack, $root );
90
91 foreach ( $matches as $number ) {
92 $last_data = $stack[count( $stack ) - 1];
93 $current_tag_number = isset( $number[2] ) ? $number[2] : '';
94 $current_title = isset( $number[0] ) ? $number[0] : '';
95 $current_tag = isset( $number[1] ) ? $number[1] : '';
96
97 $heading_name = preg_replace( '/<[^<]+?>/', '', $current_title );
98 $heading_name = ! empty( $heading_name ) ? strtolower( str_replace( " ", '-', preg_replace( '/[^\p{L}\p{N}\s]/u', "", $heading_name ) ) ) : '';
99 preg_match('/id="(.+?)"/', $current_title, $matches_id);
100 $heading_id = isset( $matches_id[1] ) ? strtolower( $matches_id[1] ) : '';
101 $tag_number = ! empty( $heading_id ) ? $heading_id : ( ! empty( $heading_name ) && $this->settings->get( 'toc_dynamic_title' ) ? $heading_name : $tag_counter . '-toc-title' );
102
103 $new_data = new Node();
104 $new_data->key = $current_tag_number;
105 $new_data->tag = $current_tag;
106 $new_data->title = $current_title;
107 $new_data->tag_number = $tag_number;
108 $new_data->items = [];
109
110 if ( $last_data->key != null && $current_tag_number <= $last_data->key ) {
111 while ( $stack[count( $stack ) - 1]->key != null && $stack[count( $stack ) - 1]->key >= $current_tag_number ) {
112 array_pop( $stack );
113 }
114 $last_data = $stack[count( $stack ) - 1];
115 }
116
117 array_push( $last_data->items, $new_data );
118
119 if ( $toc_hierarchy != 'off' && $toc_hierarchy != '' ) {
120 array_push( $stack, $new_data );
121 }
122
123 $tag_counter++;
124 }
125
126 return $root;
127 }
128
129 return null;
130 }
131 }
132