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

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

363 lines 11.3 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 WP_Query;
6 use WP_REST_Request;
7 use WPDeveloper\BetterDocs\Admin\CSVExporter;
8 use WPDeveloper\BetterDocs\Admin\Importer\Parsers\CSV_Parser;
9 use WPDeveloper\BetterDocs\Admin\Importer\WPImport;
10 use WPDeveloper\BetterDocs\Admin\ReportEmail;
11 use WPDeveloper\BetterDocs\Admin\XMLExporter;
12 use WPDeveloper\BetterDocs\Core\BaseAPI;
13 use WPDeveloper\BetterDocs\Dependencies\DI\DependencyException;
14 use WPDeveloper\BetterDocs\Dependencies\DI\NotFoundException;
15 use WPDeveloper\BetterDocsChatbot\Core\AIChatbot;
16 use WPDeveloper\BetterDocs\Core\Settings as CoreSettings;
17 use WPDeveloper\BetterDocs\Utils\Helper;
18
19 class Settings extends BaseAPI {
20
21 public function permission_check(): bool {
22 return current_user_can( 'edit_docs_settings' );
23 }
24
25 public function register() {
26 $this->get( 'settings', [ $this, 'get_settings' ] );
27 $this->post( 'dark-mode', [ $this, 'dark_mode' ] );
28 $this->post( 'settings', [ $this, 'save_settings' ] );
29 $this->post( 'plugin_insights', [ $this, 'plugin_insights' ] );
30 $this->post( 'create-sample-docs', [$this, 'sample_docs'] );
31 $this->post( 'reporting-test', [ $this, 'test_reporting' ] );
32 $this->post( 'export-docs', [ $this, 'export_docs' ] );
33 $this->post( 'export-settings', [ $this, 'export_settings' ] );
34 $this->post( 'import-docs', [ $this, 'import_docs' ] );
35 $this->post( 'import-settings', [ $this, 'import_settings' ] );
36 $this->post( 'parse-xml', [ $this, 'parse_xml' ] );
37 $this->post( 'parse-csv', [ $this, 'parse_csv' ] );
38 $this->post( 'migrate', [ $this, 'migrate_plugins' ] );
39 $this->post( 'helpscout-migration', [$this, 'helpscout_migration'] );
40 $this->post( 'dashboard-mode', [$this, 'dashboard_mode'] );
41 }
42
43 public function dashboard_mode( WP_REST_Request $request ) {
44 $mode = $request->get_param( 'dashboard_mode' );
45 return update_option( 'dashboard_mode', $mode );
46 }
47
48 public function dark_mode( WP_REST_Request $request ): bool {
49 $dark_mode = rest_sanitize_boolean( $request->get_param( 'mode' ) );
50
51 if ( betterdocs()->settings->save( 'dark_mode', $dark_mode ) ) {
52 return true;
53 }
54
55 return false;
56 }
57
58 public function sample_docs( WP_REST_Request $request ) {
59 $action = $request->get_param( 'action' );
60
61 if ( $action == 'create-dummy-data' ) {
62 $file = BETTERDOCS_ABSPATH . 'assets/static/admin/images/BetterDocs-sample-data.csv';
63 $args = [
64 'fetch_attachments' => true,
65 'action' => '',
66 'existing_slug' => '',
67 'file_type' => 'text/csv'
68 ];
69 $wp_import_object = new WPImport( $file, $args );
70 return $wp_import_object->run();
71 }
72 }
73
74 public function export_docs( WP_REST_Request $request ) {
75 $data = $request->get_params();
76 $args = [
77 'include_post_featured_image_as_attachment' => true,
78 'status' => 'publish',
79 'content' => $data['export_type'],
80 'selected_docs' => $data['export_docs'],
81 'include_faq' => $data['enable_export_faq'],
82 ];
83
84 if ( $data['export_type'] == 'docs' && $data['export_docs'][0] != 'all' ) {
85 $args['post__in'] = $data['export_docs'];
86 }
87
88 if ( $data['export_type'] == 'doc_category' || $data['export_type'] == 'knowledge_base' ) {
89 $args['content'] = 'docs';
90 }
91
92 if ( $data['export_type'] == 'doc_category' && $data['export_categories'][0] != 'all' ) {
93 $args['category_terms'] = $data['export_categories'];
94 } else if ( $data['export_type'] == 'knowledge_base' && $data['export_kbs'][0] != 'all' ) {
95 $args['kb_terms'] = $data['export_kbs'];
96 }
97
98 if ( $data['export_type'] == 'glossaries' && $data['export_glossaries'][0] != 'all' ) {
99 $args['glossary_terms'] = $data['export_glossaries'];
100 unset( $args['selected_docs'] );
101 }
102
103 if ( $data['file_type'] == 'xml' ) {
104 $exporter = new XMLExporter( $args );
105 } else if ( $data['file_type'] == 'csv' ) {
106 $exporter = new CSVExporter( $args );
107 }
108
109 /**
110 * @var XMLExporter|CSVExporter $exporter
111 */
112
113 return $exporter->run();
114 }
115
116 public function export_settings( WP_REST_Request $request ): array {
117 $betterdocs_settings = get_option( 'betterdocs_settings' );
118 $json_str = json_encode( $betterdocs_settings, JSON_PRETTY_PRINT );
119 $file_name = 'betterdocs-settings.json';
120
121 return [
122 'success' => true,
123 'data' => [
124 'filename' => $file_name,
125 'filetype' => 'text/json',
126 'download' => $json_str,
127 ]
128 ];
129 }
130
131 public function import_settings( WP_REST_Request $request ): array {
132 $settings = $request->get_param( 'settings' );
133 // Decode the JSON data into a PHP array
134 $settings = json_decode( $settings, true );
135 $saved = update_option( 'betterdocs_settings', $settings );
136
137 if ( ! $saved ) {
138 return [
139 'status' => 'failed'
140 ];
141 }
142
143 return [
144 'status' => 'success'
145 ];
146 }
147
148 public function import_docs( WP_REST_Request $request ): array {
149 $existing_slug = $request->get_param( 'existing_slug' );
150 $action = $request->get_param( 'action' );
151
152 $files = $request->get_file_params();
153
154 $file = $files['file']['tmp_name'];
155
156 $args = [
157 'fetch_attachments' => true,
158 'existing_slug' => $existing_slug,
159 'action' => $action,
160 'file_type' => $files['file']['type']
161 ];
162
163 $wp_importer = new WPImport( $file, $args );
164
165 return $wp_importer->run();
166 }
167
168 public function parse_xml( WP_REST_Request $request ): array {
169 $data = $request->get_params();
170 $existing_post_slugs = $this->get_existing_slugs( $data['posts'] );
171
172 // Output the array of existing post slugs
173 return [
174 'status' => 'success',
175 'data' => $existing_post_slugs,
176 ];
177 }
178
179 public function parse_csv( WP_REST_Request $request ): array {
180 $files = $request->get_file_params();
181
182 $file = $files['file']['tmp_name'];
183
184 $parser = new CSV_Parser();
185 $parsed = $parser->parse( $file );
186
187 $existing_post_slugs = [];
188
189 if ( isset( $parsed['posts'] ) && is_array( $parsed['posts'] ) ) {
190 $post_names = array_map(
191 function ( $post ) {
192 return $post['post_name'];
193 },
194 $parsed['posts']
195 );
196
197 $existing_post_slugs = $this->get_existing_slugs( $post_names );
198 }
199
200 return [
201 'status' => 'success',
202 'data' => $existing_post_slugs,
203 ];
204 }
205
206 public function migrate_plugins( WP_REST_Request $request ): array {
207 betterdocs()->kbmigration->migrate();
208
209 return [
210 'status' => 'success'
211 ];
212 }
213
214 public function helpscout_migration( WP_REST_Request $request ) {
215 $api_key = $request->get_param( 'helpscout_api_key' );
216 $collection_id = $request->get_param( 'helpscout_collection_id' );
217
218 if ( ! $api_key || ! $collection_id ) {
219 return [
220 'status' => 'error',
221 'message' => esc_html__( 'Please provide both API Key and Collection ID', 'betterdocs' )
222 ];
223 }
224
225 $api_endpoint = 'https://docsapi.helpscout.net/v1/collections/' . $collection_id . '/articles?pageSize=1';
226
227 $headers = array(
228 'Authorization' => 'Basic ' . base64_encode( $api_key . ':X' ),
229 'Content-Type' => 'application/json',
230 );
231
232 $initial_response = wp_remote_get( $api_endpoint, array( 'headers' => $headers ) );
233
234 if ( $initial_response['response']['code'] == '404' || $initial_response['response']['code'] == 401 ) {
235 return [
236 'status' => 'error',
237 'message' => esc_html__( 'Unauthorized API Key or Collection ID', 'betterdocs' )
238 ];
239 }
240
241 // Enqueue migration task
242 betterdocs()->backgroundProccessor->push_to_queue(
243 array(
244 'headers' => $headers,
245 'initial_response' => $initial_response,
246 'api_key' => $api_key,
247 'collection_id' => $collection_id
248 )
249 )->save();
250
251 // Start processing the queue
252 betterdocs()->backgroundProccessor->dispatch();
253
254 return [
255 'status' => 'success',
256 'message' => esc_html__( 'Migration process has started in the background.', 'betterdocs' )
257 ];
258 }
259
260 public function get_existing_slugs( $slugs ) {
261 // Initialize the array for existing post slugs
262 $existing_post_slugs = [];
263
264 // Initialize the query arguments
265 $args = [
266 'post_type' => [ 'docs', 'betterdocs_faq' ], // Change 'post' to your custom post type if applicable
267 'post_status' => 'publish',
268 'posts_per_page' => -1, // Retrieve all posts
269 'fields' => 'ids', // Retrieve only post IDs to reduce memory usage
270 ];
271
272 // Create a new instance of WP_Query
273 $query = new WP_Query( $args );
274
275 // Get an array of post slugs from the query
276 $all_post_slugs = array_map(
277 function ( $post_id ) {
278 return get_post_field( 'post_name', $post_id );
279 },
280 $query->posts
281 );
282
283 // Restore original post data
284 wp_reset_postdata();
285
286 // Find the intersection of the two arrays to get existing post slugs
287 return array_intersect( $slugs, $all_post_slugs );
288 }
289
290 public function insights(): bool {
291 return true;
292 }
293
294 public function get_settings(): array {
295 $settings = betterdocs()->settings->get_all( true );
296
297 // Never hand raw API keys back over REST. The route is already gated to
298 // `edit_docs_settings` (see permission_check() above), but get_all( true ) returned
299 // UNMASKED values, so an authorized admin still received every key in full — the admin
300 // UI only ever needs the masked form. Mask for managers, and strip entirely for anyone
301 // else as defense-in-depth should that capability gate ever loosen. Mirrors the
302 // admin-page localizer (Core\Settings::enqueue()) so the masked-key save round-trip
303 // stays consistent.
304 $sensitive_api_keys = CoreSettings::sensitive_api_key_fields();
305 $can_manage = current_user_can( 'edit_docs_settings' );
306 foreach ( $sensitive_api_keys as $api_key_field ) {
307 if ( ! isset( $settings[ $api_key_field ] ) ) {
308 continue;
309 }
310 if ( ! $can_manage ) {
311 unset( $settings[ $api_key_field ] );
312 continue;
313 }
314 if ( ! empty( $settings[ $api_key_field ] ) ) {
315 $settings[ $api_key_field ] = Helper::mask_api_key( $settings[ $api_key_field ] );
316 }
317 }
318
319 return $settings;
320 }
321
322 public function save_settings( WP_REST_Request $request ) {
323 $result = betterdocs()->settings->save_settings( $request->get_params() );
324 if ( is_wp_error( $result ) ) {
325 return $this->error( $result->get_error_code(), $result->get_error_message(), 400 );
326 }
327 if ( $result ) {
328 return $this->success( __( 'Settings Saved!', 'betterdocs' ) );
329 }
330
331 return $this->error( 'nothing_changed', __( 'There are no changes to be saved.', 'betterdocs' ), 200 );
332 }
333
334 /**
335 * @throws NotFoundException
336 * @throws DependencyException
337 */
338 public function test_reporting( $request ) {
339 return $this->container->get( ReportEmail::class )->test_email_report( $request );
340 }
341
342 public function do_wizard_tracking(): bool {
343 $insights = betterdocs()->admin->plugin_insights( true );
344 // Get our data
345 $insights->schedule_tracking();
346 $insights->set_is_tracking_allowed( true, 'betterdocs' );
347 if ( $insights->do_tracking( true ) ) {
348 $insights->update_block_notice( 'betterdocs' );
349 }
350 if ( ! isset( $_COOKIE['betterdocs_insights_allowed'] ) ) {
351 setcookie( 'betterdocs_insights_allowed', true, time() + ( 30 * 24 * 60 * 60 ), '/' );
352 }
353 return true;
354 }
355
356 public function plugin_insights( $request ) {
357 if ( $this->do_wizard_tracking() ) {
358 wp_send_json_success( 'done' );
359 }
360 wp_send_json_error( 'Something went wrong.' );
361 }
362 }
363