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

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

511 lines 24.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDeveloper\BetterDocs\Core;
4
5 use WPDeveloper\BetterDocs\Utils\Base;
6 use WPDeveloper\BetterDocs\Utils\Helper;
7 use WPDeveloper\BetterDocs\Admin\Builder\Rules;
8
9 class KBMigration extends Base {
10 public $existing_plugins;
11 public $migrated_plugins;
12 public $active = 'helpscout';
13
14 public function __construct() {
15 $this->existing_plugins = $this->knowledge_base_plugins();
16 $this->migrated_plugins = $this->get_migrated_plugins();
17
18 add_filter( 'betterdocs_settings_tabs', [ $this, 'migration_settings' ], 10, 1 );
19 if ( ! $this->existing_plugins || ( $this->existing_plugins && in_array( $this->existing_plugins[0][0], $this->migrated_plugins )) ) {
20 return;
21 }
22 $this->active = 'kb-migration';
23 //add_filter( 'admin_notices', [ $this, 'migration_notice' ], 10, 1 );
24 add_filter( 'betterdocs_migration_tab_sections', [ $this, 'kb_migration_settings' ], 10, 1 );
25 }
26
27 public function migration_notice() {
28 $screen = get_current_screen()->id;
29 if ( $screen === 'betterdocs_page_betterdocs-setup' ) {
30 return;
31 }
32 ?>
33 <div class="notice notice-success is-dismissible">
34 <?php
35 printf(
36 '<p>%s<a class="button button-primary betterdocs-migration-notice" href="%s">%s</a><a class="button" href="">Maybe Later</a><a class="button" href="">Never Show Again</a></p>',
37 __(
38 sprintf(
39 'Whoops! You are already using %s on your website. To migrate your %s data to BetterDocs, click here ',
40 '<strong>'. esc_html($this->existing_plugins[0][1]) .'</strong>',
41 '<strong>'. esc_html($this->existing_plugins[0][1]) .'</strong>'
42 ),
43 'betterdocs'
44 ),
45 esc_url(admin_url('admin.php?page=betterdocs-settings&tab=tab-migration')),
46 esc_html__('Start Migration', 'betterdocs')
47 );
48 ?>
49 </div>
50 <?php
51 }
52
53 public function migration_settings( $args ) {
54 /**
55 * License Tab
56 */
57 $args['tab-migration'] = apply_filters( 'betterdocs_settings_tab_migration', [
58 'id' => 'tab-migration',
59 'name' => 'tab-migration',
60 'classes' => 'tab-migration',
61 'label' => __( 'Migration', 'betterdocs' ),
62 'priority' => 80,
63 'fields' => [
64 'sections-migration' => [
65 'name' => 'sections-migration',
66 'type' => 'section',
67 'label' => __( 'Migration', 'betterdocs' ),
68 'priority' => 30,
69 'fields' => [
70 'all-migration' => [
71 'id' => 'all-tab-migration',
72 'name' => 'all-tab-migration',
73 'label' => __( 'Migration Settings', 'betterdocs' ),
74 'classes' => 'tab-layout',
75 'type' => "tab",
76 'active' => $this->active,
77 'completionTrack' => true,
78 'sidebar' => false,
79 'save' => false,
80 'title' => false,
81 'config' => [
82 'active' => $this->active,
83 'sidebar' => false,
84 'title' => false
85 ],
86 'submit' => [
87 'show' => false
88 ],
89 'step' => [
90 'show' => false
91 ],
92 'priority' => 20,
93 'fields' => apply_filters( 'betterdocs_migration_tab_sections', [
94 'helpscout' => [
95 'id' => 'helpscout',
96 'name' => 'helpscout',
97 'type' => 'section',
98 'label' => __( 'Help Scout', 'betterdocs' ),
99 'priority' => 2,
100 'fields' => [
101 'helpscout_api_key' => [
102 'name' => 'helpscout_api_key',
103 'type' => 'text',
104 'label' => __('Docs API Key', 'betterdocs'),
105 'label_subtitle' => __('Check out this <a target="_blank" href="'.esc_url('https://betterdocs.co/docs/help-scout-migration-feature-with-betterdocs/').'">documentation</a> to retrieve your Help Scout Docs API Key', 'betterdocs'),
106 'default' => '',
107 'priority' => 1,
108 ],
109 'helpscout_collection_id' => [
110 'name' => 'helpscout_collection_id',
111 'type' => 'text',
112 'label' => __('Collection ID', 'betterdocs'),
113 'label_subtitle' => __('Check out this <a target="_blank" href="'.esc_url('https://betterdocs.co/docs/help-scout-migration-feature-with-betterdocs/').'">documentation</a> to retrieve your Help Scout Collection ID', 'betterdocs'),
114 'default' => '',
115 'priority' => 2,
116 ],
117 'helpscout_action' => apply_filters( 'betterdocs_helpscout_migration_action',[
118 'name' => 'helpscout_action',
119 'text' => [
120 'normal' => __('Migrate Help Scout Docs', 'betterdocs'),
121 'saved' => __('Migrate Help Scout Docs', 'betterdocs'),
122 'loading' => __('Migrating...', 'betterdocs'),
123 ],
124 'type' => 'button',
125 'priority' => 3,
126 'ajax' => [
127 'on' => 'click',
128 'api' => '/betterdocs/v1/helpscout-migration',
129 'data' => [
130 'helpscout_api_key' => '@helpscout_api_key',
131 'helpscout_collection_id' => '@helpscout_collection_id'
132 ],
133 'swal' => [
134 'text' => __( 'Migration process has started in the background.', 'betterdocs' ),
135 'icon' => 'success',
136 'autoClose' => 2000
137 ]
138 ]
139 ])
140 ]
141 ]
142 ])
143 ]
144 ]
145 ]
146 ]
147 ] );
148
149 return $args;
150 }
151
152 public function kb_migration_settings( $args ) {
153 /**
154 * License Tab
155 */
156 $args['kb-migration'] = [
157 'id' => 'kb-migration',
158 'name' => 'kb-migration',
159 'type' => 'section',
160 'label' => $this->existing_plugins[0][1],
161 'priority' => 1,
162 'fields' => [
163 'kb-migration-section' => [
164 'name' => 'kb-migration-section',
165 'classes' => 'kb-migration-section',
166 'type' => 'section',
167 'priority' => 0,
168 'save' => false,
169 'fields' => apply_filters( 'betterdocs_migration_fields', [
170 'migration_header' => [
171 'name' => 'migration_header',
172 'type' => 'header',
173 'title' => __( 'Migration', 'betterdocs' ),
174 'direction' => 'column',
175 'description' => wp_sprintf(
176 __( 'We found that there is another Knowledge Base plugin, %s, installed on this website. To migrate your knowledge base to BetterDocs from %s, click the "Start Migration" button and all the documentation will be migrated to BetterDocs.', 'betterdocs' ),
177 $this->existing_plugins[0][1],
178 $this->existing_plugins[0][1]
179 ),
180 'icon' => '<img src="' . betterdocs()->assets->icon( 'icons/migration.svg', true ) . '"/>',
181 'priority' => 1,
182 ],
183 'migration_action' => [
184 'name' => 'migration_action',
185 'type' => 'button',
186 'text' => [
187 'normal' => __('Start Migration', 'betterdocs'),
188 'saved' => __('Migrated', 'betterdocs'),
189 'loading' => __('Migrating...', 'betterdocs'),
190 ],
191 'ajax' => [
192 'on' => 'click',
193 'api' => '/betterdocs/v1/migrate',
194 'data' => [
195 'existing_plugins' => $this->existing_plugins[0][1],
196 ],
197 'swal' => [
198 'text' => __('Migration completed successfully.', 'betterdocs'),
199 'icon' => 'success',
200 'autoClose' => 1000
201 ],
202 'reload' => admin_url('admin.php?page=betterdocs-settings'),
203 ],
204 'priority' => 2,
205 ]
206 ])
207 ]
208 ]
209 ];
210
211 return $args;
212 }
213
214 public function migrate() {
215 $existing_plugins = $this->knowledge_base_plugins();
216 $existing_plugins_data = $this->existing_plugins_data( $existing_plugins[0][0] );
217 if ( isset( $existing_plugins_data['name'] ) && isset( $existing_plugins_data['url'] ) ) {
218 if ( $existing_plugins_data['name'] === 'echo-knowledge-base' ) {
219 $this->eco_knowledgebase_migration();
220 } elseif ( $existing_plugins_data['name'] === 'pressapps-knowledge-base' ) {
221 $this->pressapps_migration();
222 } elseif ( $existing_plugins_data['name'] === 'wedocs' ) {
223 $this->wedocs_migration();
224 }
225 $this->update_option( $existing_plugins_data['name'] );
226 deactivate_plugins( $existing_plugins_data['url'] );
227 }
228 }
229
230 public function knowledge_base_plugins() {
231 $plugins = [];
232
233 if ( Helper::is_plugin_active( 'wedocs/wedocs.php' ) ) {
234 $plugins[] = ['wedocs', 'weDocs'];
235 }
236 if ( Helper::is_plugin_active( 'bsf-docs/bsf-docs.php' ) ) {
237 $plugins[] = ['bsf-docs', 'BSF docs'];
238 }
239 if ( Helper::is_plugin_active( 'documentor-lite/documentor-lite.php' ) ) {
240 $plugins[] = ['documentor-lite', 'Documentor'];
241 }
242 if ( Helper::is_plugin_active( 'echo-knowledge-base/echo-knowledge-base.php' ) ) {
243 $plugins[] = ['echo-knowledge-base', 'Echo Knowledge Base'];
244 }
245 if ( Helper::is_plugin_active( 'pressapps-knowledge-base/pressapps-knowledge-base.php' ) ) {
246 $plugins[] = ['pressapps-knowledge-base', 'PressApps Knowledge Base'];
247 }
248
249 return $plugins;
250 }
251
252 public function insert_terms_hierarchically( $existing_term, $new_term, $parentId = 0 ) {
253 $into = [];
254 $cats = get_terms( $existing_term, ['hide_empty' => false] );
255 if ( $cats ) {
256 foreach ( $cats as $i => $cat ) {
257 if ( $cat->parent == $parentId ) {
258 $into[$cat->term_id] = $cat;
259 unset( $cats[$i] );
260 $doc_parent_term = term_exists( $cat->name, $new_term );
261 wp_insert_term(
262 $cat->name,
263 $new_term,
264 [
265 'alias_of' => $cat->slug,
266 'description' => $cat->description,
267 'slug' => $cat->slug,
268 'parent' => $cat->parent
269 ]
270 );
271 }
272 }
273 if ( $cats ) {
274 foreach ( $cats as $i => $cat ) {
275 $get_existing_term = get_term_by( 'id', $cat->parent, $existing_term );
276 $doc_parent_term = term_exists( $get_existing_term->name, $new_term );
277 wp_insert_term(
278 $cat->name,
279 $new_term,
280 [
281 'alias_of' => $cat->slug,
282 'description' => $cat->description,
283 'slug' => $cat->slug,
284 'parent' => $doc_parent_term['term_id']
285 ]
286 );
287 }
288 }
289 }
290 }
291
292 public function insert_posts( $existing_post, $existing_cat, $existing_tag ) {
293 $args = [
294 'post_type' => $existing_post,
295 'post_status' => 'any',
296 'posts_per_page' => -1
297 ];
298 $postslist = get_posts( $args );
299 if ( $postslist ) {
300 foreach ( $postslist as $post ) {
301 // Create post object
302 if ( ! get_page_by_title( $post->post_title, 'OBJECT', 'docs' ) ) {
303 $post_args = [
304 'post_type' => 'docs',
305 'post_title' => $post->post_title,
306 'post_content' => $post->post_content,
307 'post_status' => $post->post_status,
308 'post_author' => $post->post_author,
309 'post_date' => $post->post_date,
310 'post_date_gmt' => $post->post_date_gmt,
311 'post_excerpt' => $post->post_excerpt,
312 'comment_status' => $post->comment_status,
313 'ping_status' => $post->ping_status,
314 'post_password' => $post->post_password,
315 'post_name' => $post->post_name,
316 'to_ping' => $post->to_ping,
317 'pinged' => $post->pinged,
318 'post_modified' => $post->post_modified,
319 'post_modified_gmt' => $post->post_modified_gmt,
320 'post_content_filtered' => $post->post_content_filtered,
321 'post_parent' => $post->post_parent,
322 'post_mime_type' => $post->post_mime_type,
323 'comment_count' => $post->comment_count,
324 'filter' => $post->filter
325 ];
326 // Insert the post into the database
327 $result = wp_insert_post( $post_args );
328 if ( $result && ! is_wp_error( $result ) ) {
329 $cat_list = wp_get_post_terms( $post->ID, $existing_cat, ['fields' => 'all'] );
330 if ( $cat_list ) {
331 $post_id = $result;
332 wp_set_object_terms( $post_id, [$cat_list['0']->name], 'doc_category', false );
333 }
334 $tag_list = wp_get_post_terms( $post->ID, $existing_tag, ['fields' => 'all'] );
335 if ( $tag_list ) {
336 $post_id = $result;
337 wp_set_object_terms( $post_id, [$tag_list['0']->name], 'doc_tag', false );
338 }
339 }
340 }
341 }
342 }
343 }
344
345 public function existing_plugins_data( $plugins ) {
346 $plugins_data = [];
347 if ( $plugins === 'wedocs' ) {
348 $plugins_data['name'] = 'wedocs';
349 $plugins_data['url'] = 'wedocs/wedocs.php';
350 }
351 if ( $plugins === 'bsf-docs' ) {
352 $plugins_data['name'] = 'bsf-docs';
353 $plugins_data['url'] = 'bsf-docs/bsf-docs.php';
354 }
355 if ( $plugins === 'documentor-lite' ) {
356 $plugins_data['name'] = 'documentor-lite';
357 $plugins_data['url'] = 'documentor-lite/documentor-lite.php';
358 }
359 if ( $plugins === 'echo-knowledge-base' ) {
360 $plugins_data['name'] = 'echo-knowledge-base';
361 $plugins_data['url'] = 'echo-knowledge-base/echo-knowledge-base.php';
362 }
363 if ( $plugins === 'pressapps-knowledge-base' ) {
364 $plugins_data['name'] = 'pressapps-knowledge-base';
365 $plugins_data['url'] = 'pressapps-knowledge-base/pressapps-knowledge-base.php';
366 }
367 return $plugins_data;
368 }
369
370 public function eco_knowledgebase_migration() {
371 $this->insert_terms_hierarchically( 'epkb_post_type_1_category', 'doc_category' );
372 $this->insert_terms_hierarchically( 'epkb_post_type_1_tag', 'doc_tag' );
373 $this->insert_posts( 'epkb_post_type_1', 'epkb_post_type_1_category', 'epkb_post_type_1_tag' );
374 }
375
376 public function pressapps_migration() {
377 $this->insert_terms_hierarchically( 'knowledgebase_category', 'doc_category' );
378 $this->insert_terms_hierarchically( 'knowledgebase_tags', 'doc_tag' );
379 $this->insert_posts( 'knowledgebase', 'knowledgebase_category', 'knowledgebase_tags' );
380 }
381
382 public function wedocs_migration() {
383 // Step 1: Get posts with no parent (main posts)
384 $args_step1 = array(
385 'post_type' => 'docs',
386 'post_status' => 'publish',
387 'posts_per_page' => -1,
388 'post_parent' => 0,
389 );
390
391 $posts_step1 = get_posts( $args_step1 );
392
393 // Multidimensional array to store posts
394 $nested_posts = array();
395
396 // First Dimension key: 'multiple_kb'
397 foreach ( $posts_step1 as $post_step1 ) {
398 $nested_posts['multiple_kb'][$post_step1->ID] = array(
399 'post' => $post_step1,
400 'doc_category' => array(), // Initialize the second dimension
401 );
402
403 // Step 2: 'doc_category'
404 $args_step2 = array(
405 'post_type' => 'docs',
406 'post_status' => 'publish',
407 'posts_per_page' => -1,
408 'post_parent' => $post_step1->ID,
409 );
410
411 $posts_step2 = get_posts($args_step2);
412
413 foreach ( $posts_step2 as $post_step2 ) {
414 $nested_posts['multiple_kb'][$post_step1->ID]['doc_category'][$post_step2->ID] = array(
415 'post' => $post_step2,
416 'docs' => array(), // Initialize the third dimension
417 );
418
419 // Step 3: 'docs'
420 $args_step3 = array(
421 'post_type' => 'docs', // Replace with your actual post type
422 'post_status' => 'publish',
423 'posts_per_page' => -1,
424 'post_parent' => $post_step2->ID,
425 );
426
427 $posts_step3 = get_posts($args_step3);
428
429 foreach ( $posts_step3 as $post_step3 ) {
430 $nested_posts['multiple_kb'][$post_step1->ID]['doc_category'][$post_step2->ID]['docs'][$post_step3->ID] = array(
431 'post' => $post_step3,
432 );
433 // Continue with additional dimensions if needed
434 }
435 }
436 }
437
438 // Now, $nested_posts contains the posts organized in a multidimensional array with the specified key names
439
440 foreach ( $nested_posts['multiple_kb'] as $multiple_kb_id => $multiple_kb_data ) {
441 // Step 1: Insert posts as terms under 'knowledge_base'
442 $knowledge_base_id = wp_insert_term($multiple_kb_data['post']->post_title, 'knowledge_base');
443
444 if ( ! is_wp_error($knowledge_base_id) ) {
445 wp_delete_post($multiple_kb_data['post']->ID, true);
446 $knowledge_base_term = get_term($knowledge_base_id['term_id'], 'knowledge_base');
447 }
448
449 foreach ( $multiple_kb_data['doc_category'] as $doc_category_id => $doc_category_data ) {
450
451 // Step 2: Insert posts as terms under 'doc_category' and set term meta
452 $doc_category_id = wp_insert_term($doc_category_data['post']->post_title, 'doc_category');
453
454 if (!is_wp_error($doc_category_id)) {
455 $doc_category_term = get_term($doc_category_id['term_id'], 'doc_category');
456 wp_delete_post($doc_category_data['post']->ID, true);
457 $doc_category_kb = rest_sanitize_array( array($knowledge_base_term->slug) );
458 // Set term meta for 'knowledge_base_doc_category'
459 update_term_meta($doc_category_id['term_id'], 'doc_category_knowledge_base', $doc_category_kb);
460 }
461
462 foreach ( $doc_category_data['docs'] as $docs_id => $docs_data ) {
463 wp_set_post_terms($docs_data['post']->ID, array($knowledge_base_term->term_id), 'knowledge_base');
464 wp_set_post_terms($docs_data['post']->ID, array($doc_category_term->term_id), 'doc_category');
465 // // Step 3: Update posts to assign correct parent terms
466 // wp_update_post(array(
467 // 'ID' => $docs_data['post']->ID,
468 // 'post_parent' => 0,
469 // ));
470 }
471 }
472 }
473 }
474
475 /**
476 * Updates the 'betterdocs_migration' option with migrated knowledge base plugin names.
477 *
478 * This function checks if the option exists and is a serialized array. If the option exists,
479 * it unserializes the current value, merges it with the new values, serializes the merged array,
480 * and updates the option. If the option doesn't exist or is not a serialized array, it creates
481 * a new option with the serialized format.
482 *
483 * @param string $kb_name The name of the knowledge base to be added or updated.
484 *
485 * @return void
486 */
487 public function update_option( $kb_name ) {
488 $existing_value = get_option( 'betterdocs_migration' );
489 $new_values = array( $kb_name );
490
491 if ($existing_value !== false && is_serialized( $existing_value )) {
492 $existing_values_array = unserialize($existing_value);
493 $merged_values = array_merge($existing_values_array, $new_values);
494
495 update_option('betterdocs_migration', serialize($merged_values));
496 } else {
497 update_option('betterdocs_migration', serialize($new_values));
498 }
499 }
500
501 public function get_migrated_plugins() {
502 $existing_value = get_option( 'betterdocs_migration' );
503
504 if ( $existing_value ) {
505 return unserialize($existing_value);
506 }
507
508 return [];
509 }
510 }
511