PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 1.3.5
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v1.3.5
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 / class-betterdocs-docs-post-type.php

class-betterdocs-docs-post-type.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 1.3.5, at includes/class-betterdocs-docs-post-type.php

658 lines 23.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Register docs post type and taxonomies.
4 *
5 * @link https://wpdeveloper.net
6 * @since 1.0.0
7 *
8 * @package BetterDocs
9 * @subpackage BetterDocs/includes
10 */
11
12 use function YoastSEO_Vendor\GuzzleHttp\json_decode;
13
14 /**
15 * Register docs post type and taxonomies class.
16 *
17 *
18 * Also maintains the unique identifier of this plugin as well as the current
19 * version of the plugin.
20 *
21 * @since 1.0.0
22 * @package BetterDocs
23 * @subpackage BetterDocs/includes
24 * @author WPDeveloper <support@wpdeveloper.net>
25 */
26 class BetterDocs_Docs_Post_Type {
27
28 public static $post_type = 'docs';
29 public static $menu_position = 5;
30 public static $category = 'doc_category';
31 public static $tag = 'doc_tag';
32 public static $docs_archive;
33 public static $docs_slug;
34 public static $cat_slug;
35
36 /**
37 *
38 * Initialize the class and start calling our hooks and filters
39 *
40 * @since 1.0.0
41 *
42 */
43 public static function init() {
44
45 self::$docs_archive = self::get_docs_archive();
46 self::$docs_slug = self::get_docs_slug();
47 self::$cat_slug = self::docs_category_slug();
48 add_action('init', array(__CLASS__, 'register_post'));
49 add_filter('rest_api_allowed_post_types', array(__CLASS__, 'rest_api_allowed_post_types'));
50 add_action('admin_head', array(__CLASS__, 'admin_order_terms'));
51 $alphabetically_order_term = BetterDocs_DB::get_settings('alphabetically_order_term');
52 if ( $alphabetically_order_term != 1 ) {
53 add_action('init', array(__CLASS__, 'front_end_order_terms'));
54 }
55 // doc category taxonomy media upload hooks
56 add_action('doc_category_add_form_fields', array(__CLASS__, 'add_doc_category_meta'), 10, 2);
57 add_action('doc_category_edit_form_fields', array(__CLASS__, 'update_doc_category_meta'), 10, 2);
58 add_action('created_doc_category', array(__CLASS__, 'save_doc_category_meta'), 10, 2);
59 add_action('edited_doc_category', array(__CLASS__, 'updated_doc_category_meta'), 10, 2);
60 add_action('admin_enqueue_scripts', array(__CLASS__, 'load_media'));
61 add_action('admin_footer', array(__CLASS__, 'add_script'));
62
63 }
64
65 public static function get_docs_slug() {
66
67 $builtin_doc_page = BetterDocs_DB::get_settings('builtin_doc_page');
68 $docs_slug = BetterDocs_DB::get_settings('docs_slug');
69 $docs_page = BetterDocs_DB::get_settings('docs_page');
70
71 // $disable_root_slug = BetterDocs_DB::get_settings('disable_root_slug');
72 // if ( $disable_root_slug == 1 ) {
73 // $docs_post_slug = '';
74 // }
75
76 if ( $builtin_doc_page == 1 && $docs_slug ) {
77
78 $docs_post_slug = $docs_slug;
79
80 } elseif ( $builtin_doc_page != 1 && $docs_page ) {
81
82 $post_info = get_post( $docs_page );
83 $docs_post_slug = $post_info->post_name;
84
85 } else {
86
87 $docs_post_slug = 'docs';
88
89 }
90
91 return $docs_post_slug;
92 }
93
94 public static function get_docs_archive() {
95
96 $builtin_doc_page = BetterDocs_DB::get_settings('builtin_doc_page');
97 $docs_slug = BetterDocs_DB::get_settings('docs_slug');
98 $docs_page = BetterDocs_DB::get_settings('docs_page');
99
100 if ( $builtin_doc_page == 1 && $docs_slug ) {
101
102 $docs_post_slug = $docs_slug;
103
104 } elseif ( $builtin_doc_page != 1 && $docs_page ) {
105
106 $post_info = get_post( $docs_page );
107 $docs_post_slug = $post_info->post_name;
108
109 } else {
110
111 $docs_post_slug = 'docs';
112
113 }
114
115 return $docs_post_slug;
116 }
117
118 public static function docs_category_slug() {
119
120 $category_slug = BetterDocs_DB::get_settings('category_slug');
121
122 if ( empty ( $category_slug ) ) {
123
124 $category_slug = 'docs-category';
125
126 }
127
128 return $category_slug;
129 }
130
131 /**
132 *
133 * Register post type and taxonomies
134 *
135 * @since 1.0.0
136 *
137 */
138 public static function register_post() {
139
140 $singular_name = BetterDocs_DB::get_settings('breadcrumb_doc_title');
141
142
143 /**
144 * Register category taxonomy
145 */
146 $category_labels = array(
147 'name' => esc_html__('Docs Categories', 'betterdocs'),
148 'singular_name' => esc_html__('Docs Category', 'betterdocs'),
149 'all_items' => esc_html__('Docs Categories', 'betterdocs'),
150 'parent_item' => esc_html__('Parent Docs Category', 'betterdocs'),
151 'parent_item_colon'=> esc_html__('Parent Docs Category:', 'betterdocs'),
152 'edit_item' => esc_html__('Edit Category', 'betterdocs'),
153 'update_item' => esc_html__('Update Category', 'betterdocs'),
154 'add_new_item' => esc_html__('Add New Docs Category', 'betterdocs'),
155 'new_item_name' => esc_html__('New Docs Name', 'betterdocs'),
156 'menu_name' => esc_html__('Categories', 'betterdocs')
157 );
158
159 $category_args = array(
160 'hierarchical' => true,
161 'public' => true,
162 'labels' => $category_labels,
163 'show_ui' => true,
164 'show_admin_column' => true,
165 'query_var' => true,
166 'show_in_rest' => true,
167 'has_archive' => true,
168 );
169
170 $category_args['rewrite'] = apply_filters( 'betterdocs_category_rewrite', array( 'slug' => self::$cat_slug, 'with_front' => false ));
171
172 register_taxonomy( self::$category, array( self::$post_type ), $category_args );
173
174
175 /**
176 * Register post type
177 */
178 $labels = array(
179 'name' => ($singular_name) ? $singular_name : 'Docs',
180 'singular_name' => ($singular_name) ? $singular_name : 'Docs',
181 'menu_name' => esc_html__('BetterDocs', 'betterdocs'),
182 'name_admin_bar' => esc_html__('Docs', 'betterdocs'),
183 'add_new' => esc_html__('Add New', 'betterdocs'),
184 'add_new_item' => esc_html__('Add New Docs', 'betterdocs'),
185 'new_item' => esc_html__('New Docs', 'betterdocs'),
186 'edit_item' => esc_html__('Edit Docs', 'betterdocs'),
187 'view_item' => esc_html__('View Docs', 'betterdocs'),
188 'all_items' => esc_html__('All Docs', 'betterdocs'),
189 'search_items' => esc_html__('Search Docs', 'betterdocs'),
190 'parent_item_colorn' => null,
191 'not_found' => esc_html__('No docs found', 'betterdocs'),
192 'not_found_in_trash' => esc_html__('No docs found in trash', 'betterdocs')
193 );
194
195 $betterdocs_articles_caps = apply_filters( 'betterdocs_articles_caps', 'edit_posts', 'article_roles' );
196
197 $args = array(
198 'labels' => $labels,
199 'description' => esc_html__('Add new doc from here', 'betterdocs'),
200 'public' => true,
201 'public_queryable' => true,
202 'exclude_from_search' => false,
203 'show_ui' => true,
204 'show_in_menu' => false,
205 'show_in_admin_bar' => $betterdocs_articles_caps,
206 'query_var' => true,
207 'capability_type' => 'post',
208 'hierarchical' => true,
209 'menu_position' => self::$menu_position,
210 'show_in_rest' => true,
211 'menu_icon' => BETTERDOCS_ADMIN_URL . '/assets/img/betterdocs-icon-white.svg', 100,
212 'supports' => array('title', 'editor', 'thumbnail', 'excerpt', 'author', 'revisions', 'custom-fields', 'comments')
213 );
214
215 $builtin_doc_page = BetterDocs_DB::get_settings('builtin_doc_page');
216
217 if ( $builtin_doc_page == 'off' ) {
218
219 $args['has_archive'] = false;
220
221 } else {
222
223 $args['has_archive'] = self::$docs_archive;
224
225 }
226
227
228 $args['rewrite'] = apply_filters('betterdocs_docs_rewrite', array( 'slug' => self::$docs_archive, 'with_front' => false ));
229
230 register_post_type(self::$post_type, $args);
231
232 flush_rewrite_rules();
233
234 /**
235 * Register tag taxonomy
236 */
237 $tags_labels = array(
238 'name' => esc_html__('Docs Tags', 'betterdocs'),
239 'singular_name' => esc_html__('Tag', 'betterdocs'),
240 'search_items' => esc_html__('Search Tags', 'betterdocs'),
241 'popular_items' => esc_html__('Popular Tags', 'betterdocs'),
242 'all_items' => esc_html__('All Tags', 'betterdocs'),
243 'parent_item' => null,
244 'parent_item_colon' => null,
245 'edit_item' => esc_html__('Edit Tag', 'betterdocs'),
246 'update_item' => esc_html__('Update Tag', 'betterdocs'),
247 'add_new_item' => esc_html__('Add New Tag', 'betterdocs'),
248 'new_item_name' => esc_html__('New Tag Name', 'betterdocs'),
249 'separate_items_with_commas' => esc_html__('Separate tags with commas', 'betterdocs'),
250 'add_or_remove_items' => esc_html__('Add or remove tags', 'betterdocs'),
251 'choose_from_most_used' => esc_html__('Choose from the most used tags', 'betterdocs'),
252 'menu_name' => esc_html__('Tags', 'betterdocs'),
253 );
254
255 $tag_args = array(
256 'hierarchical' => true,
257 'labels' => $tags_labels,
258 'show_ui' => true,
259 'update_count_callback' => '_update_post_term_count',
260 'show_admin_column' => true,
261 'query_var' => true,
262 'show_in_rest' => true
263 );
264
265 $tag_slug = BetterDocs_DB::get_settings('tag_slug');
266
267 if ($tag_slug) {
268
269 $tag_args['rewrite'] = array('slug' => $tag_slug, 'with_front' => false);
270
271 } else {
272
273 $tag_args['rewrite'] = array('slug' => 'docs-tag', 'with_front' => false);
274
275 }
276
277 register_taxonomy(self::$tag, array(self::$post_type), $tag_args);
278
279 }
280
281 /**
282 * Added post type to allowed for rest api
283 *
284 * @param array $post_types Get the docs post types.
285 * @return array
286 *
287 * @since 1.0.0
288 *
289 */
290 public static function rest_api_allowed_post_types($post_types) {
291 $post_types[] = self::$post_type;
292
293 return $post_types;
294 }
295
296 /**
297 * load media for taxonomy category image
298 *
299 * @since 1.0.0
300 */
301 public static function load_media() {
302
303 wp_enqueue_media();
304
305 }
306
307 /**
308 * Default the taxonomy's terms' order if it's not set.
309 *
310 * @param string $tax_slug The taxonomy's slug.
311 */
312 public static function default_term_order( $tax_slug ) {
313
314 $terms = get_terms($tax_slug, array('hide_empty' => false));
315 $order = self::get_max_taxonomy_order($tax_slug);
316
317 foreach ($terms as $term) {
318
319 if ( !get_term_meta( $term->term_id, 'doc_category_order', true ) ) {
320
321 update_term_meta($term->term_id, 'doc_category_order', $order);
322 $order++;
323
324 }
325
326 }
327 }
328
329 /**
330 * Order the terms on the admin side.
331 */
332 public static function admin_order_terms() {
333
334 $screen = function_exists('get_current_screen') ? get_current_screen() : '';
335
336 if (in_array($screen->id, array('toplevel_page_betterdocs-admin', 'betterdocs_page_betterdocs-settings'))) {
337 self::default_term_order('doc_category');
338 }
339
340 if (!isset($_GET['orderby']) && !empty($screen) && !empty($screen->base) && $screen->base === 'edit-tags' && $screen->taxonomy === 'doc_category') {
341 self::default_term_order($screen->taxonomy);
342 add_filter('terms_clauses', array(__CLASS__, 'set_tax_order'), 10, 3);
343 }
344
345 }
346
347 /**
348 * Get the maximum doc_category_order for this taxonomy. This will be applied to terms that don't have a tax position.
349 */
350 private static function get_max_taxonomy_order($tax_slug) {
351
352 global $wpdb;
353
354 $max_term_order = $wpdb->get_col(
355 $wpdb->prepare(
356 "SELECT MAX( CAST( tm.meta_value AS UNSIGNED ) )
357 FROM $wpdb->terms t
358 JOIN $wpdb->term_taxonomy tt ON t.term_id = tt.term_id AND tt.taxonomy = '%s'
359 JOIN $wpdb->termmeta tm ON tm.term_id = t.term_id WHERE tm.meta_key = 'doc_category_order'",
360 $tax_slug
361 )
362 );
363
364 $max_term_order = is_array($max_term_order) ? current($max_term_order) : 0;
365
366 return (int) $max_term_order === 0 || empty($max_term_order) ? 1 : (int) $max_term_order + 1;
367 }
368
369 /**
370 * Re-Order the taxonomies based on the doc_category_order value.
371 *
372 * @param array $pieces Array of SQL query clauses.
373 * @param array $taxonomies Array of taxonomy names.
374 * @param array $args Array of term query args.
375 */
376 public static function set_tax_order($pieces, $taxonomies, $args) {
377
378 foreach ( $taxonomies as $taxonomy ) {
379
380 global $wpdb;
381
382 if ($taxonomy === 'doc_category') {
383
384 $join_statement = " LEFT JOIN $wpdb->termmeta AS term_meta ON t.term_id = term_meta.term_id AND term_meta.meta_key = 'doc_category_order'";
385
386 if (!self::does_substring_exist($pieces['join'], $join_statement)) {
387 $pieces['join'] .= $join_statement;
388 }
389
390 $pieces['orderby'] = 'ORDER BY CAST( term_meta.meta_value AS UNSIGNED )';
391 }
392 }
393
394 return $pieces;
395 }
396
397 /**
398 * Order the taxonomies on the front end.
399 */
400 public static function front_end_order_terms() {
401
402 if (!is_admin()) {
403
404 add_filter('terms_clauses', array(__CLASS__, 'set_tax_order'), 10, 3);
405
406 }
407
408 }
409
410 /**
411 * Check if a substring exists inside a string.
412 *
413 * @param string $string The main string (haystack) we're searching in.
414 * @param string $substring The substring we're searching for.
415 *
416 * @return bool True if substring exists, else false.
417 */
418 protected static function does_substring_exist( $string, $substring ) {
419
420 return strstr($string, $substring) !== false;
421
422 }
423
424 /**
425 * Default the taxonomy's terms' order if it's not set.
426 *
427 * @param string $tax_slug The taxonomy's slug.
428 */
429 public static function get_manage_docs() {
430
431 $terms = get_terms('knowledge_base', array('hide_empty' => false));
432
433 if($terms) {
434
435 echo '<select name="term_meta[knowledge_base]" id="knowledge_base">';
436 echo '<option> ' . esc_html__('Select an option') . ' </option>';
437
438 foreach ($terms as $term) {
439
440 echo '<option value="' . $term->slug . '">' . $term->name . '</option>';
441
442 }
443
444 echo '</select>';
445 }
446 }
447
448 /**
449 * Add a form field in the new category page
450 *
451 * @since 1.0.0
452 */
453 public static function add_doc_category_meta($taxonomy) {
454
455 do_action( 'betterdocs_doc_category_add_form_before' );
456
457 ?>
458
459 <div class="form-field term-group">
460 <label for="doc-category-order"><?php esc_html_e('Order', 'betterdocs'); ?></label>
461 <input type="number" id="doc-category-order" style="width:100px" name="term_meta[order]" value="">
462 </div>
463
464 <div class="form-field term-group">
465 <label for="doc-category-image-id"><?php esc_html_e('Category Icon', 'betterdocs'); ?></label>
466 <input type="hidden" id="doc-category-image-id" name="term_meta[image-id]" class="custom_media_url" value="">
467 <div id="doc-category-image-wrapper">
468 <?php echo '<img src="' . BETTERDOCS_ADMIN_URL . 'assets/img/betterdocs-cat-icon.svg" alt="">'; ?>
469 </div>
470 <p>
471 <input type="button" class="button button-secondary betterdocs_tax_media_button"
472 id="betterdocs_tax_media_button" name="betterdocs_tax_media_button"
473 value="<?php esc_html_e('Add Image', 'betterdocs'); ?>" />
474 <input type="button" class="button button-secondary doc_tax_media_remove" id="doc_tax_media_remove"
475 name="doc_tax_media_remove"
476 value="<?php esc_html_e('Remove Image', 'betterdocs'); ?>" />
477 </p>
478 </div>
479
480 <?php
481 }
482
483 /**
484 * Save the form field
485 *
486 * @since 1.0.0
487 */
488 public static function save_doc_category_meta($term_id) {
489 if (isset($_POST['term_meta'])) {
490 $term_meta = get_option("doc_category_$term_id");
491 $cat_keys = array_keys($_POST['term_meta']);
492 foreach ($cat_keys as $key) {
493 if (isset($_POST['term_meta'][$key])) {
494 add_term_meta($term_id, "doc_category_$key", $_POST['term_meta'][$key]);
495 $term_meta[$key] = $_POST['term_meta'][$key];
496 }
497 }
498 }
499 if ( isset($_POST['doc_category_kb']) ) {
500 $doc_category_kb = $_POST['doc_category_kb'];
501 update_term_meta($term_id, "doc_category_knowledge_base", $doc_category_kb);
502 }
503 }
504
505 /**
506 * Edit the form field
507 *
508 * @since 1.0.0
509 */
510 public static function update_doc_category_meta($term, $taxonomy) { ?>
511 <?php
512 $term_meta = get_option("doc_category_$term->term_id");
513 $cat_order = get_term_meta($term->term_id, 'doc_category_order', true);
514 $cat_icon_id = get_term_meta($term->term_id, 'doc_category_image-id', true);
515
516 do_action( 'betterdocs_doc_category_update_form_before', $term );
517
518 ?>
519
520 <tr class="form-field term-group-wrap">
521 <th scope="row">
522 <label for="doc-category-id"><?php esc_html_e('Category Id', 'betterdocs'); ?></label>
523 </th>
524 <td>
525 <input type="text" id="doc-category-id" style="width:100px" name="" value="<?php echo $_GET["tag_ID"] ?>" readonly>
526 </td>
527 </tr>
528 <tr class="form-field term-group-wrap">
529 <th scope="row">
530 <label for="doc-category-order"><?php esc_html_e('Order', 'betterdocs'); ?></label>
531 </th>
532 <td>
533 <input type="number" id="doc-category-order" style="width:100px" name="term_meta[order]"
534 value="<?php echo $cat_order ? $cat_order : ''; ?>">
535 </td>
536 </tr>
537 <tr class="form-field term-group-wrap batterdocs-cat-media-upload">
538 <th scope="row">
539 <label for="doc-category-image-id"><?php esc_html_e('Image', 'betterdocs'); ?></label>
540 </th>
541 <td>
542 <input type="hidden" id="doc-category-image-id" name="term_meta[image-id]" value="<?php echo $cat_icon_id; ?>">
543 <div id="doc-category-image-wrapper">
544
545 <?php
546
547 if ( $cat_icon_id ) {
548
549 echo wp_get_attachment_image( $cat_icon_id, 'thumbnail' );
550
551 } else {
552
553 echo '<img src="' . BETTERDOCS_ADMIN_URL . 'assets/img/betterdocs-cat-icon.svg" alt="">';
554
555 }
556 ?>
557
558 </div>
559 <p>
560 <input type="button" class="button button-secondary betterdocs_tax_media_button"
561 id="betterdocs_tax_media_button" name="betterdocs_tax_media_button"
562 value="<?php esc_html_e('Add Image', 'betterdocs'); ?>" />
563 <input type="button" class="button button-secondary doc_tax_media_remove" id="doc_tax_media_remove"
564 name="doc_tax_media_remove"
565 value="<?php esc_html_e('Remove Image', 'betterdocs'); ?>" />
566 </p>
567 </td>
568 </tr>
569 <?php
570 }
571
572 /*
573 * Update the form field value
574 *
575 * @since 1.0.0
576 */
577 public static function updated_doc_category_meta( $term_id ) {
578 if ( isset($_POST['term_meta']) ) {
579 $cat_keys = array_keys($_POST['term_meta']);
580 foreach ($cat_keys as $key) {
581 if (isset($_POST['term_meta'][$key])) {
582 update_term_meta($term_id, "doc_category_$key", $_POST['term_meta'][$key]);
583 }
584 }
585 }
586 if ( isset($_POST['doc_category_kb']) ) {
587 $doc_category_kb = $_POST['doc_category_kb'];
588 update_term_meta($term_id, "doc_category_knowledge_base", $doc_category_kb);
589 }
590 }
591
592 /*
593 * Add script
594 *
595 * @since 1.0.0
596 */
597 public static function add_script() {
598
599 global $current_screen;
600 if ( $current_screen->id == 'edit-doc_category' ) {
601
602 ?>
603 <script>
604 jQuery(document).ready(function($) {
605
606 function betterdocs_media_upload(button_class) {
607 var _custom_media = true,
608 _betterdocs_send_attachment = wp.media.editor.send.attachment;
609 $('body').on('click', button_class, function(e) {
610 var button_id = '#' + $(this).attr('id');
611 var send_attachment_bkp = wp.media.editor.send.attachment;
612 var button = $(button_id);
613 _custom_media = true;
614 wp.media.editor.send.attachment = function(props, attachment) {
615 if (_custom_media) {
616 $('#doc-category-image-id').val(attachment.id);
617 $('#doc-category-image-wrapper').html(
618 '<img class="custom_media_image" src="" style="margin:0;padding:0;max-height:100px;float:none;" />'
619 );
620 $('#doc-category-image-wrapper .custom_media_image').attr('src', attachment
621 .url).css('display', 'block');
622 } else {
623 return _betterdocs_send_attachment.apply(button_id, [props, attachment]);
624 }
625 }
626 wp.media.editor.open(button);
627 return false;
628 });
629 }
630
631 betterdocs_media_upload('.betterdocs_tax_media_button.button');
632
633 $('body').on('click', '.doc_tax_media_remove', function() {
634 $('#doc-category-image-id').val('');
635 $('#doc-category-image-wrapper').html(
636 '<img class="custom_media_image" src="" style="margin:0;padding:0;max-height:100px;float:none;" />'
637 );
638 });
639
640 $(document).ajaxComplete(function(event, xhr, settings) {
641 var queryStringArr = settings.data.split('&');
642 if ($.inArray('action=add-tag', queryStringArr) !== -1) {
643 var xml = xhr.responseXML;
644 $response = $(xml).find('term_id').text();
645 if ($response != "") {
646 // Clear the thumb image
647 $('#doc-category-image-wrapper').html('');
648 }
649 }
650 });
651 });
652 </script>
653 <?php }
654 }
655 }
656
657 BetterDocs_Docs_Post_Type::init();
658