PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 1.7.3
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v1.7.3
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 / public / class-betterdocs-public.php

class-betterdocs-public.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 1.7.3, at public/class-betterdocs-public.php

434 lines 15.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * The public-facing functionality of the plugin.
5 *
6 * @link https://wpdeveloper.net
7 * @since 1.0.0
8 *
9 * @package BetterDocs
10 * @subpackage BetterDocs/public
11 */
12
13 /**
14 * The public-facing functionality of the plugin.
15 *
16 * Defines the plugin name, version, and two examples hooks for how to
17 * enqueue the public-facing stylesheet and JavaScript.
18 *
19 * @package BetterDocs
20 * @subpackage BetterDocs/public
21 * @author WPDeveloper <support@wpdeveloper.net>
22 */
23 class BetterDocs_Public {
24
25 /**
26 * The ID of this plugin.
27 *
28 * @since 1.0.0
29 * @access private
30 * @var string $plugin_name The ID of this plugin.
31 */
32 private $plugin_name;
33
34 /**
35 * The version of this plugin.
36 *
37 * @since 1.0.0
38 * @access private
39 * @var string $version The current version of this plugin.
40 */
41 private $version;
42
43 /**
44 * Initialize the class and set its properties.
45 *
46 * @since 1.0.0
47 * @param string $plugin_name The name of the plugin.
48 * @param string $version The version of this plugin.
49 */
50 public function __construct( $plugin_name, $version )
51 {
52 $this->plugin_name = $plugin_name;
53 $this->version = $version;
54 add_action( 'init', array( $this, 'public_hooks' ) );
55
56 }
57
58 /**
59 * Register the stylesheets for the public-facing side of the site.
60 *
61 * @since 1.0.0
62 */
63 public function enqueue_styles()
64 {
65 /**
66 * This function is provided for demonstration purposes only.
67 *
68 * An instance of this class should be passed to the run() function
69 * defined in BetterDocs_Loader as all of the hooks are defined
70 * in that particular class.
71 *
72 * The BetterDocs_Loader will then create the relationship
73 * between the defined hooks and the functions defined in this
74 * class.
75 */
76 wp_enqueue_style( $this->plugin_name, BETTERDOCS_PUBLIC_URL . 'css/betterdocs-public.css', array(), $this->version, 'all' );
77 wp_enqueue_style( 'simplebar', BETTERDOCS_PUBLIC_URL . 'css/simplebar.css', array(), $this->version, 'all' );
78 wp_register_style( 'betterdocs-category-grid', BETTERDOCS_URL . 'includes/elementor/assets/betterdocs-category-grid.css', array(), $this->version, 'all' );
79 wp_register_style( 'betterdocs-category-box', BETTERDOCS_URL . 'includes/elementor/assets/betterdocs-category-box.css', array(), $this->version, 'all' );
80
81 }
82
83 /**
84 * Register the JavaScript for the public-facing side of the site.
85 *
86 * @since 1.0.0
87 */
88 public function enqueue_scripts()
89 {
90 /**
91 * This function is provided for demonstration purposes only.
92 *
93 * An instance of this class should be passed to the run() function
94 * defined in BetterDocs_Loader as all of the hooks are defined
95 * in that particular class.
96 *
97 * The BetterDocs_Loader will then create the relationship
98 * between the defined hooks and the functions defined in this
99 * class.
100 */
101 wp_enqueue_script('masonry');
102 wp_enqueue_script( 'clipboard', BETTERDOCS_PUBLIC_URL . 'js/clipboard.min.js', array( 'jquery' ), $this->version, true );
103 wp_enqueue_script( $this->plugin_name, BETTERDOCS_PUBLIC_URL . 'js/betterdocs-public.js', array( 'jquery' ), $this->version, true );
104 wp_enqueue_script( 'simplebar', BETTERDOCS_PUBLIC_URL . 'js/simplebar.js', array( 'jquery' ), $this->version, true );
105 wp_register_script( 'betterdocs-category-grid', BETTERDOCS_URL . 'includes/elementor/assets/betterdocs-category-grid.js', [ 'jquery','masonry' ], '1.0.0', true );
106 wp_localize_script( $this->plugin_name, 'betterdocspublic', array(
107 'ajax_url' => admin_url( 'admin-ajax.php' ),
108 'post_id' => get_the_ID(),
109 'copy_text' => esc_html__('Copied','betterdocs'),
110 'sticky_toc_offset' => BetterDocs_DB::get_settings('sticky_toc_offset'),
111 'nonce' => wp_create_nonce( 'betterdocs_submit_data' ),
112 ));
113 }
114
115 /**
116 * Register the JavaScript for the public-facing side of the site.
117 *
118 * @since 1.0.0
119 */
120 public function public_hooks()
121 {
122 add_filter( 'archive_template', array( $this, 'get_docs_archive_template' ) );
123 add_filter( 'single_template', array( $this, 'get_docs_single_template' ), 99 );
124 // add_filter( 'template_include', array( $this, 'load_docs_taxonomy_template' ) );
125 $defaults = betterdocs_generate_defaults();
126 if( is_array( $defaults ) && $defaults['betterdocs_docs_layout_select'] === 'layout-2' ) {
127 add_filter( 'betterdocs_doc_page_cat_icon_size2_default', 80 );
128 }
129 if( is_admin() ) {
130 add_filter('plugin_action_links_' . BETTERDOCS_BASENAME, array($this, 'insert_plugin_links'));
131 }
132 }
133
134 /**
135 * Get Archive Template for the docs base directory.
136 *
137 * @since 1.0.0
138 */
139 public function get_docs_archive_template($template)
140 {
141 $docs_layout = get_theme_mod('betterdocs_docs_layout_select', 'layout-1');
142 $tax = BetterDocs_Helper::get_tax();
143 if (is_post_type_archive('docs')) {
144 $docs_layout = get_theme_mod('betterdocs_docs_layout_select', 'layout-1');
145
146 if ( $docs_layout === 'layout-2' ) {
147 $template = BETTERDOCS_PUBLIC_PATH . 'partials/archive-template/category-box.php';
148 } else {
149 $template = BETTERDOCS_PUBLIC_PATH . 'partials/archive-template/category-list.php';
150 }
151 } elseif ($tax === 'doc_category') {
152 $template = BETTERDOCS_PUBLIC_PATH . 'betterdocs-category-template.php';
153 } else if (is_tax('doc_tag')) {
154 $template = BETTERDOCS_PUBLIC_PATH . 'betterdocs-tag-template.php';
155 } else if ($tax === 'knowledge_base' && $docs_layout === 'layout-2') {
156 $template = BETTERDOCS_PUBLIC_PATH . 'partials/archive-template/category-box.php';
157 } else if ($tax === 'knowledge_base') {
158 $template = BETTERDOCS_PUBLIC_PATH . 'partials/archive-template/category-list.php';
159 }
160 return apply_filters('betterdocs_archive_template', $template);
161 }
162
163 /**
164 * Get Category Taxonomy Template for the docs base directory.
165 *
166 * @since 1.0.0
167 */
168 public function get_docs_category_taxonomy_template( $template )
169 {
170 if ( is_tax( 'doc_category' ) ) {
171 $template = BETTERDOCS_PUBLIC_PATH . 'betterdocs-category-template.php';
172 }
173 return apply_filters('betterdocs_category_taxonomy_template', $template);
174 }
175
176 /**
177 * Get Tags Taxonomy Template for the docs base directory.
178 *
179 * @since 1.0.0
180 */
181 public function get_docs_tag_taxonomy_template( $template )
182 {
183 if ( is_tax( 'doc_tag' ) ) {
184 $template = BETTERDOCS_PUBLIC_PATH . 'public/betterdocs-tag-template.php';
185 }
186 return $template;
187 }
188
189 /**
190 * Get Tags Taxonomy Template for the docs base directory.
191 *
192 * @since 1.0.0
193 */
194 public function load_docs_taxonomy_template($template)
195 {
196 $docs_layout = get_theme_mod('betterdocs_docs_layout_select', 'layout-1');
197 $tax = BetterDocs_Helper::get_tax();
198
199 if ($tax === 'doc_category') {
200 $template = BETTERDOCS_PUBLIC_PATH . 'betterdocs-category-template.php';
201 } else if (is_tax('doc_tag')) {
202 $template = BETTERDOCS_PUBLIC_PATH . 'betterdocs-tag-template.php';
203 } else if ($tax === 'knowledge_base' && $docs_layout === 'layout-2') {
204 $template = BETTERDOCS_PUBLIC_PATH . 'partials/archive-template/category-box.php';
205 } else if ($tax === 'knowledge_base') {
206 $template = BETTERDOCS_PUBLIC_PATH . 'partials/archive-template/category-list.php';
207 }
208
209 return $template;
210 }
211
212
213 /**
214 * Get Single Page Template for docs base directory.
215 *
216 * @param int $single_template Overirde single templates.
217 *
218 * @since 1.0.0
219 */
220 public function get_docs_single_template($single_template)
221 {
222 if (is_singular('docs')) {
223 $single_template = plugin_dir_path( dirname( __FILE__ ) ) . 'public/partials/template-single/layout-1.php';
224 }
225 return $single_template;
226 }
227
228 /**
229 * Get supported heading tag from settings
230 *
231 * @since 1.0.0
232 */
233 public static function htag_support()
234 {
235 $supported_tag = BetterDocs_DB::get_settings('supported_heading_tag');
236 if( ! empty( $supported_tag ) && $supported_tag !== 'off' ) {
237 $tags = implode(',',$supported_tag);
238 }
239 return $tags;
240 }
241
242 public static function list_hierarchy($post_content, $toc_hierarchy, $htag_support)
243 {
244 // Whether or not the TOC should be built flat or hierarchical.
245 preg_match_all( '/(<h(['.$htag_support.']{1})[^>]*>).*<\/h\2>/msuU', $post_content, $matches, PREG_SET_ORDER );
246 $html = '';
247 if ($matches) {
248 $first_match = $matches[0][2];
249 $current_depth = $first_match; // headings can't be larger than h6 but 100 as a default to be sure
250 $numbered_items = array();
251 $numbered_items_min = null;
252
253 if ($toc_hierarchy == '1') {
254 $html .= '<ul class="toc-list betterdocs-hierarchial-toc">';
255
256 // find the minimum heading to establish our baseline
257 foreach ($matches as $i => $match) {
258 if ($current_depth < $first_match) {
259 $current_depth = $first_match;
260 } else if ($current_depth > $matches[ $i ][2]) {
261 $current_depth = (int) $matches[ $i ][2];
262 }
263 }
264
265 $numbered_items[ $current_depth ] = 0;
266 $numbered_items_min = $current_depth;
267
268 foreach ($matches as $i => $match) {
269 $level = $matches[ $i ][2];
270 $count = $i + 1;
271
272 if ($current_depth == (int) $matches[ $i ][2]) {
273 $html .= '<li class="betterdocs-toc-heading-level-' . $current_depth . '">';
274 }
275
276 // start lists
277 if ($current_depth != (int) $matches[ $i ][2]) {
278 $diff = $current_depth - (int) $matches[ $i ][2];
279 for ($current_depth; $current_depth < (int) $matches[ $i ][2]; $current_depth = $current_depth - $diff) {
280 $numbered_items[ $current_depth + 1 ] = 0;
281 $html .= '<ul class="betterdocs-toc-list-level-' . $level . '"><li class="betterdocs-toc-heading-level-' . $level . '">';
282 }
283 }
284
285 $title = isset( $matches[ $i ]['alternate'] ) ? $matches[ $i ]['alternate'] : $matches[ $i ][0];
286 $title = strip_tags( $title );
287 $has_id = preg_match('/id=(["\'])(.*?)\1[\s>]/si', $matches[ $i ][0], $matched_ids);
288 $id = $has_id ? $matched_ids[2] : $i . '-toc-title';
289
290 $html .= '<a href="#' . $id . '">' . $title . '</a>';
291
292 // end lists
293 if ($i != count($matches) - 1) {
294 $next_match = (int) $matches[ $i + 1 ][2];
295 if ($first_match > $next_match && $current_depth > $next_match) {
296 $diff = $current_depth - $next_match;
297 for ($current_depth; $current_depth > $next_match; $current_depth-- ) {
298 $html .= '</li>';
299 $numbered_items[ $current_depth ] = 0;
300 }
301 } else if ($current_depth > (int) $matches[ $i + 1 ][2]) {
302 for ($current_depth; $current_depth > (int) $matches[ $i + 1 ][2]; $current_depth--) {
303 $html .= '</li></ul>';
304 $numbered_items[ $current_depth ] = 0;
305 }
306 }
307
308 if ($current_depth == (int) @$matches[ $i + 1 ][2]) {
309 $html .= '</li>';
310 }
311 } else {
312 // this is the last item, make sure we close off all tags
313 for ($current_depth; $current_depth >= $numbered_items_min; $current_depth--) {
314 $html .= '</li>';
315 if ( $current_depth != $numbered_items_min ) {
316 $html .= '</ul>';
317 }
318 }
319 }
320 }
321
322 $html .= '</ul>';
323 } else {
324 $html .= '<ul class="toc-list">';
325
326 foreach ($matches as $i => $match) {
327 $count = $i + 1;
328 $title = isset( $matches[ $i ]['alternate'] ) ? $matches[ $i ]['alternate'] : $matches[ $i ][0];
329 $title = strip_tags( apply_filters( 'ez_toc_title', $title ), apply_filters( 'ez_toc_title_allowable_tags', '' ) );
330 $html .= '<li>';
331 $title = isset( $matches[ $i ]['alternate'] ) ? $matches[ $i ]['alternate'] : $matches[ $i ][0];
332 $title = strip_tags( $title );
333 $has_id = preg_match('/id=(["\'])(.*?)\1[\s>]/si', $matches[ $i ][0], $matched_ids);
334 $id = $has_id ? $matched_ids[2] : $i . '-toc-title';
335 $html .= '<a href="#'.$id.'">' . $title . '</a>';
336 $html .= '</li>';
337 }
338
339 $html .= '</ul>';
340 }
341 }
342 return $html;
343 }
344
345 public static function betterdocs_toc(
346 $content,
347 $htags,
348 $toc_hierarchy,
349 $list_number,
350 $collapsible
351 ) {
352 $html = '';
353 if (!empty(self::list_hierarchy($content, $toc_hierarchy, $htags))) {
354 $toc_class = array( 'betterdocs-toc' );
355 $toc_title = BetterDocs_DB::get_settings('toc_title') ? BetterDocs_DB::get_settings('toc_title') : esc_html__( 'Table of Contents', 'betterdocs' );
356 if ($collapsible == '1') {
357 $toc_class[] = 'collapsible-sm';
358 $collapsible_arrow = "<svg class='angle-icon angle-up' aria-hidden='true' focusable='false' data-prefix='fas' data-icon='angle-up' class='svg-inline--fa fa-angle-up fa-w-10' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'><path fill='currentColor' d='M177 159.7l136 136c9.4 9.4 9.4 24.6 0 33.9l-22.6 22.6c-9.4 9.4-24.6 9.4-33.9 0L160 255.9l-96.4 96.4c-9.4 9.4-24.6 9.4-33.9 0L7 329.7c-9.4-9.4-9.4-24.6 0-33.9l136-136c9.4-9.5 24.6-9.5 34-.1z'></path></svg><svg class='angle-icon angle-down' aria-hidden='true' focusable='false' data-prefix='fas' data-icon='angle-down' class='svg-inline--fa fa-angle-down fa-w-10' role='img' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'><path fill='currentColor' d='M143 352.3L7 216.3c-9.4-9.4-9.4-24.6 0-33.9l22.6-22.6c9.4-9.4 24.6-9.4 33.9 0l96.4 96.4 96.4-96.4c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9l-136 136c-9.2 9.4-24.4 9.4-33.8 0z'></path></svg>";
359 } else {
360 $collapsible_arrow = null;
361 }
362
363 if ($list_number == '1') {
364 $toc_class[] = 'toc-list-number';
365 }
366
367 $html = '<div class="' . implode( ' ', $toc_class ) . '">
368 <span class="toc-title">' . $toc_title . $collapsible_arrow . '</span>';
369 $html .= self::list_hierarchy($content, $toc_hierarchy, $htags);
370 $html .= '</div>';
371 }
372 return $html;
373 }
374
375 /**
376 * Return table of content list before single post the_content
377 *
378 * @since 1.0.0
379 */
380 public static function betterdocs_the_content ($content, $htgs, $enable_toc) {
381 if ($enable_toc == '1' && preg_match_all( '/(<h(['.$htgs.']{1})[^>]*>).*<\/h\2>/msuU', $content, $matches, PREG_SET_ORDER)) {
382 $index = 0;
383 $content = preg_replace_callback( '#<(h['.$htgs.'])(.*?)>(.*?)</\1>#si', function ($matches) use (&$index) {
384 $tag = $matches[1];
385 $title = strip_tags($matches[3]);
386 $has_id = preg_match('/id=(["\'])(.*?)\1[\s>]/si', $matches[2], $matched_ids);
387 $id = $has_id ? $matched_ids[2] : $index++ . '-toc-title';
388
389 if ($has_id) {
390 return $matches[0];
391 }
392
393 $title_link_ctc = BetterDocs_DB::get_settings('title_link_ctc');
394
395 if ($title_link_ctc == 1) {
396 $hash_link = '<a href="#'.$id.'" class="anchor" data-clipboard-text="'. get_permalink() .'#'. $id .'" data-title="'.esc_html__('Copy URL','betterdocs').'">#</a>';
397 } else {
398 $hash_link = '';
399 }
400
401 return sprintf('<%s%s class="betterdocs-content-heading" id="%s">%s %s</%s>', $tag, $matches[2], $id, $matches[3], $hash_link, $tag);
402 }, $content );
403 }
404
405 $content = '<div id="betterdocs-single-content" class="betterdocs-content">'. $content . '</div>';
406
407 return $content;
408 }
409
410 public static function get_last_post_id()
411 {
412 global $wpdb;
413
414 $query = "SELECT ID FROM $wpdb->posts ORDER BY ID DESC LIMIT 0,1";
415
416 $result = $wpdb->get_results($query);
417 $row = $result[0];
418 $id = $row->ID;
419
420 return $id;
421 }
422
423 /**
424 * Insert quick action link to plugin page
425 *
426 * @since 1.1.5
427 */
428 public function insert_plugin_links($links)
429 {
430 $links[] = sprintf('<a href="admin.php?page=betterdocs-settings">' . esc_html__('Settings','betterdocs') . '</a>');
431 return $links;
432 }
433 }
434