PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 3.2.0
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v3.2.0
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 / Core / Query.php

Query.php in BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot 3.2.0, at includes/Core/Query.php

791 lines 25.4 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\Core;
4
5 use WP_Query;
6 use WPDeveloper\BetterDocs\Utils\Base;
7 use WPDeveloper\BetterDocs\Utils\Database;
8 use WPDeveloper\BetterDocs\Dependencies\DI\Container;
9
10 class Query extends Base {
11 private $container;
12 protected $database;
13 protected $settings;
14
15 public function __construct( Container $container, Database $database, Settings $settings ) {
16 $this->container = $container;
17 $this->database = $database;
18 $this->settings = $settings;
19
20 add_action( 'parse_term_query', [$this, 'parse_term_query'] );
21 // add_action( 'parse_query', [$this, 'parse_query'], 1 );
22 add_action( 'pre_get_posts', [$this, 'pre_get_posts'], 1 );
23
24 /**
25 * These below filters are hooked for navigation only.
26 *
27 * For old version of this portion.
28 * @see `betterdocs_single_post_nav` filter
29 *
30 * For details:
31 * @see https://developer.wordpress.org/reference/functions/get_next_post/
32 * @see https://developer.wordpress.org/reference/functions/get_previous_post/
33 *
34 * @link https://developer.wordpress.org/reference/hooks/get_adjacent_post_where/
35 */
36 add_filter( 'get_next_post_where', [$this, 'next_post_where'], 99, 5 );
37 add_filter( 'get_previous_post_where', [$this, 'previous_post_where'], 99, 5 );
38
39 $this->init();
40 }
41
42 public function init() {
43 }
44
45 public function parse_term_query( $term_query ) {
46 if ( empty( $term_query->query_vars['taxonomy'] ) ) {
47 return;
48 }
49
50 if ( ! in_array( 'doc_category', $term_query->query_vars['taxonomy'], true ) ) {
51 return;
52 }
53
54 global $current_screen;
55
56 if ( $current_screen == null ) {
57 return;
58 }
59
60 if ( $current_screen->taxonomy !== 'doc_category' || $current_screen->id != 'edit-doc_category' ) {
61 return;
62 }
63
64 $term_query->query_vars['meta_query'] = [[
65 'key' => 'doc_category_order',
66 'type' => 'NUMERIC'
67 ]];
68
69 $term_query->query_vars['orderby'] = 'meta_value_num';
70 }
71
72 public function parse_query( &$query ) {
73 // dump( is_single(), $query->query_vars );
74 // if ( is_single() && isset( $query->query_vars['post_type'] ) && $query->query_vars['post_type'] == 'docs' ) {
75 // $query->is_single = false;
76 // $query->is_archive = true;
77 // $query->set( 'knowledge_base', $query->query_vars['docs'] );
78 // }
79 }
80
81 public function pre_get_posts( &$query ) {
82 if ( is_admin() || ! $query->is_main_query() ) {
83 return;
84 }
85
86 if ( is_tax( 'doc_category' ) ) {
87 $query->set( 'post_type', 'docs' );
88 $query->set( 'posts_per_archive_page', -1 );
89
90 $term = get_term_by( 'slug', $query->get( 'doc_category', '' ), 'doc_category' );
91
92 $post__in = $this->get_docs_order_by_terms( $term->term_id );
93 if ( ! empty( $post__in ) ) {
94 $query->set( 'orderby', 'post__in' );
95 $query->set( 'post__in', $post__in );
96 }
97
98 // if ( ! empty( $query->query_vars['knowledge_base'] ) ) {
99 // $query->betterdocs_terms = get_terms( [
100 // 'taxonomy' => 'doc_category',
101 // 'parent' => 0,
102 // 'hide_empty' => true,
103 // 'meta_query' => [
104 // 'relation' => 'OR',
105 // [
106 // 'key' => 'doc_category_knowledge_base',
107 // 'value' => $query->query_vars['knowledge_base'],
108 // 'compare' => 'LIKE'
109 // ]
110 // ]
111 // ] );
112 // }
113 }
114
115 // dump( is_archive(), $query->query_vars );
116 }
117
118 /**
119 * Get docs orders by term_id.
120 *
121 * @since 2.5.0
122 * @param int $term_id
123 *
124 * @return array
125 */
126 public function get_docs_order_by_terms( $term_id ) {
127 global $wpdb;
128 $_docs_order = get_term_meta( $term_id, '_docs_order', true );
129 $query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}term_relationships WHERE term_taxonomy_id = %d", $term_id );
130 $query_key = "docs_order_by_terms_{$term_id}_" . md5( $query );
131
132 if ( ( $results = $this->database->get_cache( $query_key ) ) !== false ) {
133 return $results;
134 }
135
136 if ( ! empty( $_docs_order ) ) {
137 $_docs_order = explode( ',', $_docs_order );
138 $new_ids = [];
139
140 $results = $wpdb->get_results( $query );
141
142 if ( is_array( $results ) && ! empty( $results ) ) {
143 $object_ids = array_filter( $results, function ( $value ) use ( $_docs_order ) {
144 return ! in_array( $value->object_id, $_docs_order );
145 } );
146
147 if ( ! empty( $object_ids ) ) {
148 array_walk( $object_ids, function ( $value ) use ( &$new_ids ) {
149 $new_ids[] = $value->object_id;
150 } );
151 }
152 }
153
154 $_docs_order = array_merge( $new_ids, $_docs_order );
155 $this->database->set_cache( $query_key, $_docs_order, 1 );
156
157 return $_docs_order;
158 }
159
160 return [];
161 }
162
163 /**
164 * For determine the next post ID
165 *
166 * @link https://developer.wordpress.org/reference/hooks/get_adjacent_post_where/
167 *
168 * @param mixed $where
169 * @param mixed $in_same_term
170 * @param mixed $excluded_terms
171 * @param mixed $taxonomy
172 * @param mixed $post
173 * @return mixed
174 */
175 public function next_post_where( $where, $in_same_term, $excluded_terms, $taxonomy, $post ) {
176 return $this->get_adjacent_post_id( 'next', $where, $post, $taxonomy );
177 }
178
179 /**
180 * For determine the previous post ID
181 *
182 * @link https://developer.wordpress.org/reference/hooks/get_adjacent_post_where/
183 *
184 * @param mixed $where
185 * @param mixed $in_same_term
186 * @param mixed $excluded_terms
187 * @param mixed $taxonomy
188 * @param mixed $post
189 * @return mixed
190 */
191 public function previous_post_where( $where, $in_same_term, $excluded_terms, $taxonomy, $post ) {
192 return $this->get_adjacent_post_id( 'previous', $where, $post, $taxonomy );
193 }
194
195 /**
196 * Get where clause for next/previous post ID mainly used in post navigation.
197 *
198 * @see `previous_post_where` and `next_post_where` methods.
199 *
200 * @param mixed $adjacent
201 * @param mixed $where
202 * @param mixed $post
203 * @param mixed $taxonomy
204 * @return mixed
205 */
206 private function get_adjacent_post_id( $adjacent, $where, $post, $taxonomy ) {
207 if ( $taxonomy !== 'doc_category' ) {
208 return $where;
209 }
210
211 $_id = null;
212 $_terms = get_the_terms( $post->ID, 'doc_category' );
213 if ( empty( $_terms ) ) {
214 return $where;
215 }
216
217 global $wp_query, $wpdb;
218
219 $_docs_order = $this->get_docs_order_by_terms( $_terms[0]->term_id );
220
221 $_where = explode( 'AND', $where );
222 if ( is_array( $_where ) ) {
223 // $_where[0] = str_replace( 'WHERE ', '', $_where[0] );
224 unset( $_where[0] );
225 $_where = implode( 'AND', $_where );
226 }
227
228 $_orderby = $this->settings->get( 'alphabetically_order_post', 'betterdocs_order' );
229 $_order = $this->settings->get( 'docs_order', 'ASC' );
230 $_docs_order = $_orderby === 'betterdocs_order' ? $_docs_order : [];
231
232 if ( empty( $_docs_order ) ) {
233 $statuses = [ 'publish' ];
234
235 if( is_user_logged_in() ) {
236 $statuses[] = 'private';
237 }
238
239 $_args = [
240 'post_status' => $statuses
241 ];
242 if ( isset( $wp_query->query_vars['doc_category'] ) ) {
243 $_args['tax_query'][] = [
244 'taxonomy' => 'doc_category',
245 'field' => 'slug',
246 'terms' => $wp_query->query_vars['doc_category'],
247 'operator' => 'AND',
248 'include_children' => false
249 ];
250 }
251
252 $_args['orderby'] = $_orderby;
253 if ( $_orderby != 'betterdocs_order' ) {
254 $_args['order'] = $_order;
255 }
256
257 /**
258 * Before Query
259 */
260 do_action_ref_array( 'betterdocs_navigation_docs_query', [ &$_args] );
261 $docs = $this->get_posts( $this->docs_query_args( $_args ) );
262
263 $_docs = [];
264 if ( $docs->have_posts() ) {
265 array_map( function ( $post ) use ( &$_docs ) {
266 $_docs[] = $post->ID;
267 }, $docs->posts );
268 }
269
270 $_docs_order = $_docs;
271 }
272
273 $_docs_order = apply_filters( 'betterdocs_adjacent_docs_order', $_docs_order, $_terms );
274
275 $_id_index = array_search( $post->ID, $_docs_order );
276 $_id_index = $adjacent === 'next' ? $_id_index + 1 : $_id_index - 1;
277 $_id = isset( $_docs_order[$_id_index] ) ? (int) $_docs_order[$_id_index] : null;
278
279 return $wpdb->prepare( "WHERE p.ID = %s AND $_where", (int) $_id );
280 }
281
282 public function parse_terms_args( $args = [] ) {
283 $_default_args = [
284 'hide_empty' => true,
285 'taxonomy' => 'doc_category'
286 ];
287
288 // OrderBy & Order
289 $_orderby = ! empty( $args['orderby'] ) && $args['orderby'] != 1 ? $args['orderby'] : 'name';
290 $_order = ! empty( $args['order'] ) ? $args['order'] : '';
291
292 if ( $_orderby == 'betterdocs_order' ) {
293 $args['meta_key'] = 'doc_category_order';
294 $args['orderby'] = 'meta_value_num';
295 $args['order'] = 'ASC';
296 } else {
297 $args['orderby'] = $_orderby;
298 $args['order'] = $_order;
299 }
300
301 // Nested Sub Category
302 // $args['parent'] = 0;
303 // if ( $nested_subcategory == true ) {
304 // }
305
306 if ( ! isset( $args['number'] ) ) {
307 global $wp_query;
308 if ( $wp_query->query === NULL || ( isset( $wp_query->query['post_type'] ) && $wp_query->query['post_type'] != 'docs' ) ) {
309 $args['number'] = 4;
310 }
311 }
312
313 // Includes
314 if ( isset( $args['include'] ) ) {
315 $_include = ! is_array( $args['include'] ) ? explode( ',', $args['include'] ) : $args['include'];
316 $args['include'] = $_include;
317 $args['orderby'] = 'include';
318
319 unset( $args['parent'] );
320 }
321
322 $_meta_query = ! empty( $args['meta_query'] ) ? $args['meta_query'] : [];
323 $args['meta_query'] = apply_filters( 'betterdocs_taxonomy_object_meta_query', $_meta_query, $args );
324
325 return apply_filters( 'betterdocs_category_terms_object', wp_parse_args( $args, $_default_args ), $args );
326 }
327
328 public function get_terms( $args ) {
329 return get_terms( $this->parse_terms_args( $args ) );
330 }
331
332 public function get_child_terms( $args ) {
333 if ( ! isset( $args['number'] ) ) {
334 global $wp_query;
335 if ( $wp_query->query === NULL || ( isset( $wp_query->query['post_type'] ) && $wp_query->query['post_type'] != 'docs' ) ) {
336 $args['number'] = 1;
337 }
338 }
339
340 return $this->get_terms( $args );
341 }
342
343 /**
344 * Get POSTs of Docs type.
345 *
346 * @param mixed $args
347 * @return WP_Query
348 */
349 public function get_posts( $args, $ignore = false ) {
350 if ( ! $ignore ) {
351 $args = $this->docs_query_args( $args );
352 }
353
354 return new WP_Query( $args );
355 }
356
357 public function get_taxonomy( $tax = '' ) {
358 global $wp_query;
359 if ( is_tax( 'knowledge_base' ) ) {
360 $_tax = $wp_query->tax_query->queried_terms;
361 if ( array_key_exists( "doc_category", $_tax ) ) {
362 $tax = 'doc_category';
363 } else {
364 $tax = 'knowledge_base';
365 }
366 } elseif ( is_tax( 'doc_category' ) ) {
367 $tax = 'doc_category';
368 }
369
370 return $tax;
371 }
372
373 public function terms_query( $args = [] ) {
374 global $wp_query;
375 $_origin_args = $args;
376
377 $default_args = [
378 'hide_empty' => true,
379 'taxonomy' => 'doc_category',
380 'orderby' => 'name'
381 ];
382
383 /**
384 * Number Set
385 *
386 * @FIX: If Built-in Docs page off and docs_page in use, then Terms Query Number 4|1 set.
387 */
388 // if ( $wp_query->query === NULL || ( isset( $wp_query->query['post_type'] ) && $wp_query->query['post_type'] != 'docs' ) ) {
389 // $default_args['number'] = 1;
390 // }
391
392 /**
393 * Nested Sub Category
394 */
395 if ( isset( $args['nested_subcategory'] ) && $args['nested_subcategory'] == true ) {
396 $default_args['parent'] = 0;
397 unset( $args['nested_subcategory'] );
398 // if ( $wp_query->query === NULL || ( isset( $wp_query->query['post_type'] ) && $wp_query->query['post_type'] != 'docs' ) ) {
399 // $default_args['number'] = 4;
400 // }
401 }
402
403 /**
404 * OrderBy and Order
405 */
406 if ( ! isset( $args['orderby'] ) ) {
407 $_orderby = $this->settings->get( 'terms_orderby', 'name' );
408 $_order = $this->settings->get( 'terms_order', '' );
409 } else {
410 $_orderby = $args['orderby'];
411 $_order = ! empty( $args['order'] ) ? $args['order'] : '';
412 }
413
414 if ( 'betterdocs_order' === $_orderby ) {
415 $default_args['meta_key'] = 'doc_category_order';
416 $_orderby = 'meta_value_num';
417 $_order = 'ASC';
418 } elseif ( $_orderby === true ) {
419 $_orderby = 'name';
420 }
421
422 $args['orderby'] = $_orderby;
423 if( ! empty( $_order ) ) {
424 $args['order'] = $_order;
425 }
426
427 /**
428 * @todo old hook
429 * hook: betterdocs_child_taxonomy_meta_query
430 */
431 $_multiple_kb = apply_filters(
432 'betterdocs_query_args_multiple_kb_enabled',
433 isset( $args['multiple_kb'] ) ? (bool) $args['multiple_kb'] : false,
434 $_origin_args
435 );
436
437 $_kb_slug = isset( $args['kb_slug'] ) ? trim( $args['kb_slug'] ) : '';
438
439 unset( $args['multiple_kb'] );
440 unset( $args['kb_slug'] );
441
442 $meta_query = ! empty( $args['meta_query'] ) ? $args['meta_query'] : [];
443 $meta_query = apply_filters( 'betterdocs_terms_meta_query_args', $meta_query, $_multiple_kb, $_kb_slug, $_origin_args );
444
445 if ( ! empty( $meta_query ) ) {
446 $default_args['meta_query'] = $meta_query;
447 }
448
449 if ( ! empty( $args['terms'] ) ) {
450 $args['include'] = explode( ',', $args['terms'] );
451 $args['orderby'] = 'include';
452 $args['order'] = 'ASC';
453
454 unset( $default_args['parent'] );
455 unset( $args['parent'] );
456 unset( $args['terms'] );
457 }
458
459 $_query_args = wp_parse_args( $args, $default_args );
460 return apply_filters( 'betterdocs_terms_query_args', $_query_args, $_origin_args );
461 }
462
463 public function get_term_parents( $term_id, $taxonomy = 'doc_category', $args = [] ) {
464 $term = get_term( $term_id, $taxonomy );
465 if ( is_wp_error( $term ) ) {
466 return $term;
467 }
468
469 if ( ! $term ) {
470 return [];
471 }
472
473 $_lists = [];
474 $origin_term = $term_id;
475 $term_id = $term->term_id;
476
477 $defaults = [
478 'format' => 'name',
479 'inclusive' => true
480 ];
481
482 $args = wp_parse_args( $args, $defaults );
483
484 $args['inclusive'] = wp_validate_boolean( $args['inclusive'] );
485
486 $parents = get_ancestors( $term_id, $taxonomy );
487
488 if ( $args['inclusive'] ) {
489 array_unshift( $parents, $term_id );
490 }
491
492 foreach ( array_reverse( $parents ) as $term_id ) {
493 $parent = get_term( $term_id, $taxonomy );
494 $name = ( 'slug' === $args['format'] ) ? $parent->slug : $parent->name;
495 $term_permalink = get_term_link( $parent->term_id, $taxonomy );
496 $term_permalink = apply_filters( 'betterdocs_breadcrumb_term_permalink', $term_permalink, $term_id );
497
498 $_item = [
499 'url' => $term_permalink,
500 'text' => $name
501 ];
502
503 $_lists[] = $_item;
504 }
505
506 return apply_filters( 'betterdocs_breadcrumb_archive_lists', $_lists, $origin_term );
507 }
508
509 /**
510 * Summary of docs_query_args
511 * @param mixed $args
512 * @throws \Exception
513 * @return mixed
514 */
515 public function docs_query_args( $args, $filter = [] ) {
516 $_origin_args = $args;
517
518 $default_args = [
519 'post_type' => 'docs'
520 ];
521
522 if ( ! empty( $args['post_type'] ) && trim( $args['post_type'] ) === 'docs_any' ) {
523 $default_args['post_type'] = 'docs';
524 $default_args['post_status'] = 'any';
525
526 unset( $args['post_type'] );
527 }
528
529 /**
530 * OrderBy and Order
531 */
532 if ( ! isset( $args['orderby'] ) ) {
533 $_orderby = $this->settings->get( 'alphabetically_order_post' );
534 $_order = $this->settings->get( 'docs_order', 'ASC' );
535 } else {
536 $_orderby = $args['orderby'];
537 $_order = ! empty( $args['order'] ) ? $args['order'] : 'ASC';
538 }
539
540 if ( 'betterdocs_order' != $_orderby ) {
541 if ( $_orderby === true ) {
542 $args['orderby'] = 'title';
543 } else {
544 $args['orderby'] = $_orderby;
545 }
546
547 $args['order'] = $_order;
548 } elseif ( 'betterdocs_order' == $_orderby ) {
549 unset( $args['orderby'] );
550 }
551
552 if ( empty( $args['orderby'] ) ) {
553 unset( $args['order'] );
554 }
555
556 /**
557 * Term ID
558 */
559 $_term_id = null;
560 if ( ! empty( $args['term_id'] ) ) {
561 $_term_id = intval( $args['term_id'] );
562 unset( $args['term_id'] );
563 }
564
565 // if ( $_term_id == null ) {
566 // throw new \Exception( __( '$args["term_id"] cannot be null.', 'betterdocs' ) );
567 // }
568
569 /**
570 * Term Slug for tax_query
571 */
572 $_term_slug = '';
573 if ( ! empty( $args['term_slug'] ) ) {
574 $_term_slug = trim( $args['term_slug'] );
575 unset( $args['term_slug'] );
576 }
577
578 /**
579 * @todo old hook
580 * hook: betterdocs_cat_template_multikb
581 */
582
583 $_multiple_kb = apply_filters(
584 'betterdocs_enable_multiple_knowledge_base',
585 isset( $args['multiple_kb'] ) ? (bool) $args['multiple_kb'] : false,
586 $_origin_args
587 );
588
589 $_kb_slug = isset( $args['kb_slug'] ) ? trim( $args['kb_slug'] ) : '';
590
591 unset( $args['multiple_kb'] );
592 unset( $args['kb_slug'] );
593
594 $tax_query = [
595 [
596 'taxonomy' => 'doc_category',
597 'field' => 'slug',
598 'terms' => $_term_slug,
599 'operator' => 'AND',
600 'include_children' => false
601 ]
602 ];
603
604 if ( isset( $args['tax_query'] ) ) {
605 $tax_query = $args['tax_query'];
606 }
607
608 $args['tax_query'] = apply_filters(
609 'betterdocs_docs_tax_query_args',
610 $tax_query, $_multiple_kb, $_term_slug, $_kb_slug, $_origin_args
611 );
612 /**
613 * Final parse args
614 */
615 $args = wp_parse_args( $args, $default_args );
616
617 if ( ! empty( $filter ) ) {
618 $filter = array_flip( $filter );
619 $args = array_filter( $args, function ( $item ) use ( $filter ) {
620 return ! array_key_exists( $item, $filter );
621 }, ARRAY_FILTER_USE_KEY );
622 }
623
624 return apply_filters( 'betterdocs_articles_args', $args, $_term_id, $_origin_args );
625 }
626
627 public function faq_terms_query_args( $includes = '', $excludes = '', $args = [] ) {
628 $_args = [
629 'taxonomy' => 'betterdocs_faq_category',
630 'meta_key' => 'order',
631 'orderby' => 'meta_value_num',
632 'order' => 'ASC',
633 'include' => $includes,
634 'exclude' => $excludes,
635 'meta_query' => [
636 [
637 'key' => 'status',
638 'value' => 1,
639 'compare' => '=='
640 ]
641 ]
642 ];
643
644 if ( $_args['include'] == 'all' ) {
645 unset( $_args['include'] );
646 unset( $_args['exclude'] );
647 }
648
649 if ( empty( $_args['exclude'] ) ) {
650 unset( $_args['exclude'] );
651 }
652
653 if ( empty( $_args['include'] ) ) {
654 unset( $_args['include'] );
655 }
656
657 return wp_parse_args( $args, $_args );
658 }
659
660 public function get_faq_by_term( $term_id ) {
661 global $wpdb;
662
663 $args = [
664 'post_type' => 'betterdocs_faq',
665 'post_status' => 'publish',
666 'tax_query' => [
667 [
668 'taxonomy' => 'betterdocs_faq_category',
669 'field' => 'term_id',
670 'terms' => $term_id,
671 'operator' => 'AND'
672 ]
673 ],
674 'posts_per_page' => -1
675 ];
676
677 $args['orderby'] = 'post__in';
678 $args['post__in'] = $this->get_faq_orders( $term_id );
679
680 return new WP_Query( $args );
681 }
682
683 public function get_faq_orders( $term_id = null ) {
684 global $wpdb;
685 $faq_order = get_term_meta( $term_id, '_betterdocs_faq_order', true );
686 $faq_order = explode( ',', $faq_order );
687
688 $query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}term_relationships WHERE term_taxonomy_id = %d", $term_id );
689 $query_key = "betterdocs_faq_order_" . md5( $query );
690
691 if ( ( $results = $this->database->get_cache( $query_key ) ) !== false ) {
692 return $results;
693 }
694
695 if ( ! empty( $faq_order ) ) {
696 $new_ids = [];
697 $results = $wpdb->get_results( $query );
698
699 if ( ! is_null( $results ) && ! empty( $results ) && is_array( $results ) ) {
700 $object_ids = array_filter( $results, function ( $value ) use ( $faq_order ) {
701 return ! in_array( $value->object_id, $faq_order );
702 } );
703
704 if ( ! empty( $object_ids ) ) {
705 array_walk( $object_ids, function ( $value ) use ( &$new_ids ) {
706 $new_ids[] = $value->object_id;
707 } );
708 }
709 }
710
711 $faq_order = array_merge( $new_ids, $faq_order );
712 }
713
714 $this->database->set_cache( $query_key, $faq_order, 1 );
715
716 return $faq_order;
717 }
718
719 public function get_faq_terms( $terms = [] ) {
720 $_terms = get_terms( [
721 'taxonomy' => 'betterdocs_faq_category',
722 'hide_empty' => true,
723 'orderby' => 'name',
724 'order' => 'ASC',
725 'meta_query' => [
726 [
727 'key' => 'status',
728 'value' => 1,
729 'compare' => '=='
730 ]
731 ]
732 ] );
733
734 if ( ! is_wp_error( $_terms ) ) {
735 foreach ( $_terms as $term ) {
736 $terms[$term->term_id] = $term->name;
737 }
738 }
739
740 return $terms;
741 }
742
743 public function get_docs_count( $term, $nested_subcategory = false, $args = [] ) {
744 $counts = isset( $term->count ) ? $term->count : 0;
745
746 if ( $nested_subcategory == false ) {
747 return apply_filters( 'betterdocs_docs_count', $counts, $term, $nested_subcategory, $args );
748 }
749
750 $_child_terms_docs_ids = $this->get_doc_ids_by_term( $term, null, $nested_subcategory );
751 if ( is_array( $_child_terms_docs_ids ) ) {
752 $counts = count( $_child_terms_docs_ids );
753 }
754
755 return apply_filters( 'betterdocs_docs_count', $counts, $term, $nested_subcategory, $args );
756 }
757
758 public function get_doc_ids_by_term( $term, $optional = null, $nested_subcategory = false ) {
759 $args = [ 'include' => $term->term_id ];
760 if( $nested_subcategory ) {
761 $args['child_of'] = $term->term_id;
762 unset( $args['include'] );
763 }
764 $_child_terms = get_terms( $term->taxonomy, $args );
765
766 if ( ! is_array( $_child_terms ) ) {
767 return false;
768 }
769
770 array_unshift( $_child_terms, $term );
771
772 $_child_terms_ids = array_column( $_child_terms, 'term_id' );
773 $_child_terms_taxs = array_column( $_child_terms, 'taxonomy' );
774 $_child_terms_docs_ids = get_objects_in_term( $_child_terms_ids, $_child_terms_taxs );
775
776 if ( $optional !== null ) {
777 $_optional_doc_ids = get_objects_in_term( $optional->term_id, $optional->taxonomy );
778 $_child_terms_docs_ids = array_intersect( $_child_terms_docs_ids, $_optional_doc_ids );
779 }
780
781 return array_filter( $_child_terms_docs_ids, function ( $doc_id ) {
782 if ( ! is_user_logged_in() ) {
783 return is_post_publicly_viewable( $doc_id );
784 }
785
786 $_status = get_post_status( $doc_id );
787 return $_status == 'private' || is_post_publicly_viewable( $doc_id );
788 } );
789 }
790 }
791