1212 * @since 4.2.3
1313 */
1414class TableOfContents extends Blocks {
15+ /**
16+ * Initializes our blocks.
17+ *
18+ * @since 4.9.0
19+ *
20+ * @return void
21+ */
22+ public function init () {
23+ $ this ->register ();
24+
25+ // Enqueue the block's assets.
26+ add_action ( 'enqueue_block_assets ' , [ $ this , 'enqueueBlockAssets ' ] );
27+ }
28+
1529 /**
1630 * Register the block.
1731 *
@@ -20,6 +34,164 @@ class TableOfContents extends Blocks {
2034 * @return void
2135 */
2236 public function register () {
23- aioseo ()->blocks ->registerBlock ( 'aioseo/table-of-contents ' );
37+ aioseo ()->blocks ->registerBlock ( 'table-of-contents ' , [
38+ 'render_callback ' => [ $ this , 'render ' ]
39+ ] );
40+ }
41+
42+ /**
43+ * Enqueues the block's assets.
44+ *
45+ * @since 4.9.0
46+ *
47+ * @return void
48+ */
49+ public function enqueueBlockAssets () {
50+ aioseo ()->core ->assets ->load ( 'src/vue/standalone/blocks/table-of-contents/frontend.js ' );
51+ }
52+
53+ /**
54+ * Get the default attributes for the block.
55+ *
56+ * @since 4.9.0
57+ *
58+ * @return array
59+ */
60+ private function getDefaultAttributes () {
61+ return [
62+ 'listStyle ' => 'ul ' ,
63+ 'collapsibleType ' => 'off ' ,
64+ 'collapsed ' => false ,
65+ 'collapsedTitle ' => __ ( 'Show Table of Contents ' , 'all-in-one-seo-pack ' ),
66+ 'expandedTitle ' => __ ( 'Hide Table of Contents ' , 'all-in-one-seo-pack ' ),
67+ 'mode ' => null ,
68+ 'headings ' => [],
69+ 'reOrdered ' => false
70+ ];
71+ }
72+
73+ /**
74+ * Get the nested headings for the block.
75+ *
76+ * @since 4.9.0
77+ *
78+ * @param array $headings The headings to get.
79+ * @param string $listStyle The list style to use.
80+ *
81+ * @return string
82+ */
83+ private function getNestedHeadings ( $ headings , $ listStyle ) {
84+ $ htmlString = '< ' . $ listStyle . '> ' ;
85+
86+ foreach ( $ headings as $ heading ) {
87+ if ( $ heading ['hidden ' ] ) {
88+ continue ;
89+ }
90+
91+ $ listItem = '<li> ' ;
92+
93+ $ content = empty ( $ heading ['editedContent ' ] ) ? $ heading ['content ' ] : $ heading ['editedContent ' ];
94+
95+ $ listItem .= '<a class="aioseo-toc-item" href="# ' . esc_attr ( $ heading ['anchor ' ] ) . '"> ' . esc_html ( $ content ) . '</a> ' ;
96+
97+ if ( ! empty ( $ heading ['headings ' ] ) ) {
98+ $ listItem .= $ this ->getNestedHeadings ( $ heading ['headings ' ], $ listStyle );
99+ }
100+
101+ $ listItem .= '</li> ' ;
102+
103+ $ htmlString .= $ listItem ;
104+ }
105+
106+ $ htmlString .= '</ ' . $ listStyle . '> ' ;
107+
108+ return $ htmlString ;
109+ }
110+
111+ /**
112+ * Get the collapsed icon for the block.
113+ *
114+ * @since 4.9.0
115+ *
116+ * @return string
117+ */
118+ private function getCollapsedIcon () {
119+ return '<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
120+ <path d="M6 8H0V6H6V0H8V6H14V8H8V14H6V8Z" fill="#005AE0"/>
121+ </svg> ' ;
122+ }
123+
124+ /**
125+ * Get the expanded icon for the block.
126+ *
127+ * @since 4.9.0
128+ *
129+ * @return string
130+ */
131+ private function getExpandedIcon () {
132+ return '<svg width="14" height="2" viewBox="0 0 14 2" fill="none" xmlns="http://www.w3.org/2000/svg">
133+ <path d="M0 2V0H14V2H0Z" fill="#005AE0"/>
134+ </svg> ' ;
135+ }
136+
137+ /**
138+ * Get the HTML for the block.
139+ *
140+ * @since 4.9.0
141+ *
142+ * @param array $attributes The attributes for the block.
143+ *
144+ * @return string
145+ */
146+ private function getHtml ( $ attributes ) {
147+ $ htmlString = $ this ->getNestedHeadings ( $ attributes ['headings ' ], $ attributes ['listStyle ' ] );
148+ $ class1 = 'open ' === $ attributes ['collapsibleType ' ] ? 'aioseo-toc-collapsed ' : '' ;
149+ $ class2 = 'closed ' === $ attributes ['collapsibleType ' ] ? 'aioseo-toc-collapsed ' : '' ;
150+ $ class3 = 'closed ' === $ attributes ['collapsibleType ' ] ? 'aioseo-toc-collapsed ' : '' ;
151+ $ blockCustomClass = isset ( $ attributes ['className ' ] ) ? $ attributes ['className ' ] : '' ;
152+
153+ $ fullHtmlString = '<div class=" ' . $ blockCustomClass . '">
154+ <div class="aioseo-toc-header">
155+ <header class="aioseo-toc-header-area">
156+ <div class="aioseo-toc-header-title aioseo-toc-header-collapsible-closed ' . $ class1 . '">
157+ <div class="aioseo-toc-header-collapsible">
158+ ' . $ this ->getCollapsedIcon () . '
159+ </div>
160+ ' . esc_html ( $ attributes ['collapsedTitle ' ] ) . '
161+ </div>
162+
163+ <div class="aioseo-toc-header-title aioseo-toc-header-collapsible-open ' . $ class2 . '">
164+ <div class="aioseo-toc-header-collapsible">
165+ ' . $ this ->getExpandedIcon () . '
166+ </div>
167+ ' . esc_html ( $ attributes ['expandedTitle ' ] ) . '
168+ </div>
169+ </header>
170+ <div class="aioseo-toc-contents ' . $ class3 . '">
171+ ' . $ htmlString . '
172+ </div>
173+ </div>
174+ </div> ' ;
175+
176+ $ fullHtmlString = 'off ' === $ attributes ['collapsibleType ' ] ? $ htmlString : $ fullHtmlString ;
177+
178+ return $ fullHtmlString ;
179+ }
180+
181+ /**
182+ * Render the block.
183+ *
184+ * @since 4.9.0
185+ *
186+ * @param array $attributes The attributes for the block.
187+ *
188+ * @return string
189+ */
190+ public function render ( $ attributes ) {
191+ if ( empty ( $ attributes ['headings ' ] ) ) {
192+ return null ;
193+ }
194+
195+ return $ this ->getHtml ( array_merge ( $ this ->getDefaultAttributes (), $ attributes ) );
24196 }
25197}
0 commit comments