PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 3.5.3
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v3.5.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
← All changes | includes/Core/Query.php +256 -809 4.5.43.5.3 View file →
@@ -16,12 +16,11 @@
16 16 $this->container = $container;
17 17 $this->database = $database;
18 18 $this->settings = $settings;
19 19
20 - add_action( 'parse_term_query', array( $this, 'parse_term_query' ) );
20 + add_action( 'parse_term_query', [$this, 'parse_term_query'] );
21 21 // add_action( 'parse_query', [$this, 'parse_query'], 1 );
22 - add_action( 'pre_get_posts', array( $this, 'pre_get_posts' ), 1 );
23 - add_filter( 'betterdocs_base_terms_args', array( $this, 'modify_terms_args_for_private_docs' ), 10, 1 );
22 + add_action( 'pre_get_posts', [$this, 'pre_get_posts'], 1 );
24 23
25 24 /**
26 25 * These below filters are hooked for navigation only.
27 26 *
@@ -33,10 +32,10 @@
33 32 * @see https://developer.wordpress.org/reference/functions/get_previous_post/
34 33 *
35 34 * @link https://developer.wordpress.org/reference/hooks/get_adjacent_post_where/
36 35 */
37 - add_filter( 'get_next_post_where', array( $this, 'next_post_where' ), 99, 5 );
38 - add_filter( 'get_previous_post_where', array( $this, 'previous_post_where' ), 99, 5 );
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 );
39 38
40 39 $this->init();
41 40
42 41 /**
@@ -41,29 +40,21 @@
41 40
42 41 /**
43 42 * Modify Popular Docs Query (For Shortcode & Widget)
44 43 */
45 - add_filter( 'posts_clauses', array( $this, 'mod_query_popular_docs' ), 10, 2 );
44 + add_filter( 'posts_clauses', [$this, 'mod_query_popular_docs'], 10, 2 );
46 45 }
47 46
48 47 public function mod_query_popular_docs( $clauses, $wp_query ) {
49 - if ( isset( $wp_query->query[ 'meta_key' ] ) ) {
50 - if ( '_betterdocs_meta_views' == $wp_query->query[ 'meta_key' ] ) {
48 + if ( isset( $wp_query->query['meta_key'] ) ) {
49 + if ( $wp_query->query['meta_key'] == '_betterdocs_meta_views' ) {
51 50 global $wpdb;
52 - $order = isset( $wp_query->query[ 'order' ] ) ? $wp_query->query[ 'order' ] : '';
53 - $order_by_query = ( 'ASC' == $order || 'DESC' == $order ) ? "SUM({$wpdb->prefix}betterdocs_analytics.impressions) {$order}" : ( 'MODIFIED' == $order ? "{$wpdb->prefix}posts.post_modified_gmt DESC" : "{$wpdb->prefix}posts.post_date_gmt DESC" );
54 - $clauses[ 'join' ] = "JOIN {$wpdb->prefix}betterdocs_analytics ON {$wpdb->prefix}posts.ID = {$wpdb->prefix}betterdocs_analytics.post_id";
55 - $clauses[ 'where' ] = ! current_user_can( 'read_private_docs' ) ? "AND ( ( {$wpdb->prefix}posts.post_type = 'docs' ) AND ( {$wpdb->prefix}posts.post_status = 'publish' OR {$wpdb->prefix}posts.post_status = 'future' ) )" : "AND ( ( {$wpdb->prefix}posts.post_type = 'docs' ) AND ( {$wpdb->prefix}posts.post_status = 'publish' OR {$wpdb->prefix}posts.post_status = 'future' OR {$wpdb->prefix}posts.post_status = 'draft' OR {$wpdb->prefix}posts.post_status = 'pending' OR {$wpdb->prefix}posts.post_status = 'private' ) )";
56 - $clauses[ 'orderby' ] = $order_by_query;
57 - $clauses[ 'groupby' ] = "{$wpdb->prefix}betterdocs_analytics.post_id";
58 - if ( is_plugin_active( 'sitepress-multilingual-cms/sitepress.php' ) ) {
59 - global $sitepress;
60 - if ( $sitepress->is_setup_complete() ) {
61 - $constant_language_code = ICL_LANGUAGE_CODE;
62 - $clauses[ 'join' ] .= " JOIN {$wpdb->prefix}icl_translations ON {$wpdb->prefix}posts.ID = {$wpdb->prefix}icl_translations.element_id";
63 - $clauses[ 'where' ] .= " AND ( {$wpdb->prefix}icl_translations.language_code = '{$constant_language_code}' ) AND ( {$wpdb->prefix}icl_translations.element_type = CONCAT('post_', {$wpdb->prefix}posts.post_type ) )";
64 - }
65 - }
51 + $order = isset( $wp_query->query['order'] ) ? $wp_query->query['order'] : '';
52 + $order_by_query = ( $order == 'ASC' || $order == 'DESC' ) ? "SUM({$wpdb->prefix}betterdocs_analytics.impressions) {$order}" : ( $order == 'MODIFIED' ? "{$wpdb->prefix}posts.post_modified_gmt DESC" : "{$wpdb->prefix}posts.post_date_gmt DESC" );
53 + $clauses['join'] = "JOIN {$wpdb->prefix}betterdocs_analytics ON {$wpdb->prefix}posts.ID = {$wpdb->prefix}betterdocs_analytics.post_id";
54 + $clauses['where'] = "AND ( ( {$wpdb->prefix}posts.post_type = 'docs' ) AND ( {$wpdb->prefix}posts.post_status = 'publish' OR {$wpdb->prefix}posts.post_status = 'future' OR {$wpdb->prefix}posts.post_status = 'draft' OR {$wpdb->prefix}posts.post_status = 'pending' OR {$wpdb->prefix}posts.post_status = 'private' ) )";
55 + $clauses['orderby'] = $order_by_query;
56 + $clauses['groupby'] = "{$wpdb->prefix}betterdocs_analytics.post_id";
66 57 }
67 58 }
68 59 return $clauses;
69 60 }
@@ -70,68 +61,33 @@
70 61
71 62 public function init() {
72 63 }
73 64
74 - /**
75 - * Modify terms args to include terms with only private docs for users with read_private_docs capability
76 - *
77 - * @param array $args
78 - * @return array
79 - */
80 - public function modify_terms_args_for_private_docs( $args ) {
81 - // Only modify for users with read_private_docs capability and supported taxonomies
82 - if ( ! current_user_can( 'read_private_docs' ) || ! isset( $args[ 'taxonomy' ] ) ) {
83 - return $args;
84 - }
85 -
86 - // Only support doc_category taxonomy for private docs filtering
87 - // knowledge_base terms don't have docs directly assigned to them
88 - $supported_taxonomies = array( 'doc_category' );
89 - if ( ! in_array( $args[ 'taxonomy' ], $supported_taxonomies ) ) {
90 - return $args;
91 - }
92 -
93 - // If hide_empty is true, we need to modify the logic to include terms with private docs
94 - if ( isset( $args[ 'hide_empty' ] ) && $args[ 'hide_empty' ] ) {
95 - // Set hide_empty to false and we'll filter manually later
96 - $args[ 'hide_empty' ] = false;
97 - // Add a flag to indicate we need to filter manually
98 - $args[ '_betterdocs_filter_private' ] = true;
99 - }
100 -
101 - return $args;
102 - }
103 -
104 65 public function parse_term_query( $term_query ) {
105 - if ( empty( $term_query->query_vars[ 'taxonomy' ] ) ) {
66 + if ( empty( $term_query->query_vars['taxonomy'] ) ) {
106 67 return;
107 68 }
108 69
109 - if ( ! in_array( 'doc_category', $term_query->query_vars[ 'taxonomy' ], true ) ) {
70 + if ( ! in_array( 'doc_category', $term_query->query_vars['taxonomy'], true ) ) {
110 71 return;
111 72 }
112 73
113 74 global $current_screen;
114 75
115 - if ( null == $current_screen ) {
76 + if ( $current_screen == null ) {
116 77 return;
117 78 }
118 79
119 - if ( 'doc_category' !== $current_screen->taxonomy || 'edit-doc_category' != $current_screen->id ) {
80 + if ( $current_screen->taxonomy !== 'doc_category' || $current_screen->id != 'edit-doc_category' ) {
120 81 return;
121 82 }
122 83
123 - // Use base meta key for admin listing - fallback logic is handled in set_tax_order
124 - $meta_key = 'doc_category_order';
84 + $term_query->query_vars['meta_query'] = [[
85 + 'key' => 'doc_category_order',
86 + 'type' => 'NUMERIC'
87 + ]];
125 88
126 - $term_query->query_vars[ 'meta_query' ] = array(
127 - array(
128 - 'key' => $meta_key,
129 - 'type' => 'NUMERIC'
130 - )
131 - );
132 -
133 - $term_query->query_vars[ 'orderby' ] = 'meta_value_num';
89 + $term_query->query_vars['orderby'] = 'meta_value_num';
134 90 }
135 91
136 92 public function parse_query( &$query ) {
137 93 // dump( is_single(), $query->query_vars );
@@ -152,13 +108,9 @@
152 108 $query->set( 'posts_per_archive_page', -1 );
153 109
154 110 $term = get_term_by( 'slug', $query->get( 'doc_category', '' ), 'doc_category' );
155 111
156 - if ( $term && isset( $term->term_id ) ) {
157 - $post__in = $this->get_docs_order_by_terms( $term->term_id );
158 - } else {
159 - $post__in = array();
160 - }
112 + $post__in = $this->get_docs_order_by_terms( $term->term_id );
161 113 if ( ! empty( $post__in ) ) {
162 114 $query->set( 'orderby', 'post__in' );
163 115 $query->set( 'post__in', $post__in );
164 116 }
@@ -192,41 +144,31 @@
192 144 * @return array
193 145 */
194 146 public function get_docs_order_by_terms( $term_id ) {
195 147 global $wpdb;
148 + $_docs_order = get_term_meta( $term_id, '_docs_order', true );
149 + $query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}term_relationships WHERE term_taxonomy_id = %d", $term_id );
150 + $query_key = "docs_order_by_terms_{$term_id}_" . md5( $query );
196 151
197 - // Get language-specific meta key with fallback
198 - $meta_key = \WPDeveloper\BetterDocs\Utils\Helper::get_meta_key_with_fallback( '_docs_order', $term_id );
199 - $_docs_order = get_term_meta( $term_id, $meta_key, true );
200 -
201 - $query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}term_relationships WHERE term_taxonomy_id = %d", $term_id );
202 - $query_key = "docs_order_by_terms_{$term_id}_{$meta_key}_" . md5( $query );
203 -
204 - if ( ( $results = $this->database->get_cache( $query_key ) ) !== false ) {
152 + if ( ( $results = $this->database->get_cache( $query_key ) ) !== false ) {
205 153 return $results;
206 154 }
207 155
208 156 if ( ! empty( $_docs_order ) ) {
209 157 $_docs_order = explode( ',', $_docs_order );
210 - $new_ids = array();
158 + $new_ids = [];
211 159
212 - $results = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
160 + $results = $wpdb->get_results( $query );
213 161
214 162 if ( is_array( $results ) && ! empty( $results ) ) {
215 - $object_ids = array_filter(
216 - $results,
217 - function ( $value ) use ( $_docs_order ) {
218 - return ! in_array( $value->object_id, $_docs_order );
219 - }
220 - );
163 + $object_ids = array_filter( $results, function ( $value ) use ( $_docs_order ) {
164 + return ! in_array( $value->object_id, $_docs_order );
165 + } );
221 166
222 167 if ( ! empty( $object_ids ) ) {
223 - array_walk(
224 - $object_ids,
225 - function ( $value ) use ( &$new_ids ) {
226 - $new_ids[ ] = $value->object_id;
227 - }
228 - );
168 + array_walk( $object_ids, function ( $value ) use ( &$new_ids ) {
169 + $new_ids[] = $value->object_id;
170 + } );
229 171 }
230 172 }
231 173
232 174 $_docs_order = array_merge( $new_ids, $_docs_order );
@@ -234,9 +176,9 @@
234 176
235 177 return $_docs_order;
236 178 }
237 179
238 - return array();
180 + return [];
239 181 }
240 182
241 183 /**
242 184 * For determine the next post ID
@@ -281,9 +223,9 @@
281 223 * @param mixed $taxonomy
282 224 * @return mixed
283 225 */
284 226 private function get_adjacent_post_id( $adjacent, $where, $post, $taxonomy ) {
285 - if ( 'doc_category' !== $taxonomy ) {
227 + if ( $taxonomy !== 'doc_category' ) {
286 228 return $where;
287 229 }
288 230
289 231 $_id = null;
@@ -293,84 +235,57 @@
293 235 }
294 236
295 237 global $wp_query, $wpdb;
296 238
297 - $_docs_order = $this->get_docs_order_by_terms( $_terms[ 0 ]->term_id );
239 + $_docs_order = $this->get_docs_order_by_terms( $_terms[0]->term_id );
298 240
241 + $_where = explode( 'AND', $where );
242 + if ( is_array( $_where ) ) {
243 + // $_where[0] = str_replace( 'WHERE ', '', $_where[0] );
244 + unset( $_where[0] );
245 + $_where = implode( 'AND', $_where );
246 + }
247 +
299 248 $_orderby = $this->settings->get( 'alphabetically_order_post', 'betterdocs_order' );
300 249 $_order = $this->settings->get( 'docs_order', 'ASC' );
301 - $_docs_order = 'betterdocs_order' === $_orderby ? $_docs_order : array();
250 + $_docs_order = $_orderby === 'betterdocs_order' ? $_docs_order : [];
302 251
303 252 if ( empty( $_docs_order ) ) {
304 - $statuses = array( 'publish' );
253 + $statuses = [ 'publish' ];
305 254
306 - if ( current_user_can( 'read_private_docs' ) ) {
307 - $statuses[ ] = 'private';
255 + if( is_user_logged_in() ) {
256 + $statuses[] = 'private';
308 257 }
309 258
310 - $_args = array(
311 - 'post_status' => $statuses,
312 - 'term_id' => $_terms[ 0 ]->term_id
313 - );
314 - if ( isset( $wp_query->query_vars[ 'doc_category' ] ) ) {
315 - $_args[ 'tax_query' ][ ] = array(
316 - 'taxonomy' => 'doc_category',
317 - 'field' => 'slug',
318 - 'terms' => $wp_query->query_vars[ 'doc_category' ],
319 - 'operator' => 'AND',
259 + $_args = [
260 + 'post_status' => $statuses
261 + ];
262 + if ( isset( $wp_query->query_vars['doc_category'] ) ) {
263 + $_args['tax_query'][] = [
264 + 'taxonomy' => 'doc_category',
265 + 'field' => 'slug',
266 + 'terms' => $wp_query->query_vars['doc_category'],
267 + 'operator' => 'AND',
320 268 'include_children' => false
321 - );
322 - } elseif ( isset( $wp_query->query_vars[ 'name' ] ) && isset( $wp_query->query_vars[ 'post_type' ] ) && 'docs' == $wp_query->query_vars[ 'post_type' ] ) {
323 - $_post = get_page_by_path( $wp_query->query_vars[ 'name' ], OBJECT, 'docs' );
324 - $doc_terms = array();
325 -
326 - if ( isset( $_post->ID ) ) {
327 - $terms = get_the_terms( $_post->ID, 'doc_category' );
328 - if ( ! empty( $terms ) ) {
329 - $doc_terms = wp_list_pluck( $terms, 'term_id' );
330 - }
331 - }
332 -
333 - if ( ! empty( $doc_terms ) ) {
334 - $_args[ 'tax_query' ][ ] = array(
335 - 'taxonomy' => 'doc_category',
336 - 'field' => 'term_id',
337 - 'terms' => $doc_terms,
338 - 'operator' => 'AND',
339 - 'include_children' => false
340 - );
341 - $_args[ 'term_id' ] = $doc_terms[ 0 ];
342 - }
343 - } else {
344 - // Fallback: use the term from current post
345 - $_args[ 'tax_query' ][ ] = array(
346 - 'taxonomy' => 'doc_category',
347 - 'field' => 'term_id',
348 - 'terms' => $_terms[ 0 ]->term_id,
349 - 'operator' => 'AND',
350 - 'include_children' => false
351 - );
269 + ];
352 270 }
353 271
354 - $_args[ 'orderby' ] = $_orderby;
355 - if ( 'betterdocs_order' != $_orderby ) {
356 - $_args[ 'order' ] = $_order;
272 + $_args['orderby'] = $_orderby;
273 + if ( $_orderby != 'betterdocs_order' ) {
274 + $_args['order'] = $_order;
357 275 }
358 276
359 277 /**
360 278 * Before Query
361 279 */
362 - do_action_ref_array( 'betterdocs_navigation_docs_query', array( &$_args ) );
280 + do_action_ref_array( 'betterdocs_navigation_docs_query', [ &$_args] );
363 281 $docs = $this->get_posts( $this->docs_query_args( $_args ) );
364 282
365 - $_docs = array();
283 + $_docs = [];
366 284 if ( $docs->have_posts() ) {
367 - array_map(
368 - function ( $_post ) use ( &$_docs ) {
369 - $_docs[ ] = $_post->ID;
370 - },
371 - $docs->posts
372 - );
285 + array_map( function ( $post ) use ( &$_docs ) {
286 + $_docs[] = $post->ID;
287 + }, $docs->posts );
373 288 }
374 289
375 290 $_docs_order = $_docs;
376 291 }
@@ -376,49 +291,32 @@
376 291 }
377 292
378 293 $_docs_order = apply_filters( 'betterdocs_adjacent_docs_order', $_docs_order, $_terms );
379 294
380 - // Ensure consistent type comparison by converting all IDs to integers
381 - $_docs_order = array_map( 'intval', $_docs_order );
382 - $_docs_order = array_values( $_docs_order ); // Re-index array after type conversion
295 + $_id_index = array_search( $post->ID, $_docs_order );
296 + $_id_index = $adjacent === 'next' ? $_id_index + 1 : $_id_index - 1;
297 + $_id = isset( $_docs_order[$_id_index] ) ? (int) $_docs_order[$_id_index] : null;
383 298
384 - $_id_index = array_search( (int) $post->ID, $_docs_order, true );
385 -
386 - // If current post not found in order list, return original where clause
387 - if ( false === $_id_index ) {
388 - return $where;
389 - }
390 -
391 - $_id_index = 'next' === $adjacent ? $_id_index + 1 : $_id_index - 1;
392 - $_id = isset( $_docs_order[ $_id_index ] ) ? (int) $_docs_order[ $_id_index ] : null;
393 -
394 - // Fix: replace only ID comparison in where clause using regex
395 - if ( $_id ) {
396 - // This replaces any 'p.ID < N', 'p.ID > N', 'p.ID <= N', or 'p.ID >= N' etc, with 'p.ID = $_id'
397 - $where = preg_replace( '/p\.ID\s*[<>!=]+\s*\d+/', 'p.ID = ' . (int) $_id, $where );
398 - }
399 -
400 - return $where;
299 + return $wpdb->prepare( "WHERE p.ID = %s AND $_where", (int) $_id );
401 300 }
402 301
403 - public function parse_terms_args( $args = array() ) {
404 - $_default_args = array(
302 + public function parse_terms_args( $args = [] ) {
303 + $_default_args = [
405 304 'hide_empty' => true,
406 - 'taxonomy' => 'doc_category'
407 - );
305 + 'taxonomy' => 'doc_category'
306 + ];
408 307
409 308 // OrderBy & Order
410 - $_orderby = ! empty( $args[ 'orderby' ] ) && 1 != $args[ 'orderby' ] ? $args[ 'orderby' ] : 'name';
411 - $_order = ! empty( $args[ 'order' ] ) ? $args[ 'order' ] : '';
309 + $_orderby = ! empty( $args['orderby'] ) && $args['orderby'] != 1 ? $args['orderby'] : 'name';
310 + $_order = ! empty( $args['order'] ) ? $args['order'] : '';
412 311
413 - if ( 'betterdocs_order' == $_orderby ) {
414 - // Use base meta key - fallback logic will be handled in the terms_clauses filter
415 - $args[ 'meta_key' ] = 'doc_category_order';
416 - $args[ 'orderby' ] = 'meta_value_num';
417 - $args[ 'order' ] = 'ASC';
312 + if ( $_orderby == 'betterdocs_order' ) {
313 + $args['meta_key'] = 'doc_category_order';
314 + $args['orderby'] = 'meta_value_num';
315 + $args['order'] = 'ASC';
418 316 } else {
419 - $args[ 'orderby' ] = $_orderby;
420 - $args[ 'order' ] = $_order;
317 + $args['orderby'] = $_orderby;
318 + $args['order'] = $_order;
421 319 }
422 320
423 321 // Nested Sub Category
424 322 // $args['parent'] = 0;
@@ -424,51 +322,39 @@
424 322 // $args['parent'] = 0;
425 323 // if ( $nested_subcategory == true ) {
426 324 // }
427 325
428 - if ( ! isset( $args[ 'number' ] ) ) {
326 + if ( ! isset( $args['number'] ) ) {
429 327 global $wp_query;
430 - if ( null === $wp_query->query || ( isset( $wp_query->query[ 'post_type' ] ) && 'docs' != $wp_query->query[ 'post_type' ] ) ) {
431 - $args[ 'number' ] = 4;
328 + if ( $wp_query->query === NULL || ( isset( $wp_query->query['post_type'] ) && $wp_query->query['post_type'] != 'docs' ) ) {
329 + $args['number'] = 4;
432 330 }
433 331 }
434 332
435 333 // Includes
436 - if ( isset( $args[ 'include' ] ) ) {
437 - $_include = ! is_array( $args[ 'include' ] ) ? explode( ',', $args[ 'include' ] ) : $args[ 'include' ];
438 - $args[ 'include' ] = $_include;
439 - $args[ 'orderby' ] = 'include';
334 + if ( isset( $args['include'] ) ) {
335 + $_include = ! is_array( $args['include'] ) ? explode( ',', $args['include'] ) : $args['include'];
336 + $args['include'] = $_include;
337 + $args['orderby'] = 'include';
440 338
441 - unset( $args[ 'parent' ] );
339 + unset( $args['parent'] );
442 340 }
443 341
444 - $_meta_query = ! empty( $args[ 'meta_query' ] ) ? $args[ 'meta_query' ] : array();
445 - $args[ 'meta_query' ] = apply_filters( 'betterdocs_taxonomy_object_meta_query', $_meta_query, $args );
342 + $_meta_query = ! empty( $args['meta_query'] ) ? $args['meta_query'] : [];
343 + $args['meta_query'] = apply_filters( 'betterdocs_taxonomy_object_meta_query', $_meta_query, $args );
446 344
447 345 return apply_filters( 'betterdocs_category_terms_object', wp_parse_args( $args, $_default_args ), $args );
448 346 }
449 347
450 348 public function get_terms( $args ) {
451 - $parsed_args = $this->parse_terms_args( $args );
452 - $terms = get_terms( $parsed_args );
453 -
454 - // Filter terms manually if we need to consider private docs for users with read_private_docs capability
455 - if ( isset( $parsed_args[ '_betterdocs_filter_private' ] ) && $parsed_args[ '_betterdocs_filter_private' ] && current_user_can( 'read_private_docs' ) ) {
456 - $terms = array_filter( $terms, function ( $term ) {
457 - // Get the actual count including private docs for users with read_private_docs capability
458 - $actual_count = $this->get_docs_count( $term, false );
459 - return $actual_count > 0;
460 - } );
461 - }
462 -
463 - return $terms;
349 + return get_terms( $this->parse_terms_args( $args ) );
464 350 }
465 351
466 352 public function get_child_terms( $args ) {
467 - if ( ! isset( $args[ 'number' ] ) ) {
353 + if ( ! isset( $args['number'] ) ) {
468 354 global $wp_query;
469 - if ( null === $wp_query->query || ( isset( $wp_query->query[ 'post_type' ] ) && 'docs' != $wp_query->query[ 'post_type' ] ) ) {
470 - $args[ 'number' ] = 1;
355 + if ( $wp_query->query === NULL || ( isset( $wp_query->query['post_type'] ) && $wp_query->query['post_type'] != 'docs' ) ) {
356 + $args['number'] = 1;
471 357 }
472 358 }
473 359
474 360 return $this->get_terms( $args );
@@ -491,9 +377,9 @@
491 377 public function get_taxonomy( $tax = '' ) {
492 378 global $wp_query;
493 379 if ( is_tax( 'knowledge_base' ) ) {
494 380 $_tax = $wp_query->tax_query->queried_terms;
495 - if ( array_key_exists( 'doc_category', $_tax ) ) {
381 + if ( array_key_exists( "doc_category", $_tax ) ) {
496 382 $tax = 'doc_category';
497 383 } else {
498 384 $tax = 'knowledge_base';
499 385 }
@@ -503,17 +389,17 @@
503 389
504 390 return $tax;
505 391 }
506 392
507 - public function terms_query( $args = array() ) {
393 + public function terms_query( $args = [] ) {
508 394 global $wp_query;
509 395 $_origin_args = $args;
510 396
511 - $default_args = array(
397 + $default_args = [
512 398 'hide_empty' => true,
513 - 'taxonomy' => 'doc_category',
514 - 'orderby' => 'name'
515 - );
399 + 'taxonomy' => 'doc_category',
400 + 'orderby' => 'name'
401 + ];
516 402
517 403 /**
518 404 * Number Set
519 405 *
@@ -525,11 +411,11 @@
525 411
526 412 /**
527 413 * Nested Sub Category
528 414 */
529 - if ( isset( $args[ 'nested_subcategory' ] ) && true == $args[ 'nested_subcategory' ] ) {
530 - $default_args[ 'parent' ] = 0;
531 - unset( $args[ 'nested_subcategory' ] );
415 + if ( isset( $args['nested_subcategory'] ) && $args['nested_subcategory'] == true ) {
416 + $default_args['parent'] = 0;
417 + unset( $args['nested_subcategory'] );
532 418 // if ( $wp_query->query === NULL || ( isset( $wp_query->query['post_type'] ) && $wp_query->query['post_type'] != 'docs' ) ) {
533 419 // $default_args['number'] = 4;
534 420 // }
535 421 }
@@ -536,32 +422,27 @@
536 422
537 423 /**
538 424 * OrderBy and Order
539 425 */
540 - if ( ! isset( $args[ 'orderby' ] ) ) {
426 + if ( ! isset( $args['orderby'] ) ) {
541 427 $_orderby = $this->settings->get( 'terms_orderby', 'name' );
542 428 $_order = $this->settings->get( 'terms_order', '' );
543 429 } else {
544 - $_orderby = $args[ 'orderby' ];
545 - $_order = ! empty( $args[ 'order' ] ) ? $args[ 'order' ] : '';
430 + $_orderby = $args['orderby'];
431 + $_order = ! empty( $args['order'] ) ? $args['order'] : '';
546 432 }
547 433
548 434 if ( 'betterdocs_order' === $_orderby ) {
549 - // Use different meta keys for different taxonomies
550 - if ( isset( $args[ 'taxonomy' ] ) && 'knowledge_base' === $args[ 'taxonomy' ] ) {
551 - $default_args[ 'meta_key' ] = 'kb_order';
552 - } else {
553 - $default_args[ 'meta_key' ] = 'doc_category_order';
554 - }
555 - $_orderby = 'meta_value_num';
556 - $_order = 'ASC';
557 - } elseif ( true === $_orderby ) {
435 + $default_args['meta_key'] = 'doc_category_order';
436 + $_orderby = 'meta_value_num';
437 + $_order = 'ASC';
438 + } elseif ( $_orderby === true ) {
558 439 $_orderby = 'name';
559 440 }
560 441
561 - $args[ 'orderby' ] = $_orderby;
562 - if ( ! empty( $_order ) ) {
563 - $args[ 'order' ] = $_order;
442 + $args['orderby'] = $_orderby;
443 + if( ! empty( $_order ) ) {
444 + $args['order'] = $_order;
564 445 }
565 446
566 447 /**
567 448 * @todo old hook
@@ -568,192 +449,84 @@
568 449 * hook: betterdocs_child_taxonomy_meta_query
569 450 */
570 451 $_multiple_kb = apply_filters(
571 452 'betterdocs_query_args_multiple_kb_enabled',
572 - isset( $args[ 'multiple_kb' ] ) ? (bool) $args[ 'multiple_kb' ] : false,
453 + isset( $args['multiple_kb'] ) ? (bool) $args['multiple_kb'] : false,
573 454 $_origin_args
574 455 );
575 456
576 - $_kb_slug = isset( $args[ 'kb_slug' ] ) ? trim( $args[ 'kb_slug' ] ) : '';
457 + $_kb_slug = isset( $args['kb_slug'] ) ? trim( $args['kb_slug'] ) : '';
577 458
578 - unset( $args[ 'multiple_kb' ] );
579 - unset( $args[ 'kb_slug' ] );
459 + unset( $args['multiple_kb'] );
460 + unset( $args['kb_slug'] );
580 461
581 - $meta_query = ! empty( $args[ 'meta_query' ] ) ? $args[ 'meta_query' ] : array();
462 + $meta_query = ! empty( $args['meta_query'] ) ? $args['meta_query'] : [];
582 463 $meta_query = apply_filters( 'betterdocs_terms_meta_query_args', $meta_query, $_multiple_kb, $_kb_slug, $_origin_args );
583 464
584 465 if ( ! empty( $meta_query ) ) {
585 - $default_args[ 'meta_query' ] = $meta_query;
466 + $default_args['meta_query'] = $meta_query;
586 467 }
587 468
588 - if ( ! empty( $args[ 'terms' ] ) ) {
589 - $args[ 'include' ] = explode( ',', $args[ 'terms' ] );
590 - $args[ 'orderby' ] = 'include';
591 - $args[ 'order' ] = 'ASC';
469 + if ( ! empty( $args['terms'] ) ) {
470 + $args['include'] = explode( ',', $args['terms'] );
471 + $args['orderby'] = 'include';
472 + $args['order'] = 'ASC';
592 473
593 - unset( $default_args[ 'parent' ] );
594 - unset( $args[ 'parent' ] );
595 - unset( $args[ 'terms' ] );
474 + unset( $default_args['parent'] );
475 + unset( $args['parent'] );
476 + unset( $args['terms'] );
596 477 }
597 478
598 479 $_query_args = wp_parse_args( $args, $default_args );
599 - $_query_args = apply_filters( 'betterdocs_terms_query_args', $_query_args, $_origin_args );
600 -
601 - // Apply private docs logic for logged-in users
602 - $_query_args = $this->modify_terms_args_for_private_docs( $_query_args );
603 -
604 - return $_query_args;
480 + return apply_filters( 'betterdocs_terms_query_args', $_query_args, $_origin_args );
605 481 }
606 482
607 - public function get_term_parents( $term_id, $taxonomy = 'doc_category', $args = array() ) {
483 + public function get_term_parents( $term_id, $taxonomy = 'doc_category', $args = [] ) {
608 484 $term = get_term( $term_id, $taxonomy );
609 485 if ( is_wp_error( $term ) ) {
610 486 return $term;
611 487 }
612 488
613 - if ( ! $term || ! isset( $term->term_id ) ) {
614 - return array();
489 + if ( ! $term ) {
490 + return [];
615 491 }
616 492
617 - $_lists = array();
493 + $_lists = [];
618 494 $origin_term = $term_id;
619 495 $term_id = $term->term_id;
620 496
621 - $defaults = array(
622 - 'format' => 'name',
497 + $defaults = [
498 + 'format' => 'name',
623 499 'inclusive' => true
624 - );
500 + ];
625 501
626 502 $args = wp_parse_args( $args, $defaults );
627 503
628 - $args[ 'inclusive' ] = wp_validate_boolean( $args[ 'inclusive' ] );
504 + $args['inclusive'] = wp_validate_boolean( $args['inclusive'] );
629 505
630 506 $parents = get_ancestors( $term_id, $taxonomy );
631 507
632 - if ( $args[ 'inclusive' ] ) {
508 + if ( $args['inclusive'] ) {
633 509 array_unshift( $parents, $term_id );
634 510 }
635 511
636 512 foreach ( array_reverse( $parents ) as $term_id ) {
637 513 $parent = get_term( $term_id, $taxonomy );
638 - $name = ( 'slug' === $args[ 'format' ] ) ? $parent->slug : $parent->name;
514 + $name = ( 'slug' === $args['format'] ) ? $parent->slug : $parent->name;
639 515 $term_permalink = get_term_link( $parent->term_id, $taxonomy );
640 516 $term_permalink = apply_filters( 'betterdocs_breadcrumb_term_permalink', $term_permalink, $term_id );
641 517
642 - $_item = array(
643 - 'url' => $term_permalink,
518 + $_item = [
519 + 'url' => $term_permalink,
644 520 'text' => $name
645 - );
521 + ];
646 522
647 - $_lists[ ] = $_item;
523 + $_lists[] = $_item;
648 524 }
649 525
650 526 return apply_filters( 'betterdocs_breadcrumb_archive_lists', $_lists, $origin_term );
651 527 }
652 528
653 - /**
654 - * Get all non-empty child term IDs recursively for a given taxonomy and parent term.
655 - *
656 - * This function retrieves all child terms for a specified taxonomy and parent term,
657 - * recursively fetching child terms of child terms, and returns only those with a non-zero post count.
658 - *
659 - * @param string $taxonomy The taxonomy name (e.g., 'doc_category').
660 - * @param int $parent_id The ID of the parent term to start retrieving children from.
661 - *
662 - * @return array An array of non-empty child term IDs.
663 - */
664 - public function get_all_child_term_ids( $taxonomy, $parent_id ) {
665 - // Set up the arguments for retrieving child terms
666 - $args = apply_filters(
667 - 'betterdocs_get_child_term_ids_args',
668 - array(
669 - 'taxonomy' => $taxonomy,
670 - 'parent' => $parent_id,
671 - 'hide_empty' => true,
672 - 'fields' => 'ids'
673 - )
674 - );
675 -
676 - // Get the terms based on the arguments
677 - $terms = get_terms( $args );
678 -
679 - // Initialize an empty array to hold non-empty child term IDs
680 - $non_empty_children = array();
681 -
682 - // Check if terms were retrieved without errors and that the result isn't empty
683 - if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
684 - $term_ids = array();
685 -
686 - // Loop through each term ID
687 - foreach ( $terms as $term_id ) {
688 - // Add the current term ID to the term_ids array
689 - $term_ids[ ] = $term_id;
690 -
691 - // Recursively get child terms for the current term
692 - $child_term_ids = $this->get_all_child_term_ids( $taxonomy, $term_id );
693 -
694 - // If there are child terms, merge them into the term_ids array
695 - if ( ! empty( $child_term_ids ) ) {
696 - $term_ids = array_merge( $term_ids, $child_term_ids );
697 - }
698 - }
699 -
700 - // Loop through all retrieved term IDs to filter out empty ones
701 - foreach ( $term_ids as $term_id ) {
702 - // Get the term object for the current term ID
703 - $child_term = get_term( $term_id, $taxonomy );
704 -
705 - // Only include terms that have a non-zero post count
706 - if ( $child_term && isset( $child_term->term_id ) && $child_term->count > 0 ) {
707 - $non_empty_children[ ] = $child_term->term_id;
708 - }
709 - }
710 - }
711 -
712 - // Return the final array of non-empty child term IDs
713 - return $non_empty_children;
714 - }
715 -
716 - /**
717 - * Get all nested child term IDs of a specific parent term in a taxonomy and return as a comma-separated string.
718 - *
719 - * @param string $taxonomy The taxonomy.
720 - * @param int $parent_id The parent term ID.
721 - * @return string The comma-separated term IDs.
722 - */
723 - public function get_child_term_ids_by_parent_id( $taxonomy, $parent_id ) {
724 - $term_ids = $this->get_all_child_term_ids( $taxonomy, $parent_id );
725 - return implode( ',', $term_ids );
726 - }
727 -
728 - public function get_terms_children( $taxonomy, $parent_id ) {
729 - $children = get_term_children( $parent_id, $taxonomy );
730 - $non_empty_children = array();
731 - if ( ! is_wp_error( $children ) && ! empty( $children ) ) {
732 - foreach ( $children as $child_id ) {
733 - $child_term = get_term( $child_id, $taxonomy );
734 -
735 - // Only include non-empty terms
736 - if ( $child_term && $child_term->count > 0 ) {
737 - $non_empty_children[ ] = $child_term;
738 - }
739 - }
740 - }
741 -
742 - return $non_empty_children;
743 - }
744 -
745 - public function get_terms_children_ids( $taxonomy, $parent_id ) {
746 - $children = $this->get_terms_children( $taxonomy, $parent_id );
747 - $term_ids = wp_list_pluck( $children, 'term_id' );
748 -
749 - return implode( ',', $term_ids );
750 - }
751 -
752 - public function count_terms_children( $taxonomy, $parent_id ) {
753 - return count( $this->get_terms_children( $taxonomy, $parent_id ) );
754 - }
755 -
756 529 public function is_inner_templates() {
757 530 if ( is_tax( 'knowledge_base' ) || is_tax( 'doc_category' ) || is_tax( 'doc_tag' ) || is_singular( 'docs' ) ) {
758 531 return true;
759 532 }
@@ -765,47 +538,47 @@
765 538 * @param mixed $args
766 539 * @throws \Exception
767 540 * @return mixed
768 541 */
769 - public function docs_query_args( $args, $filter = array() ) {
542 + public function docs_query_args( $args, $filter = [] ) {
770 543 $_origin_args = $args;
771 544
772 - $default_args = array(
545 + $default_args = [
773 546 'post_type' => 'docs'
774 - );
547 + ];
775 548
776 - if ( ! empty( $args[ 'post_type' ] ) && trim( $args[ 'post_type' ] ) === 'docs_any' ) {
777 - $default_args[ 'post_type' ] = 'docs';
778 - $default_args[ 'post_status' ] = 'any';
549 + if ( ! empty( $args['post_type'] ) && trim( $args['post_type'] ) === 'docs_any' ) {
550 + $default_args['post_type'] = 'docs';
551 + $default_args['post_status'] = 'any';
779 552
780 - unset( $args[ 'post_type' ] );
553 + unset( $args['post_type'] );
781 554 }
782 555
783 556 /**
784 557 * OrderBy and Order
785 558 */
786 - if ( ! isset( $args[ 'orderby' ] ) ) {
559 + if ( ! isset( $args['orderby'] ) ) {
787 560 $_orderby = $this->settings->get( 'alphabetically_order_post' );
788 561 $_order = $this->settings->get( 'docs_order', 'ASC' );
789 562 } else {
790 - $_orderby = $args[ 'orderby' ];
791 - $_order = ! empty( $args[ 'order' ] ) ? $args[ 'order' ] : 'ASC';
563 + $_orderby = $args['orderby'];
564 + $_order = ! empty( $args['order'] ) ? $args['order'] : 'ASC';
792 565 }
793 566
794 567 if ( 'betterdocs_order' != $_orderby ) {
795 - if ( true === $_orderby ) {
796 - $args[ 'orderby' ] = 'title';
568 + if ( $_orderby === true ) {
569 + $args['orderby'] = 'title';
797 570 } else {
798 - $args[ 'orderby' ] = $_orderby;
571 + $args['orderby'] = $_orderby;
799 572 }
800 573
801 - $args[ 'order' ] = $_order;
574 + $args['order'] = $_order;
802 575 } elseif ( 'betterdocs_order' == $_orderby ) {
803 - unset( $args[ 'orderby' ] );
576 + unset( $args['orderby'] );
804 577 }
805 578
806 - if ( empty( $args[ 'orderby' ] ) ) {
807 - unset( $args[ 'order' ] );
579 + if ( empty( $args['orderby'] ) ) {
580 + unset( $args['order'] );
808 581 }
809 582
810 583 /**
811 584 * Term ID
@@ -810,11 +583,11 @@
810 583 /**
811 584 * Term ID
812 585 */
813 586 $_term_id = null;
814 - if ( ! empty( $args[ 'term_id' ] ) ) {
815 - $_term_id = intval( $args[ 'term_id' ] );
816 - unset( $args[ 'term_id' ] );
587 + if ( ! empty( $args['term_id'] ) ) {
588 + $_term_id = intval( $args['term_id'] );
589 + unset( $args['term_id'] );
817 590 }
818 591
819 592 // if ( $_term_id == null ) {
820 593 // throw new \Exception( __( '$args["term_id"] cannot be null.', 'betterdocs' ) );
@@ -823,11 +596,11 @@
823 596 /**
824 597 * Term Slug for tax_query
825 598 */
826 599 $_term_slug = '';
827 - if ( ! empty( $args[ 'term_slug' ] ) ) {
828 - $_term_slug = trim( $args[ 'term_slug' ] );
829 - unset( $args[ 'term_slug' ] );
600 + if ( ! empty( $args['term_slug'] ) ) {
601 + $_term_slug = trim( $args['term_slug'] );
602 + unset( $args['term_slug'] );
830 603 }
831 604
832 605 /**
833 606 * @todo old hook
@@ -835,44 +608,36 @@
835 608 */
836 609
837 610 $_multiple_kb = apply_filters(
838 611 'betterdocs_enable_multiple_knowledge_base',
839 - isset( $args[ 'multiple_kb' ] ) ? (bool) $args[ 'multiple_kb' ] : false,
612 + isset( $args['multiple_kb'] ) ? (bool) $args['multiple_kb'] : false,
840 613 $_origin_args
841 614 );
842 615
843 - $_kb_slug = isset( $args[ 'kb_slug' ] ) ? trim( $args[ 'kb_slug' ] ) : '';
616 + $_kb_slug = isset( $args['kb_slug'] ) ? trim( $args['kb_slug'] ) : '';
844 617
845 - unset( $args[ 'multiple_kb' ] );
846 - unset( $args[ 'kb_slug' ] );
618 + unset( $args['multiple_kb'] );
619 + unset( $args['kb_slug'] );
847 620
848 - $tax_query = array(
849 - array(
850 - 'taxonomy' => 'doc_category',
851 - 'field' => 'slug',
852 - 'terms' => $_term_slug,
853 - 'operator' => 'AND',
621 + $tax_query = [
622 + [
623 + 'taxonomy' => 'doc_category',
624 + 'field' => 'slug',
625 + 'terms' => $_term_slug,
626 + 'operator' => 'AND',
854 627 'include_children' => false
855 - )
856 - );
628 + ]
629 + ];
857 630
858 - if ( ! isset( $args[ 'orderby' ] ) || 'betterdocs_order' == $args[ 'orderby' ] ) {
859 - $args[ 'orderby' ] = 'post__in';
860 - $args[ 'post__in' ] = $this->get_docs_order_by_terms( $_term_id );
631 + if ( isset( $args['tax_query'] ) ) {
632 + $tax_query = $args['tax_query'];
861 633 }
862 634
863 - if ( isset( $args[ 'tax_query' ] ) ) {
864 - $tax_query = $args[ 'tax_query' ];
865 - }
866 635
867 - $args[ 'tax_query' ] = apply_filters(
636 +
637 + $args['tax_query'] = apply_filters(
868 638 'betterdocs_docs_tax_query_args',
869 - $tax_query,
870 - $_multiple_kb,
871 - $_term_slug,
872 - $_kb_slug,
873 - $_origin_args,
874 - $this->is_inner_templates()
639 + $tax_query, $_multiple_kb, $_term_slug, $_kb_slug, $_origin_args, $this->is_inner_templates()
875 640 );
876 641 /**
877 642 * Final parse args
878 643 */
@@ -879,63 +644,44 @@
879 644 $args = wp_parse_args( $args, $default_args );
880 645
881 646 if ( ! empty( $filter ) ) {
882 647 $filter = array_flip( $filter );
883 - $args = array_filter(
884 - $args,
885 - function ( $item ) use ( $filter ) {
886 - return ! array_key_exists( $item, $filter );
887 - },
888 - ARRAY_FILTER_USE_KEY
889 - );
648 + $args = array_filter( $args, function ( $item ) use ( $filter ) {
649 + return ! array_key_exists( $item, $filter );
650 + }, ARRAY_FILTER_USE_KEY );
890 651 }
891 652
892 - $final_args = apply_filters( 'betterdocs_articles_args', $args, $_term_id, $_origin_args );
893 -
894 - // Process betterdocs_order AFTER all filters have run
895 - if ( isset( $final_args[ 'orderby' ] ) && 'betterdocs_order' == $final_args[ 'orderby' ] ) {
896 - $docs_order = $this->get_docs_order_by_terms( $_term_id );
897 -
898 - if ( ! empty( $docs_order ) ) {
899 - $final_args[ 'orderby' ] = 'post__in';
900 - $final_args[ 'post__in' ] = $docs_order;
901 - } else {
902 - $final_args[ 'orderby' ] = 'menu_order';
903 - $final_args[ 'order' ] = 'ASC';
904 - }
905 - }
906 -
907 - return $final_args;
653 + return apply_filters( 'betterdocs_articles_args', $args, $_term_id, $_origin_args );
908 654 }
909 655
910 - public function faq_terms_query_args( $includes = '', $excludes = '', $args = array() ) {
911 - $_args = array(
912 - 'taxonomy' => 'betterdocs_faq_category',
913 - 'meta_key' => 'order',
914 - 'orderby' => 'meta_value_num',
915 - 'order' => 'ASC',
916 - 'include' => $includes,
917 - 'exclude' => $excludes,
918 - 'meta_query' => array(
919 - array(
920 - 'key' => 'status',
921 - 'value' => 1,
656 + public function faq_terms_query_args( $includes = '', $excludes = '', $args = [] ) {
657 + $_args = [
658 + 'taxonomy' => 'betterdocs_faq_category',
659 + 'meta_key' => 'order',
660 + 'orderby' => 'meta_value_num',
661 + 'order' => 'ASC',
662 + 'include' => $includes,
663 + 'exclude' => $excludes,
664 + 'meta_query' => [
665 + [
666 + 'key' => 'status',
667 + 'value' => 1,
922 668 'compare' => '=='
923 - )
924 - )
925 - );
669 + ]
670 + ]
671 + ];
926 672
927 - if ( 'all' == $_args[ 'include' ] ) {
928 - unset( $_args[ 'include' ] );
929 - unset( $_args[ 'exclude' ] );
673 + if ( $_args['include'] == 'all' ) {
674 + unset( $_args['include'] );
675 + unset( $_args['exclude'] );
930 676 }
931 677
932 - if ( empty( $_args[ 'exclude' ] ) ) {
933 - unset( $_args[ 'exclude' ] );
678 + if ( empty( $_args['exclude'] ) ) {
679 + unset( $_args['exclude'] );
934 680 }
935 681
936 - if ( empty( $_args[ 'include' ] ) ) {
937 - unset( $_args[ 'include' ] );
682 + if ( empty( $_args['include'] ) ) {
683 + unset( $_args['include'] );
938 684 }
939 685
940 686 return wp_parse_args( $args, $_args );
941 687 }
@@ -942,24 +688,24 @@
942 688
943 689 public function get_faq_by_term( $term_id ) {
944 690 global $wpdb;
945 691
946 - $args = array(
947 - 'post_type' => 'betterdocs_faq',
948 - 'post_status' => 'publish',
949 - 'tax_query' => array(
950 - array(
692 + $args = [
693 + 'post_type' => 'betterdocs_faq',
694 + 'post_status' => 'publish',
695 + 'tax_query' => [
696 + [
951 697 'taxonomy' => 'betterdocs_faq_category',
952 - 'field' => 'term_id',
953 - 'terms' => $term_id,
698 + 'field' => 'term_id',
699 + 'terms' => $term_id,
954 700 'operator' => 'AND'
955 - )
956 - ),
701 + ]
702 + ],
957 703 'posts_per_page' => -1
958 - );
704 + ];
959 705
960 - $args[ 'orderby' ] = 'post__in';
961 - $args[ 'post__in' ] = $this->get_faq_orders( $term_id );
706 + $args['orderby'] = 'post__in';
707 + $args['post__in'] = $this->get_faq_orders( $term_id );
962 708
963 709 return new WP_Query( $args );
964 710 }
965 711
@@ -968,33 +714,27 @@
968 714 $faq_order = get_term_meta( $term_id, '_betterdocs_faq_order', true );
969 715 $faq_order = explode( ',', $faq_order );
970 716
971 717 $query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}term_relationships WHERE term_taxonomy_id = %d", $term_id );
972 - $query_key = 'betterdocs_faq_order_' . md5( $query );
718 + $query_key = "betterdocs_faq_order_" . md5( $query );
973 719
974 - if ( ( $results = $this->database->get_cache( $query_key ) ) !== false ) {
720 + if ( ( $results = $this->database->get_cache( $query_key ) ) !== false ) {
975 721 return $results;
976 722 }
977 723
978 724 if ( ! empty( $faq_order ) ) {
979 - $new_ids = array();
980 - $results = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
725 + $new_ids = [];
726 + $results = $wpdb->get_results( $query );
981 727
982 728 if ( ! is_null( $results ) && ! empty( $results ) && is_array( $results ) ) {
983 - $object_ids = array_filter(
984 - $results,
985 - function ( $value ) use ( $faq_order ) {
986 - return ! in_array( $value->object_id, $faq_order );
987 - }
988 - );
729 + $object_ids = array_filter( $results, function ( $value ) use ( $faq_order ) {
730 + return ! in_array( $value->object_id, $faq_order );
731 + } );
989 732
990 733 if ( ! empty( $object_ids ) ) {
991 - array_walk(
992 - $object_ids,
993 - function ( $value ) use ( &$new_ids ) {
994 - $new_ids[ ] = $value->object_id;
995 - }
996 - );
734 + array_walk( $object_ids, function ( $value ) use ( &$new_ids ) {
735 + $new_ids[] = $value->object_id;
736 + } );
997 737 }
998 738 }
999 739
1000 740 $faq_order = array_merge( $new_ids, $faq_order );
@@ -1004,28 +744,26 @@
1004 744
1005 745 return $faq_order;
1006 746 }
1007 747
1008 - public function get_faq_terms( $terms = array() ) {
1009 - $_terms = get_terms(
1010 - array(
1011 - 'taxonomy' => 'betterdocs_faq_category',
1012 - 'hide_empty' => true,
1013 - 'orderby' => 'name',
1014 - 'order' => 'ASC',
1015 - 'meta_query' => array(
1016 - array(
1017 - 'key' => 'status',
1018 - 'value' => 1,
1019 - 'compare' => '=='
1020 - )
1021 - )
1022 - )
1023 - );
748 + public function get_faq_terms( $terms = [] ) {
749 + $_terms = get_terms( [
750 + 'taxonomy' => 'betterdocs_faq_category',
751 + 'hide_empty' => true,
752 + 'orderby' => 'name',
753 + 'order' => 'ASC',
754 + 'meta_query' => [
755 + [
756 + 'key' => 'status',
757 + 'value' => 1,
758 + 'compare' => '=='
759 + ]
760 + ]
761 + ] );
1024 762
1025 763 if ( ! is_wp_error( $_terms ) ) {
1026 764 foreach ( $_terms as $term ) {
1027 - $terms[ $term->term_id ] = $term->name;
765 + $terms[$term->term_id] = $term->name;
1028 766 }
1029 767 }
1030 768
1031 769 return $terms;
@@ -1030,62 +768,12 @@
1030 768
1031 769 return $terms;
1032 770 }
1033 771
1034 - public function get_doc_terms( $terms = array() ) {
1035 - $_terms = get_terms(
1036 - array(
1037 - 'taxonomy' => 'doc_category',
1038 - 'hide_empty' => true,
1039 - 'orderby' => 'name',
1040 - 'order' => 'ASC'
1041 - )
1042 - );
1043 -
1044 - if ( ! is_wp_error( $_terms ) ) {
1045 - foreach ( $_terms as $term ) {
1046 - $terms[ $term->term_id ] = $term->name;
1047 - }
1048 - }
1049 -
1050 - return $terms;
1051 - }
1052 -
1053 - public function get_docs_count( $term, $nested_subcategory = false, $args = array() ) {
1054 - // Validate term object
1055 - if ( ! is_object( $term ) ) {
1056 - return 0;
1057 - }
1058 -
772 + public function get_docs_count( $term, $nested_subcategory = false, $args = [] ) {
1059 773 $counts = isset( $term->count ) ? $term->count : 0;
1060 774
1061 - if ( false == $nested_subcategory ) {
1062 - // For non-nested categories, we need to recalculate counts based on user capabilities
1063 - // Only proceed if we have a valid term with required properties
1064 - if ( isset( $term->term_id ) && isset( $term->taxonomy ) && is_numeric( $term->term_id ) ) {
1065 - // Get all post IDs for this term
1066 - $post_ids = get_objects_in_term( $term->term_id, $term->taxonomy );
1067 -
1068 - if ( ! empty( $post_ids ) ) {
1069 - if ( current_user_can( 'read_private_docs' ) ) {
1070 - // For users with read_private_docs capability, include both private and public posts
1071 - $filtered_post_ids = array_filter( $post_ids, function ( $post_id ) {
1072 - $post_status = get_post_status( $post_id );
1073 - return 'private' === $post_status || is_post_publicly_viewable( $post_id );
1074 - } );
1075 - } else {
1076 - // For users without read_private_docs capability, only include public posts
1077 - $filtered_post_ids = array_filter( $post_ids, function ( $post_id ) {
1078 - return is_post_publicly_viewable( $post_id );
1079 - } );
1080 - }
1081 -
1082 - $counts = count( $filtered_post_ids );
1083 - } else {
1084 - $counts = 0;
1085 - }
1086 - }
1087 -
775 + if ( $nested_subcategory == false ) {
1088 776 return apply_filters( 'betterdocs_docs_count', $counts, $term, $nested_subcategory, $args );
1089 777 }
1090 778
1091 779 $_child_terms_docs_ids = $this->get_doc_ids_by_term( $term, null, $nested_subcategory );
@@ -1096,18 +784,13 @@
1096 784 return apply_filters( 'betterdocs_docs_count', $counts, $term, $nested_subcategory, $args );
1097 785 }
1098 786
1099 787 public function get_doc_ids_by_term( $term, $optional = null, $nested_subcategory = false ) {
1100 - // Check if term has required properties and is a valid object
1101 - if ( ! is_object( $term ) || ! isset( $term->term_id ) || ! isset( $term->taxonomy ) || ! is_numeric( $term->term_id ) ) {
1102 - return false;
788 + $args = [ 'include' => $term->term_id ];
789 + if( $nested_subcategory ) {
790 + $args['child_of'] = $term->term_id;
791 + unset( $args['include'] );
1103 792 }
1104 -
1105 - $args = array( 'include' => $term->term_id );
1106 - if ( $nested_subcategory ) {
1107 - $args[ 'child_of' ] = $term->term_id;
1108 - unset( $args[ 'include' ] );
1109 - }
1110 793 $_child_terms = get_terms( $term->taxonomy, $args );
1111 794
1112 795 if ( ! is_array( $_child_terms ) ) {
1113 796 return false;
@@ -1118,255 +801,19 @@
1118 801 $_child_terms_ids = array_column( $_child_terms, 'term_id' );
1119 802 $_child_terms_taxs = array_column( $_child_terms, 'taxonomy' );
1120 803 $_child_terms_docs_ids = get_objects_in_term( $_child_terms_ids, $_child_terms_taxs );
1121 804
1122 - if ( null !== $optional ) {
805 + if ( $optional !== null ) {
1123 806 $_optional_doc_ids = get_objects_in_term( $optional->term_id, $optional->taxonomy );
1124 807 $_child_terms_docs_ids = array_intersect( $_child_terms_docs_ids, $_optional_doc_ids );
1125 808 }
1126 809
1127 810 return array_filter( $_child_terms_docs_ids, function ( $doc_id ) {
1128 - if ( ! current_user_can( 'read_private_docs' ) ) {
811 + if ( ! is_user_logged_in() ) {
1129 812 return is_post_publicly_viewable( $doc_id );
1130 813 }
1131 814
1132 815 $_status = get_post_status( $doc_id );
1133 - return 'private' == $_status || is_post_publicly_viewable( $doc_id );
816 + return $_status == 'private' || is_post_publicly_viewable( $doc_id );
1134 817 } );
1135 - }
1136 -
1137 - /**
1138 - * Get the common query arguments for WP_Query.
1139 - *
1140 - * @param string $terms The taxonomy.
1141 - * @param string $term_slug The taxonomy term slug.
1142 - * @param array $additional_args Additional arguments to merge with the common arguments.
1143 - * @return array The query arguments.
1144 - */
1145 - private function tax_query_args( $terms, $term_slug, $additional_args = array() ) {
1146 - $common_args = array(
1147 - 'post_type' => 'docs',
1148 - 'post_status' => 'publish',
1149 - 'tax_query' => array(
1150 - array(
1151 - 'taxonomy' => $terms,
1152 - 'field' => 'slug',
1153 - 'terms' => $term_slug
1154 - )
1155 - )
1156 - );
1157 - return array_merge( $common_args, $additional_args );
1158 - }
1159 -
1160 - /**
1161 - * Get the latest updated date for a specific taxonomy term.
1162 - *
1163 - * @param string $terms The taxonomy.
1164 - * @param string $term_slug The taxonomy term slug.
1165 - * @return string|null The latest modified date or null if no posts found.
1166 - */
1167 - public function latest_updated_date( $terms, $term_slug ) {
1168 - $args = $this->tax_query_args(
1169 - $terms,
1170 - $term_slug,
1171 - array(
1172 - 'posts_per_page' => 1,
1173 - 'orderby' => 'modified',
1174 - 'order' => 'DESC'
1175 - )
1176 - );
1177 -
1178 - $query = new WP_Query( $args );
1179 -
1180 - if ( $query->have_posts() ) {
1181 - while ( $query->have_posts() ) {
1182 - $query->the_post();
1183 - $latest_post = get_the_modified_date();
1184 - wp_reset_postdata();
1185 - return $latest_post;
1186 - }
1187 - } else {
1188 - return null;
1189 - }
1190 - }
1191 -
1192 - /**
1193 - * Check if there are any new posts within the last 7 days for a specific taxonomy term.
1194 - *
1195 - * @param string $terms The taxonomy.
1196 - * @param string $term_slug The taxonomy term slug.
1197 - * @return bool True if there are new posts, false otherwise.
1198 - */
1199 - public function check_new_posts( $terms, $term_slug ) {
1200 - $date_7_days_ago = date( 'Y-m-d H:i:s', strtotime( '-7 days' ) );
1201 -
1202 - $args = $this->tax_query_args(
1203 - $terms,
1204 - $term_slug,
1205 - array(
1206 - 'posts_per_page' => 1,
1207 - 'orderby' => 'modified',
1208 - 'order' => 'DESC',
1209 - 'date_query' => array(
1210 - array(
1211 - 'after' => $date_7_days_ago,
1212 - 'inclusive' => true
1213 - )
1214 - )
1215 - )
1216 - );
1217 -
1218 - $query = new WP_Query( $args );
1219 -
1220 - $has_new_posts = $query->have_posts();
1221 -
1222 - wp_reset_postdata();
1223 -
1224 - return $has_new_posts;
1225 - }
1226 -
1227 - public function insert_search_keyword( $search_input, $input_not_found ) {
1228 - if ( empty( $search_input ) ) {
1229 - return false;
1230 - }
1231 -
1232 - global $wpdb;
1233 -
1234 - // Use BINARY comparison to avoid collation mismatch errors
1235 - // This works across all character sets (latin1, utf8, utf8mb4, etc.)
1236 - $search = $wpdb->get_results(
1237 - $wpdb->prepare(
1238 - "SELECT *
1239 - FROM {$wpdb->prefix}betterdocs_search_keyword
1240 - WHERE BINARY keyword = %s",
1241 - $search_input
1242 - )
1243 - );
1244 -
1245 - if ( ! empty( $search ) ) {
1246 - $search_log = $wpdb->get_results(
1247 - $wpdb->prepare(
1248 - "SELECT *
1249 - FROM {$wpdb->prefix}betterdocs_search_log
1250 - WHERE created_at = %s AND keyword_id = %d",
1251 - date( 'Y-m-d' ),
1252 - $search[ 0 ]->id
1253 - )
1254 - );
1255 -
1256 - if ( ! empty( $search_log ) ) {
1257 - if ( ! empty( $input_not_found ) ) {
1258 - $tbl_field = 'not_found_count';
1259 - $count = $search_log[ 0 ]->not_found_count + 1;
1260 - } else {
1261 - $tbl_field = 'count';
1262 - $count = $search_log[ 0 ]->count + 1;
1263 - }
1264 - // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
1265 - $insert = $wpdb->query(
1266 - $wpdb->prepare(
1267 - "UPDATE {$wpdb->prefix}betterdocs_search_log
1268 - SET " . $tbl_field . ' = ' . $count . '
1269 - WHERE created_at = %s AND keyword_id = %d',
1270 - $search_log[ 0 ]->created_at,
1271 - $search_log[ 0 ]->keyword_id
1272 - )
1273 - );
1274 - } else {
1275 - if ( ! empty( $input_not_found ) ) {
1276 - $count = 0;
1277 - $not_found_count = 1;
1278 - } else {
1279 - $count = 1;
1280 - $not_found_count = 0;
1281 - }
1282 - $insert = $wpdb->query(
1283 - $wpdb->prepare(
1284 - "INSERT INTO {$wpdb->prefix}betterdocs_search_log
1285 - ( keyword_id, count, not_found_count, created_at )
1286 - VALUES ( %d, %d, %d, %s )",
1287 - array(
1288 - $search[ 0 ]->id,
1289 - $count,
1290 - $not_found_count,
1291 - date( 'Y-m-d' )
1292 - )
1293 - )
1294 - );
1295 - }
1296 - } else {
1297 - $insert = $wpdb->query(
1298 - $wpdb->prepare(
1299 - "INSERT INTO {$wpdb->prefix}betterdocs_search_keyword
1300 - ( keyword )
1301 - VALUES ( %s )",
1302 - array(
1303 - $search_input
1304 - )
1305 - )
1306 - );
1307 -
1308 - if ( $insert ) {
1309 - if ( ! empty( $input_not_found ) ) {
1310 - $count = 0;
1311 - $not_found_count = 1;
1312 - } else {
1313 - $count = 1;
1314 - $not_found_count = 0;
1315 - }
1316 - $insert = $wpdb->query(
1317 - $wpdb->prepare(
1318 - "INSERT INTO {$wpdb->prefix}betterdocs_search_log
1319 - ( keyword_id, count, not_found_count, created_at )
1320 - VALUES ( %d, %d, %d, %s )",
1321 - array(
1322 - $wpdb->insert_id,
1323 - $count,
1324 - $not_found_count,
1325 - date( 'Y-m-d' )
1326 - )
1327 - )
1328 - );
1329 - }
1330 - }
1331 - return $insert;
1332 - }
1333 -
1334 - /**
1335 - * Counts the number of 'doc_category' terms assigned to a specific 'knowledge_base' by slug.
1336 - *
1337 - * This method retrieves all terms in the 'doc_category' taxonomy and checks the term meta
1338 - * 'doc_category_knowledge_base' to determine how many 'doc_category' terms are associated
1339 - * with a given 'knowledge_base' slug.
1340 - *
1341 - * @param string $knowledge_base_slug The slug of the 'knowledge_base' to count the assignments for.
1342 - *
1343 - * @return int The count of 'doc_category' terms assigned to the specified 'knowledge_base'.
1344 - */
1345 - public function count_doc_categories_for_knowledge_base( $knowledge_base_slug ) {
1346 - $count = 0;
1347 -
1348 - $doc_categories = get_terms(
1349 - array(
1350 - 'taxonomy' => 'doc_category',
1351 - 'hide_empty' => true
1352 - )
1353 - );
1354 -
1355 - if ( ! empty( $doc_categories ) && ! is_wp_error( $doc_categories ) ) {
1356 - foreach ( $doc_categories as $term ) {
1357 - $meta_value = get_term_meta( $term->term_id, 'doc_category_knowledge_base', true );
1358 -
1359 - if ( $meta_value ) {
1360 - $knowledge_bases = maybe_unserialize( $meta_value );
1361 -
1362 - // Check if the specific knowledge base slug is present in the meta value array
1363 - if ( is_array( $knowledge_bases ) && in_array( $knowledge_base_slug, $knowledge_bases ) ) {
1364 - ++$count;
1365 - }
1366 - }
1367 - }
1368 - }
1369 -
1370 - return $count;
1371 818 }
1372 819 }