PluginProbe
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot / 3.8.9
BetterDocs – AI Documentation, Knowledge Base, MCP Server, Docs, Wikis, FAQ & Chatbot v3.8.9
4.9.1 4.9.0 4.8.2 4.8.1 4.8.0 4.7.0 4.6.2 4.6.1 4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 4.5.1 4.5.0 4.4.1 4.4.0 3.3.4 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.5.2 All 199 releases
betterdocs / includes / REST / Docs.php

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

399 lines 11.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDeveloper\BetterDocs\REST;
4
5 use Error;
6 use WP_Query;
7 use WP_REST_Response;
8 use WPDeveloper\BetterDocs\Core\BaseAPI;
9
10 class Docs extends BaseAPI {
11 public function permission_check(): bool {
12 return true;
13 }
14
15 public function register() {
16 $this->get( 'search', [$this, 'search_posts'] );
17 $this->get( 'search-insert', [$this, 'search_insert'] );
18 $this->get( 'get-terms', [$this, 'get_terms_name_and_slug'] );
19 $this->get( 'months-with-posts', [$this, 'get_months_with_posts'] );
20 $this->get( 'order_docs', [$this, 'render_betterdocs_order_docs'] );
21 $this->register_field( 'docs', 'year_month', [
22 'get_callback' => [$this, 'year_month']
23 ] );
24
25 $this->register_field(
26 'docs',
27 'password',
28 [
29 'get_callback' => [ $this, 'get_post_password' ]
30 ]
31 );
32
33 add_filter( 'rest_docs_query', [ $this, 'filter_docs_query' ], 10, 2 );
34 }
35
36 public function render_betterdocs_order_docs($request) {
37 $doc_category = $request->get_param('doc_category');
38 $order = $request->get_param('order');
39 $orderby = $request->get_param('orderby');
40 $per_page = $request->get_param('per_page');
41
42 if( empty( $doc_category) ) {
43 return [];
44 }
45
46 $args = [
47 'term_id' => $doc_category,
48 'orderby' => $orderby,
49 'order' => $order,
50 'posts_per_page' => $per_page
51 ];
52
53 $args = betterdocs()->query->docs_query_args($args);
54 $posts = betterdocs()->query->get_posts( $args, true );
55
56 if ( ! $posts->have_posts() ) {
57 wp_reset_query();
58 }
59
60 $post_datas = [];
61
62 while ( $posts->have_posts() ):
63 $posts->the_post();
64 $post_data = $this->get_doc_data( get_the_ID() );
65 array_push( $post_datas, $post_data );
66 endwhile;
67
68 wp_reset_postdata();
69 wp_reset_query();
70
71 return $post_datas;
72 }
73
74 /**
75 * Get Doc Data Based On Doc ID
76 *
77 * @return array
78 */
79 public function get_doc_data( $id ) {
80 $post_data = get_post( $id );
81 $data = [
82 'author' => (int) $post_data->post_author,
83 'author_info' => [
84 'name' => get_the_author_meta( 'display_name', $post_data->post_author ),
85 'author_nicename' => get_the_author_meta( 'nicename', $post_data->post_author ),
86 'author_url' => get_author_posts_url( $post_data->post_author )
87 ],
88 'unique_id' => uniqid( 'doc' ),
89 'id' => $post_data->ID,
90 'title' => [
91 'rendered' => $post_data->post_title
92 ],
93 'slug' => get_post_field( 'post_name', $id ),
94 'link' => get_permalink( $id ),
95 'status' => get_post_status(),
96 'date' => $post_data->post_date,
97 'date_gmt' => $post_data->post_date_gmt,
98 'doc_category' => wp_get_post_terms( $id, 'doc_category', ["fields" => "ids"] ),
99 'doc_tag' => wp_get_post_terms( $id, 'doc_tag', ["fields" => "ids"] ),
100 'password' => $post_data->post_password,
101 'comment_status' => $post_data->comment_status
102 ];
103
104 if ( taxonomy_exists( 'knowledge_base' ) ) {
105 $data['knowledge_base'] = wp_get_post_terms( $id, 'knowledge_base', ["fields" => "ids"] );
106 }
107
108 return $data;
109 }
110
111 /**
112 * Retrieves the months and years that have posts of the type 'docs' and formats them.
113 *
114 * This function queries the WordPress database for all unique months and years
115 * in which 'docs' post type posts have been published. The results are then
116 * formatted into an array of associative arrays, where each entry contains an
117 * 'id' and a 'name'.
118 *
119 * The 'id' is a string formatted as 'month-year' (e.g., 'may-2024') to provide
120 * a unique identifier that is easy to work with in JavaScript and HTML. The 'name'
121 * is a more human-readable string formatted as 'Month Year' (e.g., 'May 2024') to
122 * display to users.
123 *
124 * @return WP_REST_Response A response containing the formatted months and years.
125 */
126 public function get_months_with_posts() {
127 global $wpdb;
128
129 // Query to get distinct year and month from posts of type 'docs'
130 $results = $wpdb->get_results(
131 "SELECT DISTINCT YEAR(post_date) AS year, MONTH(post_date) AS month
132 FROM $wpdb->posts
133 WHERE post_type = 'docs'
134 ORDER BY post_date DESC"
135 );
136
137 $formatted_months = [];
138
139 foreach ( $results as $result ) {
140 $year = $result->year;
141 $month = $result->month;
142
143 // Create a DateTime object to format the month
144 $date = \DateTime::createFromFormat( '!m', $month );
145 $month_name = $date->format( 'F' ); // Full month name
146 $month_number = $date->format( 'm' ); // Month number with leading zero
147
148 // Format the months and years into wp rest api structure like wp-json/wp/v2/doc_category
149 $formatted_months[] = [
150 'id' => "$year-$month_number", // e.g., '2024-05'
151 'name' => "$month_name $year" // e.g., 'May 2024'
152 ];
153 }
154
155 return rest_ensure_response( $formatted_months );
156 }
157
158 /**
159 * Callback function to retrieve 'year_month' field value.
160 *
161 * @param object $post The REST API response object.
162 * @return string The formatted date (e.g., '2024-05').
163 */
164 public function year_month( $post ) {
165 $date_string = isset( $post->post_date ) ? $post->post_date : '';
166
167 $date = new \DateTime( $date_string );
168
169 // Format the date to 'Y-m' (e.g., '2024-05')
170 $formatted_date = $date->format( 'Y-m' );
171
172 return $formatted_date;
173 }
174
175 /**
176 * Filter the docs query by year_month parameters.
177 *
178 * @param array $args The query arguments.
179 * @param WP_REST_Request $request The current REST API request.
180 * @return array Modified query arguments.
181 */
182 public function filter_docs_query( $args, $request ) {
183 // Filter by year_month
184 if ( isset( $request['year_month'] ) ) {
185 $formatted_date = $request['year_month'];
186
187 // Parse the formatted_date to year and month
188 $year = substr( $formatted_date, 0, 4 );
189 $month = substr( $formatted_date, 5, 2 );
190
191 // Add date query arguments
192 $args['date_query'] = [
193 [
194 'year' => $year,
195 'month' => $month
196 ]
197 ];
198 }
199
200 return $args;
201 }
202
203
204 public function get_post_password( $object, $field_name, $request ) {
205 if ( current_user_can( 'edit_docs' ) ) {
206 return isset( $object['password'] ) ? $object['password'] : '';
207 } else {
208 return '';
209 }
210 }
211
212 public function search_posts( $request ) {
213 $search_query = sanitize_text_field( $request->get_param( 's' ) );
214 $doc_category = sanitize_text_field( $request->get_param( 'doc_category' ) );
215 $number = (int) $request->get_param( 'per_page' ) ? (int) $request->get_param( 'per_page' ) : 5;
216 $docs_ids = ! empty( $request->get_param( 'doc_ids' ) ) ? explode( ',', $request->get_param( 'doc_ids' ) ) : [];
217 $doc_term_ids = ! empty( $request->get_param( 'doc_categories_ids' ) ) ? explode( ',', $request->get_param( 'doc_categories_ids' ) ) : [];
218 $faq_term_ids = ! empty( $request->get_param( 'faq_categories_ids' ) ) ? explode( ',', $request->get_param( 'faq_categories_ids' ) ) : [];
219 $posts = array();
220
221 // Common query args
222 $common_args = [
223 'post_status' => 'publish',
224 'suppress_filters' => true,
225 'orderby' => 'relevance',
226 ];
227
228 if ( is_plugin_active( 'sitepress-multilingual-cms/sitepress.php' ) ) {
229 $common_args['suppress_filters'] = false;
230 $common_args['lang'] = ICL_LANGUAGE_CODE;
231 }
232
233 if ( $search_query ) {
234 $common_args['s'] = $search_query;
235 $common_args['posts_per_page'] = -1;
236 } else {
237 $common_args['posts_per_page'] = $number;
238 }
239
240 // Docs-specific query
241 $docs_args = array_merge(
242 $common_args,
243 [
244 'post_type' => 'docs'
245 ]
246 );
247
248 if ( ! $search_query ) {
249 $docs_args['meta_key'] = '_betterdocs_meta_views';
250 $docs_args['orderby'] = 'meta_value_num';
251 $docs_args['order'] = 'DESC';
252 }
253
254 if ( ! empty( $docs_ids ) ) {
255 unset( $docs_args['meta_key'] );
256 $docs_args['posts_per_page'] = -1;
257 $docs_args['post__in'] = $docs_ids;
258 }
259
260 if ( ! empty( $doc_term_ids ) ) {
261 unset( $docs_args['meta_key'] );
262 $docs_args['posts_per_page'] = -1;
263 $docs_args['tax_query'] = [
264 [
265 'taxonomy' => 'doc_category',
266 'field' => 'term_id',
267 'terms' => $doc_term_ids,
268 'operator' => 'IN',
269 ]
270 ];
271 }
272
273 // Taxonomy filter for docs
274 if ( $doc_category ) {
275 $docs_args['tax_query'] = [
276 [
277 'taxonomy' => 'doc_category',
278 'field' => 'slug',
279 'terms' => $doc_category,
280 'operator' => 'AND',
281 'include_children' => true,
282 ],
283 ];
284 }
285
286 // FAQ-specific query
287 $faq_args = array_merge(
288 $common_args,
289 [
290 'post_type' => 'betterdocs_faq',
291 'orderby' => 'date',
292 'order' => 'DESC',
293 ]
294 );
295
296 if ( ! empty( $faq_term_ids ) ) {
297 $faq_args['posts_per_page'] = -1;
298 $faq_args['tax_query'] = [
299 [
300 'taxonomy' => 'betterdocs_faq_category',
301 'field' => 'term_id',
302 'terms' => $faq_term_ids,
303 'operator' => 'IN',
304 ]
305 ];
306 }
307
308 // Run individual queries
309 $docs_query = betterdocs()->query->get_posts( $docs_args );
310 $faq_query = new WP_Query( $faq_args );
311
312 // Process docs posts
313 if ( $docs_query->have_posts() ) {
314 while ( $docs_query->have_posts() ) {
315 $docs_query->the_post();
316
317 $taxonomies = array();
318 $terms = get_the_terms( get_the_ID(), 'doc_category' );
319 if ( $terms && ! is_wp_error( $terms ) ) {
320 $taxonomies = wp_list_pluck( $terms, 'name' );
321 }
322
323 $posts[] = array(
324 'title' => get_the_title(),
325 'post_type' => get_post_type(),
326 'permalink' => get_the_permalink(),
327 'taxonomies' => implode( ', ', $taxonomies ),
328 );
329 }
330 wp_reset_postdata();
331 }
332
333 // Process FAQ posts with content
334 if ( $faq_query->have_posts() ) {
335 while ( $faq_query->have_posts() ) {
336 $faq_query->the_post();
337
338 $terms = get_the_terms( get_the_ID(), 'betterdocs_faq_category' );
339 $taxonomies = array();
340 if ( $terms && ! is_wp_error( $terms ) ) {
341 $taxonomies = wp_list_pluck( $terms, 'name' );
342 }
343
344 $posts[] = array(
345 'title' => get_the_title(),
346 'content' => get_the_content(), // Include post content for FAQ posts
347 'post_type' => get_post_type(),
348 'permalink' => get_the_permalink(),
349 'taxonomies' => implode( ', ', $taxonomies ),
350 );
351 }
352 wp_reset_postdata();
353 }
354
355 return $posts;
356 }
357
358
359
360 public function search_insert( $request ) {
361 $search_input = sanitize_text_field( $request->get_param( 's' ) );
362 $no_result = sanitize_text_field( $request->get_param( 'no_result' ) );
363
364 return betterdocs()->query->insert_search_keyword( $search_input, $no_result );
365 }
366
367
368 public function get_terms_name_and_slug( $request ) {
369 // Retrieve all terms for the specified taxonomy, including empty ones
370 $terms = get_terms(
371 [
372 'taxonomy' => $request->get_param( 'taxonomy' ),
373 'hide_empty' => false,
374 'fields' => 'all',
375 ]
376 );
377
378 // Initialize an empty array to hold the term data
379 $term_data = [];
380
381 // Loop through each term and extract the name and slug
382 $term_data = array_map(
383 function ( $term ) {
384 return [
385 'name' => $term->name,
386 'slug' => $term->slug,
387 'parent' => $term->parent,
388 ];
389 },
390 $terms
391 );
392
393 // Return the array of term data
394 return $term_data;
395 }
396
397 public function get_faq_categories( $request ) {}
398 }
399