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