existing_plugins = $this->knowledge_base_plugins();
$this->migrated_plugins = $this->get_migrated_plugins();
add_filter( 'betterdocs_settings_tabs', [ $this, 'migration_settings' ], 10, 1 );
if ( ! $this->existing_plugins || ( $this->existing_plugins && in_array( $this->existing_plugins[0][0], $this->migrated_plugins ) ) ) {
return;
}
$this->active = 'kb-migration';
//add_filter( 'admin_notices', [ $this, 'migration_notice' ], 10, 1 );
add_filter( 'betterdocs_migration_tab_sections', [ $this, 'kb_migration_settings' ], 10, 1 );
}
public function migration_notice() {
$screen = get_current_screen()->id;
if ( $screen === 'betterdocs_page_betterdocs-setup' ) {
return;
}
?>
%s
%s%s%s',
esc_html(
sprintf(
/* translators: %1$s and %2$s are the name of the existing plugin. */
__(
'Whoops! You are already using %1$s on your website. To migrate your %2$s data to BetterDocs, click here ',
'betterdocs'
),
'
' . esc_html( $this->existing_plugins[0][1] ) . '',
'
' . esc_html( $this->existing_plugins[0][1] ) . ''
)
),
esc_url( admin_url( 'admin.php?page=betterdocs-settings&tab=tab-migration' ) ),
esc_html__( 'Start Migration', 'betterdocs' ),
esc_html__( 'Maybe Later', 'betterdocs' ),
esc_html__( 'Never Show Again', 'betterdocs' )
);
?>
'tab-migration',
'name' => 'tab-migration',
'classes' => 'tab-migration',
'label' => __( 'Migration', 'betterdocs' ),
'priority' => 80,
'fields' => [
'sections-migration' => [
'name' => 'sections-migration',
'type' => 'section',
'label' => __( 'Migration', 'betterdocs' ),
'priority' => 30,
'fields' => [
'all-migration' => [
'id' => 'all-tab-migration',
'name' => 'all-tab-migration',
'label' => __( 'Migration Settings', 'betterdocs' ),
'classes' => 'tab-layout',
'type' => 'tab',
'active' => $this->active,
'completionTrack' => true,
'sidebar' => false,
'save' => false,
'title' => false,
'config' => [
'active' => $this->active,
'sidebar' => false,
'title' => false
],
'submit' => [
'show' => false
],
'step' => [
'show' => false
],
'priority' => 20,
'fields' => apply_filters(
'betterdocs_migration_tab_sections',
[
'helpscout' => [
'id' => 'helpscout',
'name' => 'helpscout',
'type' => 'section',
'label' => __( 'Help Scout', 'betterdocs' ),
'priority' => 2,
'fields' => [
'helpscout_api_key' => [
'name' => 'helpscout_api_key',
'type' => 'text',
'label' => __( 'Docs API Key', 'betterdocs' ),
'label_subtitle' => sprintf(
/* translators: %s is a URL to the Help Scout migration documentation. */
__( 'Check out this documentation to retrieve your Help Scout Docs API Key.', 'betterdocs' ),
esc_url( 'https://betterdocs.co/docs/help-scout-migration-feature-with-betterdocs/' )
),
'default' => '',
'priority' => 1,
],
'helpscout_collection_id' => [
'name' => 'helpscout_collection_id',
'type' => 'text',
'label' => __( 'Collection ID', 'betterdocs' ),
'label_subtitle' => sprintf(
/* translators: %s is a URL to the Help Scout migration documentation. */
__( 'Check out this documentation to retrieve your Help Scout Collection ID.', 'betterdocs' ),
esc_url( 'https://betterdocs.co/docs/help-scout-migration-feature-with-betterdocs/' )
),
'default' => '',
'priority' => 2,
],
'helpscout_action' => apply_filters(
'betterdocs_helpscout_migration_action',
[
'name' => 'helpscout_action',
'text' => [
'normal' => __( 'Migrate Help Scout Docs', 'betterdocs' ),
'saved' => __( 'Migrate Help Scout Docs', 'betterdocs' ),
'loading' => __( 'Migrating...', 'betterdocs' ),
],
'type' => 'button',
'priority' => 3,
'ajax' => [
'on' => 'click',
'api' => '/betterdocs/v1/helpscout-migration',
'data' => [
'helpscout_api_key' => '@helpscout_api_key',
'helpscout_collection_id' => '@helpscout_collection_id'
],
'swal' => [
'text' => __( 'Migration process has started in the background.', 'betterdocs' ),
'icon' => 'success',
'autoClose' => 2000
]
]
]
)
]
]
]
)
]
]
]
]
]
);
return $args;
}
public function kb_migration_settings( $args ) {
/**
* License Tab
*/
$args['kb-migration'] = [
'id' => 'kb-migration',
'name' => 'kb-migration',
'type' => 'section',
'label' => $this->existing_plugins[0][1],
'priority' => 1,
'fields' => [
'kb-migration-section' => [
'name' => 'kb-migration-section',
'classes' => 'kb-migration-section',
'type' => 'section',
'priority' => 0,
'save' => false,
'fields' => apply_filters(
'betterdocs_migration_fields',
[
'migration_header' => [
'name' => 'migration_header',
'type' => 'header',
'title' => __( 'Migration', 'betterdocs' ),
'direction' => 'column',
'description' => sprintf(
/* translators: %1$s is the name of the existing knowledge base plugin. */
__( 'We found that there is another Knowledge Base plugin, %1$s, installed on this website. To migrate your knowledge base to BetterDocs from %2$s, click the "Start Migration" button and all the documentation will be migrated to BetterDocs.', 'betterdocs' ),
esc_html( $this->existing_plugins[0][1] ),
esc_html( $this->existing_plugins[0][1] )
),
'icon' => '
',
'priority' => 1,
],
'migration_action' => [
'name' => 'migration_action',
'type' => 'button',
'text' => [
'normal' => __( 'Start Migration', 'betterdocs' ),
'saved' => __( 'Migrated', 'betterdocs' ),
'loading' => __( 'Migrating...', 'betterdocs' ),
],
'ajax' => [
'on' => 'click',
'api' => '/betterdocs/v1/migrate',
'data' => [
'existing_plugins' => $this->existing_plugins[0][1],
],
'swal' => [
'text' => __( 'Migration completed successfully.', 'betterdocs' ),
'icon' => 'success',
'autoClose' => 1000
],
'reload' => admin_url( 'admin.php?page=betterdocs-settings' ),
],
'priority' => 2,
]
]
)
]
]
];
return $args;
}
public function migrate() {
$existing_plugins = $this->knowledge_base_plugins();
$existing_plugins_data = $this->existing_plugins_data( $existing_plugins[0][0] );
if ( isset( $existing_plugins_data['name'] ) && isset( $existing_plugins_data['url'] ) ) {
if ( $existing_plugins_data['name'] === 'echo-knowledge-base' ) {
$this->eco_knowledgebase_migration();
} elseif ( $existing_plugins_data['name'] === 'pressapps-knowledge-base' ) {
$this->pressapps_migration();
} elseif ( $existing_plugins_data['name'] === 'wedocs' ) {
$this->wedocs_migration();
}
$this->update_option( $existing_plugins_data['name'] );
deactivate_plugins( $existing_plugins_data['url'] );
}
}
public function knowledge_base_plugins() {
$plugins = [];
if ( Helper::is_plugin_active( 'wedocs/wedocs.php' ) ) {
$plugins[] = [ 'wedocs', 'weDocs' ];
}
if ( Helper::is_plugin_active( 'bsf-docs/bsf-docs.php' ) ) {
$plugins[] = [ 'bsf-docs', 'BSF docs' ];
}
if ( Helper::is_plugin_active( 'documentor-lite/documentor-lite.php' ) ) {
$plugins[] = [ 'documentor-lite', 'Documentor' ];
}
if ( Helper::is_plugin_active( 'echo-knowledge-base/echo-knowledge-base.php' ) ) {
$plugins[] = [ 'echo-knowledge-base', 'Echo Knowledge Base' ];
}
if ( Helper::is_plugin_active( 'pressapps-knowledge-base/pressapps-knowledge-base.php' ) ) {
$plugins[] = [ 'pressapps-knowledge-base', 'PressApps Knowledge Base' ];
}
return $plugins;
}
public function insert_terms_hierarchically( $existing_term, $new_term, $parentId = 0 ) {
$into = [];
$cats = get_terms(
[
'taxonomy' => $existing_term,
'hide_empty' => false
]
);
if ( $cats ) {
foreach ( $cats as $i => $cat ) {
if ( $cat->parent == $parentId ) {
$into[ $cat->term_id ] = $cat;
unset( $cats[ $i ] );
$doc_parent_term = term_exists( $cat->name, $new_term );
wp_insert_term(
$cat->name,
$new_term,
[
'alias_of' => $cat->slug,
'description' => $cat->description,
'slug' => $cat->slug,
'parent' => $cat->parent
]
);
}
}
if ( $cats ) {
foreach ( $cats as $i => $cat ) {
$get_existing_term = get_term_by( 'id', $cat->parent, $existing_term );
$doc_parent_term = term_exists( $get_existing_term->name, $new_term );
wp_insert_term(
$cat->name,
$new_term,
[
'alias_of' => $cat->slug,
'description' => $cat->description,
'slug' => $cat->slug,
'parent' => $doc_parent_term['term_id']
]
);
}
}
}
}
public function insert_posts( $existing_post, $existing_cat, $existing_tag ) {
$args = [
'post_type' => $existing_post,
'post_status' => 'any',
'posts_per_page' => -1,
];
$postslist = get_posts( $args );
if ( $postslist ) {
foreach ( $postslist as $post ) {
// Check if a post with the same title exists using WP_Query
$query_args = [
'post_type' => 'docs',
'post_status' => 'any',
'title' => $post->post_title,
'posts_per_page' => 1,
'fields' => 'ids',
];
$existing_doc = new WP_Query( $query_args );
if ( ! $existing_doc->have_posts() ) {
$post_args = [
'post_type' => 'docs',
'post_title' => $post->post_title,
'post_content' => $post->post_content,
'post_status' => $post->post_status,
'post_author' => $post->post_author,
'post_date' => $post->post_date,
'post_date_gmt' => $post->post_date_gmt,
'post_excerpt' => $post->post_excerpt,
'comment_status' => $post->comment_status,
'ping_status' => $post->ping_status,
'post_password' => $post->post_password,
'post_name' => $post->post_name,
'to_ping' => $post->to_ping,
'pinged' => $post->pinged,
'post_modified' => $post->post_modified,
'post_modified_gmt' => $post->post_modified_gmt,
'post_content_filtered' => $post->post_content_filtered,
'post_parent' => $post->post_parent,
'post_mime_type' => $post->post_mime_type,
'comment_count' => $post->comment_count,
'filter' => $post->filter,
];
// Insert the post into the database
$result = wp_insert_post( $post_args );
if ( $result && ! is_wp_error( $result ) ) {
$cat_list = wp_get_post_terms( $post->ID, $existing_cat, [ 'fields' => 'all' ] );
if ( $cat_list ) {
$post_id = $result;
wp_set_object_terms( $post_id, [ $cat_list[0]->name ], 'doc_category', false );
}
$tag_list = wp_get_post_terms( $post->ID, $existing_tag, [ 'fields' => 'all' ] );
if ( $tag_list ) {
$post_id = $result;
wp_set_object_terms( $post_id, [ $tag_list[0]->name ], 'doc_tag', false );
}
}
}
// Reset post data after query
wp_reset_postdata();
}
}
}
public function existing_plugins_data( $plugins ) {
$plugins_data = [];
if ( $plugins === 'wedocs' ) {
$plugins_data['name'] = 'wedocs';
$plugins_data['url'] = 'wedocs/wedocs.php';
}
if ( $plugins === 'bsf-docs' ) {
$plugins_data['name'] = 'bsf-docs';
$plugins_data['url'] = 'bsf-docs/bsf-docs.php';
}
if ( $plugins === 'documentor-lite' ) {
$plugins_data['name'] = 'documentor-lite';
$plugins_data['url'] = 'documentor-lite/documentor-lite.php';
}
if ( $plugins === 'echo-knowledge-base' ) {
$plugins_data['name'] = 'echo-knowledge-base';
$plugins_data['url'] = 'echo-knowledge-base/echo-knowledge-base.php';
}
if ( $plugins === 'pressapps-knowledge-base' ) {
$plugins_data['name'] = 'pressapps-knowledge-base';
$plugins_data['url'] = 'pressapps-knowledge-base/pressapps-knowledge-base.php';
}
return $plugins_data;
}
public function eco_knowledgebase_migration() {
$this->insert_terms_hierarchically( 'epkb_post_type_1_category', 'doc_category' );
$this->insert_terms_hierarchically( 'epkb_post_type_1_tag', 'doc_tag' );
$this->insert_posts( 'epkb_post_type_1', 'epkb_post_type_1_category', 'epkb_post_type_1_tag' );
}
public function pressapps_migration() {
$this->insert_terms_hierarchically( 'knowledgebase_category', 'doc_category' );
$this->insert_terms_hierarchically( 'knowledgebase_tags', 'doc_tag' );
$this->insert_posts( 'knowledgebase', 'knowledgebase_category', 'knowledgebase_tags' );
}
public function wedocs_migration() {
// Step 1: Get posts with no parent (main posts)
$args_step1 = array(
'post_type' => 'docs',
'post_status' => 'publish',
'posts_per_page' => -1,
'post_parent' => 0,
);
$posts_step1 = get_posts( $args_step1 );
// Multidimensional array to store posts
$nested_posts = array();
// First Dimension key: 'multiple_kb'
foreach ( $posts_step1 as $post_step1 ) {
$nested_posts['multiple_kb'][ $post_step1->ID ] = array(
'post' => $post_step1,
'doc_category' => array(), // Initialize the second dimension
);
// Step 2: 'doc_category'
$args_step2 = array(
'post_type' => 'docs',
'post_status' => 'publish',
'posts_per_page' => -1,
'post_parent' => $post_step1->ID,
);
$posts_step2 = get_posts( $args_step2 );
foreach ( $posts_step2 as $post_step2 ) {
$nested_posts['multiple_kb'][ $post_step1->ID ]['doc_category'][ $post_step2->ID ] = array(
'post' => $post_step2,
'docs' => array(), // Initialize the third dimension
);
// Step 3: 'docs'
$args_step3 = array(
'post_type' => 'docs', // Replace with your actual post type
'post_status' => 'publish',
'posts_per_page' => -1,
'post_parent' => $post_step2->ID,
);
$posts_step3 = get_posts( $args_step3 );
foreach ( $posts_step3 as $post_step3 ) {
$nested_posts['multiple_kb'][ $post_step1->ID ]['doc_category'][ $post_step2->ID ]['docs'][ $post_step3->ID ] = array(
'post' => $post_step3,
);
// Continue with additional dimensions if needed
}
}
}
// Now, $nested_posts contains the posts organized in a multidimensional array with the specified key names
foreach ( $nested_posts['multiple_kb'] as $multiple_kb_id => $multiple_kb_data ) {
// Step 1: Insert posts as terms under 'knowledge_base'
$knowledge_base_id = wp_insert_term( $multiple_kb_data['post']->post_title, 'knowledge_base' );
if ( ! is_wp_error( $knowledge_base_id ) ) {
wp_delete_post( $multiple_kb_data['post']->ID, true );
$knowledge_base_term = get_term( $knowledge_base_id['term_id'], 'knowledge_base' );
}
foreach ( $multiple_kb_data['doc_category'] as $doc_category_id => $doc_category_data ) {
// Step 2: Insert posts as terms under 'doc_category' and set term meta
$doc_category_id = wp_insert_term( $doc_category_data['post']->post_title, 'doc_category' );
if ( ! is_wp_error( $doc_category_id ) ) {
$doc_category_term = get_term( $doc_category_id['term_id'], 'doc_category' );
wp_delete_post( $doc_category_data['post']->ID, true );
$doc_category_kb = rest_sanitize_array( array( $knowledge_base_term->slug ) );
// Set term meta for 'knowledge_base_doc_category'
update_term_meta( $doc_category_id['term_id'], 'doc_category_knowledge_base', $doc_category_kb );
}
foreach ( $doc_category_data['docs'] as $docs_id => $docs_data ) {
wp_set_post_terms( $docs_data['post']->ID, array( $knowledge_base_term->term_id ), 'knowledge_base' );
wp_set_post_terms( $docs_data['post']->ID, array( $doc_category_term->term_id ), 'doc_category' );
// // Step 3: Update posts to assign correct parent terms
// wp_update_post(array(
// 'ID' => $docs_data['post']->ID,
// 'post_parent' => 0,
// ));
}
}
}
}
/**
* Updates the 'betterdocs_migration' option with migrated knowledge base plugin names.
*
* This function checks if the option exists and is a serialized array. If the option exists,
* it unserializes the current value, merges it with the new values, serializes the merged array,
* and updates the option. If the option doesn't exist or is not a serialized array, it creates
* a new option with the serialized format.
*
* @param string $kb_name The name of the knowledge base to be added or updated.
*
* @return void
*/
public function update_option( $kb_name ) {
$existing_value = get_option( 'betterdocs_migration' );
$new_values = array( $kb_name );
if ( $existing_value !== false && is_serialized( $existing_value ) ) {
$existing_values_array = unserialize( $existing_value );
$merged_values = array_merge( $existing_values_array, $new_values );
update_option( 'betterdocs_migration', serialize( $merged_values ) );
} else {
update_option( 'betterdocs_migration', serialize( $new_values ) );
}
}
public function get_migrated_plugins() {
$existing_value = get_option( 'betterdocs_migration' );
if ( $existing_value ) {
return unserialize( $existing_value );
}
return [];
}
}