PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 2.3.6
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v2.3.6
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 2.3.6, at includes/class-betterdocs-docs-post-type.php

874 lines 33.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Register docs post type and taxonomies.
5 *
6 * @link https://wpdeveloper.com
7 * @since 1.0.0
8 *
9 * @package BetterDocs
10 * @subpackage BetterDocs/includes
11 */
12
13 /**
14 * Register docs post type and taxonomies class.
15 *
16 *
17 * Also maintains the unique identifier of this plugin as well as the current
18 * version of the plugin.
19 *
20 * @since 1.0.0
21 * @package BetterDocs
22 * @subpackage BetterDocs/includes
23 * @author WPDeveloper <support@wpdeveloper.com>
24 */
25 class BetterDocs_Docs_Post_Type
26 {
27 public static $post_type = 'docs';
28 public static $menu_position = 5;
29 public static $category = 'doc_category';
30 public static $tag = 'doc_tag';
31 public static $docs_archive;
32 public static $docs_slug;
33 public static $cat_slug;
34
35 /**
36 *
37 * Initialize the class and start calling our hooks and filters
38 *
39 * @since 1.0.0
40 *
41 */
42 public static function init()
43 {
44 self::$docs_archive = self::get_docs_archive();
45 self::$docs_slug = self::get_docs_slug();
46 self::$cat_slug = self::docs_category_slug();
47 // assign default admin capabilities for docs, doc terms, doc tags, knowledge base
48 add_action('init', array(__CLASS__, 'register_post'));
49 add_action('parse_request', array(__CLASS__, 'docs_rewrite_parse_request'));
50 add_action('generate_rewrite_rules', array(__CLASS__, 'generate_rewrite_rules'));
51 add_filter('betterdocs_docs_rewrite', array(__CLASS__, 'docs_rewrite'), 9);
52 add_filter('post_type_link', array(__CLASS__, 'docs_show_permalinks'), 1, 3);
53 add_action('init', array(__CLASS__, 'flush_rewrite_rules'), 99999);
54 add_filter('rest_docs_collection_params', array(__CLASS__, 'add_rest_orderby_params'), 10, 1);
55 add_filter('rest_doc_category_collection_params', array(__CLASS__, 'add_rest_orderby_params_on_doc_category'), 10, 1);
56 add_filter('rest_doc_category_query', array(__CLASS__, 'modify_doc_category_rest_query'), 10, 2);
57 add_action('admin_head', array(__CLASS__, 'admin_order_terms'));
58 add_action('parse_term_query', array(__CLASS__, 'parse_term_query'));
59 // doc category taxonomy media upload hooks
60 add_action('doc_category_add_form_fields', array(__CLASS__, 'add_doc_category_meta'), 10, 2);
61 add_action('doc_category_edit_form_fields', array(__CLASS__, 'update_doc_category_meta'), 10, 2);
62 add_action('created_doc_category', array(__CLASS__, 'save_doc_category_meta'), 10, 2);
63 add_action('edited_doc_category', array(__CLASS__, 'updated_doc_category_meta'), 10, 2);
64 add_action('admin_enqueue_scripts', array(__CLASS__, 'load_media'));
65 add_action('admin_footer', array(__CLASS__, 'add_script'));
66 // add doc category image on rest api
67 add_action('rest_api_init', array(__CLASS__, 'add_doc_category_meta_rest_api'), 10, 2);
68 // fires after a new doc_category is created
69 add_action('created_doc_category', array(__CLASS__, 'action_created_doc_category'), 10, 2);
70 }
71
72 public static function parse_term_query( $term_query ){
73 $screen = function_exists('get_current_screen') ? get_current_screen() : '';
74 if(
75 empty( $term_query->query_vars['taxonomy'] )
76 || ! in_array( 'doc_category', $term_query->query_vars['taxonomy'], true )
77 || empty( $screen )
78 || ( ! empty( $screen ) && $screen->taxonomy !== 'doc_category' )
79 || ( ! empty( $screen ) && $screen->id != 'edit-doc_category' )
80 ) {
81 return;
82 }
83 $term_query->query_vars['meta_query'] = [
84 [
85 'key' => 'doc_category_order',
86 'type' => 'NUMERIC'
87 ]
88 ];
89 $term_query->query_vars['orderby'] = 'meta_value_num';
90 }
91
92 public static function get_docs_slug()
93 {
94 $builtin_doc_page = BetterDocs_DB::get_settings('builtin_doc_page');
95 $docs_slug = BetterDocs_DB::get_settings('docs_slug');
96 $docs_page = BetterDocs_DB::get_settings('docs_page');
97
98 if ($builtin_doc_page == 1 && $docs_slug) {
99 $docs_post_slug = $docs_slug;
100 } elseif ($builtin_doc_page != 1 && $docs_page) {
101 $post_info = get_post($docs_page);
102 $docs_post_slug = $post_info->post_name;
103 } else {
104 $docs_post_slug = 'docs';
105 }
106
107 return $docs_post_slug;
108 }
109
110 public static function get_docs_archive()
111 {
112 $builtin_doc_page = BetterDocs_DB::get_settings('builtin_doc_page');
113 $docs_slug = BetterDocs_DB::get_settings('docs_slug');
114 $docs_page = BetterDocs_DB::get_settings('docs_page');
115
116 if ($builtin_doc_page == 1 && $docs_slug) {
117 $docs_post_slug = $docs_slug;
118 } elseif ($builtin_doc_page != 1 && $docs_page) {
119 $post_info = get_post($docs_page);
120 $docs_post_slug = $post_info->post_name;
121 } else {
122 $docs_post_slug = 'docs';
123 }
124
125 return $docs_post_slug;
126 }
127
128 public static function docs_category_slug()
129 {
130 $category_slug = BetterDocs_DB::get_settings('category_slug');
131
132 if (empty($category_slug)) {
133 $category_slug = 'docs-category';
134 }
135
136 return $category_slug;
137 }
138
139 /**
140 *
141 * Register post type and taxonomies
142 *
143 * @since 1.0.0
144 *
145 */
146 public static function register_post()
147 {
148 $singular_name = BetterDocs_DB::get_settings('breadcrumb_doc_title');
149
150 /**
151 * Register category taxonomy
152 */
153 $category_labels = array(
154 'name' => esc_html__('Docs Categories', 'betterdocs'),
155 'singular_name' => esc_html__('Docs Category', 'betterdocs'),
156 'all_items' => esc_html__('Docs Categories', 'betterdocs'),
157 'parent_item' => esc_html__('Parent Docs Category', 'betterdocs'),
158 'parent_item_colon' => esc_html__('Parent Docs Category:', 'betterdocs'),
159 'edit_item' => esc_html__('Edit Category', 'betterdocs'),
160 'update_item' => esc_html__('Update Category', 'betterdocs'),
161 'add_new_item' => esc_html__('Add New Docs Category', 'betterdocs'),
162 'new_item_name' => esc_html__('New Docs Category Name', 'betterdocs'),
163 'menu_name' => esc_html__('Categories', 'betterdocs')
164 );
165
166 $category_args = array(
167 'hierarchical' => true,
168 'public' => true,
169 'labels' => $category_labels,
170 'show_ui' => true,
171 'show_admin_column' => true,
172 'query_var' => true,
173 'show_in_rest' => true,
174 'has_archive' => true,
175 'capabilities' => [
176 'manage_terms' => 'manage_doc_terms',
177 'edit_terms' => 'edit_doc_terms',
178 'delete_terms' => 'delete_doc_terms',
179 'assign_terms' => 'edit_docs'
180 ]
181 );
182
183 $category_args['rewrite'] = apply_filters('betterdocs_category_rewrite', array('slug' => self::$cat_slug, 'with_front' => false));
184
185 register_taxonomy(self::$category, array(self::$post_type), $category_args);
186
187 /**
188 * Register post type
189 */
190 $labels = array(
191 'name' => ($singular_name) ? $singular_name : 'Docs',
192 'singular_name' => ($singular_name) ? $singular_name : 'Docs',
193 'menu_name' => esc_html__('BetterDocs', 'betterdocs'),
194 'name_admin_bar' => esc_html__('Docs', 'betterdocs'),
195 'add_new' => esc_html__('Add New', 'betterdocs'),
196 'add_new_item' => esc_html__('Add New Docs', 'betterdocs'),
197 'new_item' => esc_html__('New Docs', 'betterdocs'),
198 'edit_item' => esc_html__('Edit Docs', 'betterdocs'),
199 'view_item' => esc_html__('View Docs', 'betterdocs'),
200 'all_items' => esc_html__('All Docs', 'betterdocs'),
201 'search_items' => esc_html__('Search Docs', 'betterdocs'),
202 'parent_item_colorn' => null,
203 'not_found' => esc_html__('No docs found', 'betterdocs'),
204 'not_found_in_trash' => esc_html__('No docs found in trash', 'betterdocs')
205 );
206
207 $betterdocs_articles_caps = apply_filters('betterdocs_articles_caps', 'edit_posts', 'article_roles');
208
209 $args = array(
210 'labels' => $labels,
211 'description' => esc_html__('Add new doc from here', 'betterdocs'),
212 'public' => true,
213 'public_queryable' => true,
214 'exclude_from_search' => false,
215 'show_ui' => true,
216 'show_in_menu' => false,
217 'show_in_admin_bar' => $betterdocs_articles_caps,
218 'query_var' => true,
219 'capability_type' => ['doc', 'docs'],
220 'hierarchical' => true,
221 'map_meta_cap' => true,
222 'menu_position' => self::$menu_position,
223 'show_in_rest' => true,
224 'menu_icon' => BETTERDOCS_ADMIN_URL . '/assets/img/betterdocs-icon-white.svg', 100,
225 'supports' => array('title', 'editor', 'thumbnail', 'excerpt', 'author', 'revisions', 'custom-fields', 'comments')
226 );
227
228 $builtin_doc_page = BetterDocs_DB::get_settings('builtin_doc_page');
229
230 if ($builtin_doc_page == 'off') {
231 $args['has_archive'] = false;
232 } else {
233 $args['has_archive'] = self::$docs_archive;
234 }
235
236 $args['rewrite'] = apply_filters('betterdocs_docs_rewrite', array('slug' => self::$docs_archive, 'with_front' => false));
237
238 register_post_type(self::$post_type, $args);
239
240 /**
241 * Register tag taxonomy
242 */
243 $tags_labels = array(
244 'name' => esc_html__('Docs Tags', 'betterdocs'),
245 'singular_name' => esc_html__('Tag', 'betterdocs'),
246 'search_items' => esc_html__('Search Tags', 'betterdocs'),
247 'popular_items' => esc_html__('Popular Tags', 'betterdocs'),
248 'all_items' => esc_html__('All Tags', 'betterdocs'),
249 'parent_item' => null,
250 'parent_item_colon' => null,
251 'edit_item' => esc_html__('Edit Tag', 'betterdocs'),
252 'update_item' => esc_html__('Update Tag', 'betterdocs'),
253 'add_new_item' => esc_html__('Add New Tag', 'betterdocs'),
254 'new_item_name' => esc_html__('New Tag Name', 'betterdocs'),
255 'separate_items_with_commas' => esc_html__('Separate tags with commas', 'betterdocs'),
256 'add_or_remove_items' => esc_html__('Add or remove tags', 'betterdocs'),
257 'choose_from_most_used' => esc_html__('Choose from the most used tags', 'betterdocs'),
258 'menu_name' => esc_html__('Tags', 'betterdocs'),
259 );
260
261 $tag_args = array(
262 'hierarchical' => true,
263 'labels' => $tags_labels,
264 'show_ui' => true,
265 'update_count_callback' => '_update_post_term_count',
266 'show_admin_column' => true,
267 'query_var' => true,
268 'show_in_rest' => true,
269 'capabilities' => [
270 'manage_terms' => 'manage_doc_terms',
271 'edit_terms' => 'edit_doc_terms',
272 'delete_terms' => 'delete_doc_terms',
273 'assign_terms' => 'edit_docs'
274 ]
275 );
276
277 $tag_slug = BetterDocs_DB::get_settings('tag_slug');
278
279 if ($tag_slug) {
280 $tag_args['rewrite'] = array('slug' => $tag_slug, 'with_front' => false);
281 } else {
282 $tag_args['rewrite'] = array('slug' => 'docs-tag', 'with_front' => false);
283 }
284
285 register_taxonomy(self::$tag, array(self::$post_type), $tag_args);
286 }
287
288 /**
289 * Add menu_order param to the list of rest api orderby values
290 */
291 public static function add_rest_orderby_params($params)
292 {
293 $params['orderby']['enum'][] = 'menu_order';
294 return $params;
295 }
296
297 /**
298 * Add doc_category_order param to the list of rest api orderby values on doc_category taxonomy
299 */
300 public static function add_rest_orderby_params_on_doc_category($params)
301 {
302 $params['orderby']['enum'][] = 'doc_category_order';
303 return $params;
304 }
305
306 /**
307 * Modify doc_category rest query for doc_category_order meta key
308 */
309 public static function modify_doc_category_rest_query($args, $request)
310 {
311 $order_by = $request->get_param('orderby');
312 if (isset($order_by) && 'doc_category_order' === $order_by) {
313 $args['meta_key'] = $order_by;
314 $args['orderby'] = 'meta_value_num';
315 }
316 return $args;
317 }
318
319 /**
320 * load media for taxonomy category image
321 *
322 * @since 1.0.0
323 */
324 public static function load_media()
325 {
326 wp_enqueue_media();
327 }
328
329 /**
330 * Default the taxonomy's terms' order if it's not set.
331 *
332 * @param string $tax_slug The taxonomy's slug.
333 */
334 public static function action_created_doc_category( $term_id, $tt_id )
335 {
336 $order = self::get_max_taxonomy_order('doc_category');
337 update_term_meta($term_id, 'doc_category_order', $order++);
338 }
339
340 /**
341 * Default the taxonomy's terms' order if it's not set.
342 *
343 * @param string $tax_slug The taxonomy's slug.
344 */
345 public static function default_term_order($tax_slug)
346 {
347 $terms = get_terms($tax_slug, array('hide_empty' => false));
348 $order = self::get_max_taxonomy_order($tax_slug);
349
350 foreach ($terms as $term) {
351 if (!get_term_meta($term->term_id, 'doc_category_order', true)) {
352 update_term_meta($term->term_id, 'doc_category_order', $order);
353 $order++;
354 }
355 }
356 }
357
358 /**
359 * Order the terms on the admin side.
360 */
361 public static function admin_order_terms()
362 {
363 $screen = function_exists('get_current_screen') ? get_current_screen() : '';
364 $screen_id = isset($screen->id) ? $screen->id : '';
365 if (in_array($screen_id, array('toplevel_page_betterdocs-admin', 'betterdocs_page_betterdocs-settings'))) {
366 self::default_term_order('doc_category');
367 }
368
369 if (!isset($_GET['orderby']) && !empty($screen) && !empty($screen->base) && $screen->base === 'edit-tags' && $screen->taxonomy === 'doc_category') {
370 self::default_term_order($screen->taxonomy);
371 add_filter('terms_clauses', array(__CLASS__, 'set_tax_order'), 10, 3);
372 }
373 }
374
375 /**
376 * Get the maximum doc_category_order for this taxonomy. This will be applied to terms that don't have a tax position.
377 */
378 private static function get_max_taxonomy_order($tax_slug)
379 {
380 global $wpdb;
381
382 $max_term_order = $wpdb->get_col(
383 $wpdb->prepare(
384 "SELECT MAX( CAST( tm.meta_value AS UNSIGNED ) )
385 FROM $wpdb->terms t
386 JOIN $wpdb->term_taxonomy tt ON t.term_id = tt.term_id AND tt.taxonomy = '%s'
387 JOIN $wpdb->termmeta tm ON tm.term_id = t.term_id WHERE tm.meta_key = 'doc_category_order'",
388 $tax_slug
389 )
390 );
391
392 $max_term_order = is_array($max_term_order) ? current($max_term_order) : 0;
393
394 return (int) $max_term_order === 0 || empty($max_term_order) ? 1 : (int) $max_term_order + 1;
395 }
396
397 /**
398 * Re-Order the taxonomies based on the doc_category_order value.
399 *
400 * @param array $pieces Array of SQL query clauses.
401 * @param array $taxonomies Array of taxonomy names.
402 * @param array $args Array of term query args.
403 */
404 public static function set_tax_order($pieces, $taxonomies, $args)
405 {
406 foreach ($taxonomies as $taxonomy) {
407 global $wpdb;
408
409 if ($taxonomy === 'doc_category') {
410 $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'";
411
412 if (!self::does_substring_exist($pieces['join'], $join_statement)) {
413 $pieces['join'] .= $join_statement;
414 }
415
416 $pieces['orderby'] = 'ORDER BY CAST( term_meta.meta_value AS UNSIGNED )';
417 }
418 }
419
420 return $pieces;
421 }
422
423 /**
424 * Order the taxonomies on the front end.
425 */
426 public static function front_end_order_terms()
427 {
428 if (!is_admin()) {
429 add_filter('terms_clauses', array(__CLASS__, 'set_tax_order'), 10, 3);
430 }
431 }
432
433 /**
434 * Check if a substring exists inside a string.
435 *
436 * @param string $string The main string (haystack) we're searching in.
437 * @param string $substring The substring we're searching for.
438 *
439 * @return bool True if substring exists, else false.
440 */
441 protected static function does_substring_exist($string, $substring)
442 {
443 return strstr($string, $substring) !== false;
444 }
445
446 /**
447 * Default the taxonomy's terms' order if it's not set.
448 *
449 * @param string $tax_slug The taxonomy's slug.
450 */
451 public static function get_manage_docs()
452 {
453 $terms = get_terms('knowledge_base', array('hide_empty' => false));
454
455 if ($terms) {
456 echo '<select name="term_meta[knowledge_base]" id="knowledge_base">';
457 echo '<option> ' . esc_html__('Select an option') . ' </option>';
458
459 foreach ($terms as $term) {
460 echo '<option value="' . $term->slug . '">' . $term->name . '</option>';
461 }
462
463 echo '</select>';
464 }
465 }
466
467 /**
468 * Add a form field in the new category page
469 *
470 * @since 1.0.0
471 */
472 public static function add_doc_category_meta($taxonomy)
473 {
474 do_action('betterdocs_doc_category_add_form_before');
475
476 echo '<div class="form-field term-group">
477 <label for="doc-category-order">' . esc_html__('Order', 'betterdocs') . '</label>
478 <input type="number" id="doc-category-order" style="width:100px" name="term_meta[order]" value="">
479 </div>
480
481 <div class="form-field term-group">
482 <label>' . esc_html__('Category Icon', 'betterdocs') . '</label>
483 <input type="hidden" name="term_meta[image-id]" class="doc-category-image-id" value="">
484 <div class="doc-category-image-wrapper">
485 <img src="' . BETTERDOCS_ADMIN_URL . 'assets/img/betterdocs-cat-icon.svg" alt="">
486 </div>
487 <p>
488 <input type="button" id="betterdocs_tax_media_button"
489 class="button button-secondary betterdocs_tax_media_button"
490 name="betterdocs_tax_media_button"
491 value="' . esc_html__('Add Image', 'betterdocs') . '" />
492 <input type="button"
493 id="doc_tax_media_remove"
494 class="button button-secondary doc_tax_media_remove"
495 name="doc_tax_media_remove"
496 value="' . esc_html__('Remove Image', 'betterdocs') . '" />
497 </p>
498 </div>';
499 do_action('betterdocs_doc_category_add_form_after');
500 }
501
502 /**
503 * Save the form field
504 *
505 * @since 1.0.0
506 */
507 public static function save_doc_category_meta($term_id)
508 {
509 if (isset($_POST['term_meta'])) {
510 $term_meta = get_option("doc_category_$term_id");
511 $cat_keys = array_keys($_POST['term_meta']);
512 foreach ($cat_keys as $key) {
513 if (isset($_POST['term_meta'][$key])) {
514 add_term_meta($term_id, "doc_category_$key", $_POST['term_meta'][$key]);
515 $term_meta[$key] = $_POST['term_meta'][$key];
516 }
517 }
518 }
519 if (isset($_POST['doc_category_kb'])) {
520 $doc_category_kb = $_POST['doc_category_kb'];
521 update_term_meta($term_id, "doc_category_knowledge_base", $doc_category_kb);
522 }
523 }
524
525 /**
526 * Edit the form field
527 *
528 * @since 1.0.0
529 */
530 public static function update_doc_category_meta($term, $taxonomy)
531 { ?>
532 <?php
533 $term_meta = get_option("doc_category_$term->term_id");
534 $cat_order = get_term_meta($term->term_id, 'doc_category_order', true);
535 $cat_icon_id = get_term_meta($term->term_id, 'doc_category_image-id', true);
536
537 do_action('betterdocs_doc_category_update_form_before', $term);
538 ?>
539 <tr class="form-field term-group-wrap">
540 <th scope="row">
541 <label for="doc-category-id"><?php esc_html_e('Category Id', 'betterdocs'); ?></label>
542 </th>
543 <td>
544 <input type="text" id="doc-category-id" style="width:100px" name="" value="<?php echo esc_attr($_GET["tag_ID"]) ?>" readonly>
545 </td>
546 </tr>
547 <tr class="form-field term-group-wrap">
548 <th scope="row">
549 <label for="doc-category-order"><?php esc_html_e('Order', 'betterdocs'); ?></label>
550 </th>
551 <td>
552 <input type="number" id="doc-category-order" style="width:100px" name="term_meta[order]" value="<?php echo $cat_order ? esc_attr($cat_order) : ''; ?>">
553 </td>
554 </tr>
555 <tr class="form-field term-group-wrap batterdocs-cat-media-upload">
556 <th scope="row">
557 <label><?php esc_html_e('Category Icon', 'betterdocs'); ?></label>
558 </th>
559 <td>
560 <input type="hidden" class="doc-category-image-id" name="term_meta[image-id]" value="<?php echo esc_attr($cat_icon_id); ?>">
561 <div class="doc-category-image-wrapper" id="doc-category-image-wrapper">
562 <?php
563 if ($cat_icon_id) {
564 echo wp_get_attachment_image($cat_icon_id, 'thumbnail');
565 } else {
566 echo '<img src="' . BETTERDOCS_ADMIN_URL . 'assets/img/betterdocs-cat-icon.svg" alt="">';
567 }
568 ?>
569 </div>
570 <p>
571 <input type="button" class="button button-secondary betterdocs_tax_media_button" id="betterdocs_tax_media_button" name="betterdocs_tax_media_button" value="<?php esc_html_e('Add Image', 'betterdocs'); ?>" />
572 <input type="button" class="button button-secondary doc_tax_media_remove" id="doc_tax_media_remove" name="doc_tax_media_remove" value="<?php esc_html_e('Remove Image', 'betterdocs'); ?>" />
573 </p>
574 </td>
575 </tr>
576 <?php
577 do_action('betterdocs_doc_category_update_form_after', $term);
578 }
579
580 /*
581 * Update the form field value
582 *
583 * @since 1.0.0
584 */
585 public static function updated_doc_category_meta($term_id)
586 {
587 if (isset($_POST['term_meta'])) {
588 $cat_keys = array_keys($_POST['term_meta']);
589 foreach ($cat_keys as $key) {
590 if (isset($_POST['term_meta'][$key])) {
591 update_term_meta($term_id, "doc_category_$key", $_POST['term_meta'][$key]);
592 }
593 }
594 }
595 if (isset($_POST['doc_category_kb'])) {
596 $doc_category_kb = $_POST['doc_category_kb'];
597 update_term_meta($term_id, "doc_category_knowledge_base", $doc_category_kb);
598 }
599 }
600
601 /*
602 * Add script
603 *
604 * @since 1.0.0
605 */
606 public static function add_script()
607 {
608 global $current_screen;
609 if ($current_screen->id == 'edit-doc_category') {
610 ?>
611 <script>
612 jQuery(document).ready(function($) {
613 function betterdocs_media_upload(button_class) {
614 var _custom_media = true,
615 _betterdocs_send_attachment = wp.media.editor.send.attachment;
616 $('body').on('click', button_class, function(e) {
617 let button_id = '#' + $(this).attr('id');
618 let send_attachment_bkp = wp.media.editor.send.attachment;
619 let button = $(button_id);
620 let imageId = $(this).parent().parent().find('.doc-category-image-id');
621 let imageWrapper = $(this).parent().parent().find('.doc-category-image-wrapper');
622
623 _custom_media = true;
624 wp.media.editor.send.attachment = function(props, attachment) {
625 if (_custom_media) {
626 imageId.val(attachment.id);
627 imageWrapper.html(
628 '<img class="custom_media_image" src="" style="margin:0;padding:0;max-height:100px;float:none;" />'
629 );
630 let custom_media_image = imageWrapper.find('.custom_media_image');
631 custom_media_image.attr('src', attachment
632 .url).css('display', 'block');
633 } else {
634 return _betterdocs_send_attachment.apply(button_id, [props, attachment]);
635 }
636 }
637 wp.media.editor.open(button);
638 return false;
639 });
640 }
641
642 betterdocs_media_upload('.betterdocs_tax_media_button.button');
643
644 $('body').on('click', '.doc_tax_media_remove', function() {
645 let imageId = $(this).parent().parent().find('.doc-category-image-id');
646 let imageWrapper = $(this).parent().parent().find('.doc-category-image-wrapper');
647 imageId.val('');
648 imageWrapper.html(
649 '<img class="custom_media_image" src="" style="margin:0;padding:0;max-height:100px;float:none;" />'
650 );
651 });
652
653 $(document).ajaxComplete(function(event, xhr, settings) {
654 var queryStringArr = settings.data.split('&');
655 if ($.inArray('action=add-tag', queryStringArr) !== -1) {
656 var xml = xhr.responseXML;
657 $response = $(xml).find('term_id').text();
658 if ($response != "") {
659 // Clear the thumb image
660 $('.doc-category-image-wrapper').html('');
661 }
662 }
663 });
664 });
665 </script>
666 <?php }
667 }
668
669 public static function generate_rewrite_rules($wp_rewrite)
670 {
671 if (!empty($wp_rewrite->rules['([^/]+)/?$']) && $wp_rewrite->rules['([^/]+)/?$'] == 'index.php?doc_category=$matches[1]') {
672 unset($wp_rewrite->rules['([^/]+)/?$']);
673 }
674 }
675
676 public static function docs_rewrite_parse_request($wp)
677 {
678 if(isset($wp->query_vars['post_type'], $wp->query_vars['doc_category'], $wp->query_vars['name']) && $wp->query_vars['post_type'] == 'docs'){
679 $loop_posts = new WP_Query( array(
680 'post_type' => 'docs',
681 'post_status' => 'any',
682 'name' => $wp->query_vars['name'],
683 'posts_per_page' => 1,
684 'fields' => 'all',
685 'tax_query' => array(
686 array(
687 'taxonomy' => 'doc_category',
688 'field' => 'slug',
689 'terms' => $wp->query_vars['doc_category'],
690 ),
691 ),
692 ) );
693 if(!$loop_posts->have_posts()){
694 $wp->query_vars['pagename'] = $wp->query_vars['doc_category'] . "/" . $wp->query_vars['name'];
695 unset( $wp->query_vars['doc_category'] );
696 unset( $wp->query_vars['post_type'] );
697 unset( $wp->query_vars['name'] );
698 unset( $wp->query_vars['docs'] );
699 }
700 }
701 }
702
703 /**
704 * Filtering post type rewrite rule.
705 *
706 * @param [type] $rewrite
707 * @return array $rewrite
708 */
709 public static function docs_rewrite($rewrite)
710 {
711 $permalink_structure = BetterDocs_DB::get_settings('permalink_structure');
712 $permalink = BetterDocs_Helper::permalink_stracture(self::$docs_slug, $permalink_structure);
713 if (!empty($permalink)) {
714 if (class_exists('BetterDocs_Multiple_Kb') && BetterDocs_Multiple_Kb::get_multiple_kb() != 1) {
715 $permalink = preg_replace('/%knowledge_base%\/?/', '', $permalink);
716 }
717 $rewrite = array('slug' => trim($permalink, '/'), 'with_front' => false);
718 }
719 return $rewrite;
720 }
721
722 /**
723 * Replacing %doc_category% placeholder in permalink.
724 *
725 * @param [type] $url
726 * @param [type] $post
727 * @param boolean $leavename
728 * @return string $url
729 */
730 public static function docs_show_permalinks($url, $post = null, $leavename = false)
731 {
732 if ($post->post_type != 'docs') {
733 return $url;
734 }
735 $doc_category = 'doc_category';
736 $cat_tag = '%' . $doc_category . '%';
737 $cat_terms = wp_get_object_terms($post->ID, $doc_category);
738
739 if (is_array($cat_terms) && sizeof($cat_terms) > 0) {
740 $doccat_terms = $cat_terms[0]->slug;
741 } else {
742 $doccat_terms = 'uncategorized';
743 }
744
745 if (class_exists('BetterDocs_Multiple_Kb') && BetterDocs_Multiple_Kb::get_multiple_kb() != 1) {
746 $url = preg_replace('/%knowledge_base%\/?/', '', $url);
747 }
748 return str_replace($cat_tag, $doccat_terms, $url);
749 }
750
751 public static function flush_rewrite_rules()
752 {
753 // Get the rewrite rules
754 $rules = get_option('rewrite_rules');
755 if (is_array($rules)) {
756 $rules = implode('', $rules);
757 }
758
759 if( ! is_plugin_active( 'betterdocs-pro/betterdocs-pro.php' ) ) {
760 if (strpos($rules, 'knowledge_base') !== false) {
761 flush_rewrite_rules();
762 }
763 }
764
765 if (!strpos($rules, 'docs')) {
766 flush_rewrite_rules();
767 }
768 }
769
770 /**
771 * Resister doc_category image field in rest API
772 */
773 public static function add_doc_category_meta_rest_api()
774 {
775 register_rest_field('doc_category', 'thumbnail', [
776 'get_callback' => array(__CLASS__, 'doc_category_thumbnail_image'),
777 'update_callback' => null,
778 'schema' => [
779 'description' => 'Holds the thumbnail URL of doc category',
780 'type' => 'string',
781 'format' => 'url',
782 ]
783 ]);
784 // endpoint for single doc reactions, this code will be refactored in the future
785 register_rest_route( 'betterdocs', '/feedback/(?P<id>\d+)', array(
786 'methods' => [ 'PUT', 'POST' ],
787 'callback' => array( __CLASS__, 'save_response' ),
788 'permission_callback' => '__return_true',
789 'args' => array(
790 'id' => array(
791 'validate_callback' => function($param, $request, $key) {
792 return is_numeric( $param );
793 }
794 ),
795 ),
796 ));
797 }
798
799
800 /**
801 * Save Feedback for individual Docs(Migrated From Pro To Free Version)
802 * @param WP_REST_Request $request
803 * @return void
804 */
805 public static function save_response( WP_REST_Request $request ){
806 global $wpdb;
807 $docs_id = isset( $request['id'] ) ? intval( $request['id'] ) : null;
808 $feelings = isset( $request['feelings'] ) ? $request['feelings'] : 'happy';
809 if( $docs_id !== null && get_option('betterdocs_pro_db_version') == true ) {
810 $post_id = $wpdb->get_results(
811 $wpdb->prepare(
812 "SELECT *
813 FROM {$wpdb->prefix}betterdocs_analytics
814 WHERE created_at = %s AND post_id = %d",
815 date('Y-m-d'),
816 $docs_id
817 )
818 );
819
820 if (!empty($post_id)) {
821 $feelings_increment = $post_id[0]->{$feelings} + 1;
822 $insert = $wpdb->query(
823 $wpdb->prepare(
824 "UPDATE {$wpdb->prefix}betterdocs_analytics
825 SET ".$feelings." = ". $feelings_increment ."
826 WHERE created_at = %s AND post_id = %d",
827 array(
828 date('Y-m-d'),
829 $docs_id
830 )
831 )
832 );
833 } else {
834 $insert = $wpdb->query(
835 $wpdb->prepare(
836 "INSERT INTO {$wpdb->prefix}betterdocs_analytics
837 ( post_id, ".$request['feelings'].", created_at )
838 VALUES ( %d, %d, %s )",
839 array(
840 $docs_id,
841 1,
842 date('Y-m-d')
843 )
844 )
845 );
846 }
847
848 if( $insert == true ) return true;
849
850 }
851 return false;
852 }
853
854 /**
855 *
856 * add doc_category meta field callback function
857 *
858 * @param [string|array] $object
859 * @return string $url
860 */
861 public static function doc_category_thumbnail_image($object)
862 {
863 $attachment_id = get_term_meta($object['id'], 'doc_category_image-id', true);
864 if (!$attachment_id) {
865 return;
866 }
867 $url = wp_get_attachment_url($attachment_id);
868 return $url;
869 }
870
871 }
872
873 BetterDocs_Docs_Post_Type::init();
874