| |
| <?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| defined( 'ABSPATH' ) || exit;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function kic_get_mu_plugins_dir() {
|
| return WPMU_PLUGIN_DIR;
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function kic_scan_mu_plugins() {
|
|
|
| if ( ! function_exists( 'get_mu_plugins' ) ) {
|
| require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
| }
|
|
|
| $mu_plugins_dir = kic_get_mu_plugins_dir();
|
| $plugins = array();
|
|
|
| if ( ! is_dir( $mu_plugins_dir ) ) {
|
| return $plugins;
|
| }
|
|
|
|
|
|
|
| $native_plugins = get_mu_plugins();
|
|
|
| foreach ( $native_plugins as $filename => $plugin_data ) {
|
| $file_path = trailingslashit( $mu_plugins_dir ) . $filename;
|
|
|
| $plugins[] = array(
|
| 'file' => $filename,
|
| 'path' => $file_path,
|
| 'basename' => basename( $filename, '.php' ),
|
| 'data' => $plugin_data,
|
| );
|
| }
|
|
|
| return $plugins;
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| if ( ! function_exists( 'kic_scan_mu_subfolders' ) ) {
|
| function kic_scan_mu_subfolders() {
|
| $mu_plugins_dir = kic_get_mu_plugins_dir();
|
| $subfolders = array();
|
|
|
| if ( ! is_dir( $mu_plugins_dir ) ) {
|
| return $subfolders;
|
| }
|
|
|
|
|
| $directories = glob( trailingslashit( $mu_plugins_dir ) . '*', GLOB_ONLYDIR );
|
|
|
| if ( empty( $directories ) ) {
|
| return $subfolders;
|
| }
|
|
|
| foreach ( $directories as $dir_path ) {
|
| $folder_name = basename( $dir_path );
|
|
|
|
|
| $php_files = glob( trailingslashit( $dir_path ) . '*.php' );
|
|
|
| if ( empty( $php_files ) ) {
|
| continue;
|
| }
|
|
|
| $files_data = array();
|
| foreach ( $php_files as $file_path ) {
|
| $files_data[] = array(
|
| 'path' => $file_path,
|
| 'filename' => basename( $file_path ),
|
| 'folder_name' => $folder_name,
|
| );
|
| }
|
|
|
| $subfolders[] = array(
|
| 'folder_name' => $folder_name,
|
| 'folder_path' => $dir_path,
|
| 'files' => $files_data,
|
| 'file_count' => count( $files_data ),
|
| );
|
| }
|
|
|
| return $subfolders;
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function kic_get_mu_plugin_data( $file_path ) {
|
| if ( ! file_exists( $file_path ) || ! is_readable( $file_path ) ) {
|
| return false;
|
| }
|
|
|
|
|
|
|
|
|
| $default_headers = array(
|
| 'Name' => 'Plugin Name',
|
| 'PluginURI' => 'Plugin URI',
|
| 'Version' => 'Version',
|
| 'Description' => 'Description',
|
| 'Author' => 'Author',
|
| 'AuthorURI' => 'Author URI',
|
| 'TextDomain' => 'Text Domain',
|
| 'DomainPath' => 'Domain Path',
|
| 'Network' => 'Network',
|
| 'RequiresWP' => 'Requires at least',
|
| 'RequiresPHP' => 'Requires PHP',
|
| );
|
|
|
| $plugin_data = get_file_data( $file_path, $default_headers, 'plugin' );
|
|
|
|
|
| if ( empty( $plugin_data['Name'] ) ) {
|
| $plugin_data['Name'] = basename( $file_path, '.php' );
|
| }
|
|
|
| return $plugin_data;
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function kic_sync_mu_plugin( $plugin_info ) {
|
| $file_path = $plugin_info['path'];
|
| $file_name = $plugin_info['file'];
|
|
|
|
|
| $plugin_data = isset( $plugin_info['data'] ) ? $plugin_info['data'] : kic_get_mu_plugin_data( $file_path );
|
|
|
| if ( ! $plugin_data ) {
|
| return false;
|
| }
|
|
|
|
|
|
|
|
|
| $code_content = file_get_contents( $file_path );
|
|
|
| if ( false === $code_content ) {
|
| return false;
|
| }
|
|
|
|
|
| $kic_id = 'mu_' . sanitize_key( $plugin_info['basename'] );
|
|
|
|
|
| $existing_sync_post = get_posts( array(
|
| 'post_type' => 'wpcode_snippets_sync',
|
| 'meta_key' => 'kic_snippet_id',
|
| 'meta_value' => $kic_id,
|
| 'posts_per_page' => 1,
|
| 'fields' => 'ids',
|
| 'no_found_rows' => true,
|
| ) );
|
|
|
| $sync_post_id = ! empty( $existing_sync_post ) ? $existing_sync_post[0] : 0;
|
|
|
|
|
| $sync_post_data = array(
|
| 'post_title' => sanitize_text_field( $plugin_data['Name'] ),
|
| 'post_type' => 'wpcode_snippets_sync',
|
| 'post_status' => 'publish',
|
| 'post_author' => get_current_user_id(),
|
| );
|
|
|
|
|
| if ( $sync_post_id ) {
|
| $sync_post_data['ID'] = $sync_post_id;
|
| $result = wp_update_post( $sync_post_data, true );
|
| } else {
|
| $result = wp_insert_post( $sync_post_data, true );
|
| }
|
|
|
| if ( is_wp_error( $result ) ) {
|
| return false;
|
| }
|
|
|
| $sync_post_id = $result;
|
|
|
|
|
|
|
|
|
|
|
|
|
| update_field( 'source_type', 'mu-plugin', $sync_post_id );
|
| update_field( 'file_path', $file_path, $sync_post_id );
|
|
|
|
|
| update_field( 'original_wpcode_id', '', $sync_post_id );
|
| update_field( 'kic_snippet_id', $kic_id, $sync_post_id );
|
| update_field( 'snippet_active', true, $sync_post_id );
|
|
|
|
|
| update_field( 'snippet_title', sanitize_text_field( $plugin_data['Name'] ), $sync_post_id );
|
| update_field( 'snippet_type', 'php', $sync_post_id );
|
| update_field( 'snippet_location', 'mu-plugins', $sync_post_id );
|
| update_field( 'snippet_priority', 0, $sync_post_id );
|
|
|
|
|
| update_field( 'snippet_code', $code_content, $sync_post_id );
|
|
|
|
|
| $attachment_id = kic_create_mu_plugin_file_attachment( $code_content, $plugin_data['Name'], $sync_post_id );
|
| if ( $attachment_id ) {
|
| update_field( 'snippet_code_file', $attachment_id, $sync_post_id );
|
| }
|
|
|
|
|
| update_field( 'snippet_description', sanitize_textarea_field( $plugin_data['Description'] ), $sync_post_id );
|
| update_field( 'snippet_version', sanitize_text_field( $plugin_data['Version'] ), $sync_post_id );
|
| update_field( 'snippet_author', sanitize_text_field( $plugin_data['Author'] ), $sync_post_id );
|
|
|
|
|
| $file_created = filectime( $file_path );
|
| $file_modified = filemtime( $file_path );
|
|
|
| update_field( 'snippet_created_date', $file_created ? gmdate( 'Y-m-d H:i:s', $file_created ) : '', $sync_post_id );
|
| update_field( 'snippet_modified_date', $file_modified ? gmdate( 'Y-m-d H:i:s', $file_modified ) : '', $sync_post_id );
|
|
|
|
|
| update_field( 'last_sync_time', current_time( 'mysql' ), $sync_post_id );
|
|
|
|
|
| $tags = array( 'mu-plugin' );
|
| if ( ! empty( $plugin_data['Version'] ) ) {
|
| $tags[] = 'v' . sanitize_text_field( $plugin_data['Version'] );
|
| }
|
| if ( ! empty( $plugin_data['RequiresPHP'] ) ) {
|
| $tags[] = 'php-' . sanitize_text_field( $plugin_data['RequiresPHP'] );
|
| }
|
| update_field( 'snippet_tags', implode( ', ', $tags ), $sync_post_id );
|
|
|
|
|
| $dependencies = array();
|
| if ( ! empty( $plugin_data['RequiresWP'] ) ) {
|
| $dependencies[] = 'WordPress ' . sanitize_text_field( $plugin_data['RequiresWP'] ) . '+';
|
| }
|
| if ( ! empty( $plugin_data['RequiresPHP'] ) ) {
|
| $dependencies[] = 'PHP ' . sanitize_text_field( $plugin_data['RequiresPHP'] ) . '+';
|
| }
|
| update_field( 'snippet_dependencies', implode( ', ', $dependencies ), $sync_post_id );
|
|
|
|
|
| update_field( 'snippet_auto_insert', false, $sync_post_id );
|
| update_field( 'snippet_device_type', 'all', $sync_post_id );
|
| update_field( 'snippet_schedule_start', '', $sync_post_id );
|
| update_field( 'snippet_schedule_end', '', $sync_post_id );
|
|
|
| return $sync_post_id;
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function kic_sync_subfolder_file( $file_info ) {
|
| $file_path = $file_info['path'];
|
| $filename = $file_info['filename'];
|
| $folder_name = $file_info['folder_name'];
|
|
|
|
|
| $mu_plugins_dir = kic_get_mu_plugins_dir();
|
| $real_path = realpath( $file_path );
|
| $real_mu_dir = realpath( $mu_plugins_dir );
|
|
|
| if ( ! $real_path || strpos( $real_path, $real_mu_dir ) !== 0 ) {
|
| return false;
|
| }
|
|
|
| if ( ! file_exists( $file_path ) || ! is_readable( $file_path ) ) {
|
| return false;
|
| }
|
|
|
|
|
| $plugin_data = kic_get_mu_plugin_data( $file_path );
|
|
|
|
|
| $code_content = file_get_contents( $file_path );
|
|
|
| if ( false === $code_content ) {
|
| return false;
|
| }
|
|
|
|
|
| $basename = basename( $filename, '.php' );
|
| $kic_id = 'mu_subfolder_' . sanitize_key( $folder_name ) . '_' . sanitize_key( $basename );
|
|
|
|
|
| $existing_sync_post = get_posts( array(
|
| 'post_type' => 'wpcode_snippets_sync',
|
| 'meta_key' => 'kic_snippet_id',
|
| 'meta_value' => $kic_id,
|
| 'posts_per_page' => 1,
|
| 'fields' => 'ids',
|
| 'no_found_rows' => true,
|
| ) );
|
|
|
| $sync_post_id = ! empty( $existing_sync_post ) ? $existing_sync_post[0] : 0;
|
|
|
|
|
| $title = ! empty( $plugin_data['Name'] ) && $plugin_data['Name'] !== $basename
|
| ? $plugin_data['Name']
|
| : $folder_name . '/' . $filename;
|
|
|
|
|
| $sync_post_data = array(
|
| 'post_title' => sanitize_text_field( $title ),
|
| 'post_type' => 'wpcode_snippets_sync',
|
| 'post_status' => 'publish',
|
| 'post_author' => get_current_user_id(),
|
| );
|
|
|
|
|
| if ( $sync_post_id ) {
|
| $sync_post_data['ID'] = $sync_post_id;
|
| $result = wp_update_post( $sync_post_data, true );
|
| } else {
|
| $result = wp_insert_post( $sync_post_data, true );
|
| }
|
|
|
| if ( is_wp_error( $result ) ) {
|
| return false;
|
| }
|
|
|
| $sync_post_id = $result;
|
|
|
|
|
|
|
|
|
|
|
|
|
| update_field( 'source_type', 'mu-plugin-subfolder', $sync_post_id );
|
| update_field( 'file_path', $file_path, $sync_post_id );
|
|
|
|
|
| update_field( 'original_wpcode_id', '', $sync_post_id );
|
| update_field( 'kic_snippet_id', $kic_id, $sync_post_id );
|
| update_field( 'snippet_active', true, $sync_post_id );
|
|
|
|
|
| update_field( 'snippet_title', sanitize_text_field( $title ), $sync_post_id );
|
| update_field( 'snippet_type', 'php', $sync_post_id );
|
| update_field( 'snippet_location', 'mu-plugins/' . $folder_name, $sync_post_id );
|
| update_field( 'snippet_priority', 0, $sync_post_id );
|
|
|
|
|
| update_field( 'snippet_code', $code_content, $sync_post_id );
|
|
|
|
|
| $attachment_id = kic_create_mu_plugin_file_attachment( $code_content, $folder_name . '-' . $basename, $sync_post_id );
|
| if ( $attachment_id ) {
|
| update_field( 'snippet_code_file', $attachment_id, $sync_post_id );
|
| }
|
|
|
|
|
| $description = ! empty( $plugin_data['Description'] ) ? $plugin_data['Description'] : 'Shortcode file from ' . $folder_name;
|
| update_field( 'snippet_description', sanitize_textarea_field( $description ), $sync_post_id );
|
| update_field( 'snippet_version', sanitize_text_field( $plugin_data['Version'] ?? '' ), $sync_post_id );
|
| update_field( 'snippet_author', sanitize_text_field( $plugin_data['Author'] ?? '' ), $sync_post_id );
|
|
|
|
|
| $file_created = filectime( $file_path );
|
| $file_modified = filemtime( $file_path );
|
|
|
| update_field( 'snippet_created_date', $file_created ? gmdate( 'Y-m-d H:i:s', $file_created ) : '', $sync_post_id );
|
| update_field( 'snippet_modified_date', $file_modified ? gmdate( 'Y-m-d H:i:s', $file_modified ) : '', $sync_post_id );
|
|
|
|
|
| update_field( 'last_sync_time', current_time( 'mysql' ), $sync_post_id );
|
|
|
|
|
| $tags = array( 'mu-plugin-subfolder', sanitize_key( $folder_name ) );
|
| update_field( 'snippet_tags', implode( ', ', $tags ), $sync_post_id );
|
|
|
|
|
| update_field( 'snippet_dependencies', '', $sync_post_id );
|
|
|
|
|
| update_field( 'snippet_auto_insert', false, $sync_post_id );
|
| update_field( 'snippet_device_type', 'all', $sync_post_id );
|
| update_field( 'snippet_schedule_start', '', $sync_post_id );
|
| update_field( 'snippet_schedule_end', '', $sync_post_id );
|
|
|
| return $sync_post_id;
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function kic_create_mu_plugin_file_attachment( $code_content, $plugin_name, $parent_id ) {
|
|
|
| $safe_name = sanitize_file_name( $plugin_name );
|
| if ( empty( $safe_name ) ) {
|
| $safe_name = 'mu-plugin-' . $parent_id;
|
| }
|
| $filename = $safe_name . '.txt';
|
|
|
|
|
| $upload_dir = wp_upload_dir();
|
| $subdir = 'wpcode-sync-files';
|
| $target_dir = trailingslashit( $upload_dir['basedir'] ) . $subdir;
|
|
|
|
|
| if ( ! file_exists( $target_dir ) ) {
|
| wp_mkdir_p( $target_dir );
|
| }
|
|
|
|
|
| $file_path = trailingslashit( $target_dir ) . wp_unique_filename( $target_dir, $filename );
|
|
|
|
|
|
|
| $bytes_written = file_put_contents( $file_path, $code_content );
|
|
|
| if ( false === $bytes_written ) {
|
| return false;
|
| }
|
|
|
|
|
| $file_type = wp_check_filetype( basename( $file_path ), null );
|
|
|
| $attachment = array(
|
| 'guid' => trailingslashit( $upload_dir['baseurl'] ) . $subdir . '/' . basename( $file_path ),
|
| 'post_mime_type' => $file_type['type'] ? $file_type['type'] : 'text/plain',
|
| 'post_title' => sanitize_file_name( basename( $file_path ) ),
|
| 'post_content' => '',
|
| 'post_status' => 'inherit',
|
| );
|
|
|
|
|
| $attachment_id = wp_insert_attachment( $attachment, $file_path, $parent_id );
|
|
|
| if ( is_wp_error( $attachment_id ) ) {
|
|
|
| wp_delete_file( $file_path );
|
| return false;
|
| }
|
|
|
|
|
| require_once ABSPATH . 'wp-admin/includes/image.php';
|
| $attach_data = wp_generate_attachment_metadata( $attachment_id, $file_path );
|
| wp_update_attachment_metadata( $attachment_id, $attach_data );
|
|
|
| return $attachment_id;
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
| function kic_sync_all_mu_plugins() {
|
| $mu_plugins = kic_scan_mu_plugins();
|
| $mu_subfolders = kic_scan_mu_subfolders();
|
|
|
| $synced_root = 0;
|
| $synced_subfolder = 0;
|
| $errors = array();
|
|
|
|
|
| foreach ( $mu_plugins as $plugin ) {
|
| $result = kic_sync_mu_plugin( $plugin );
|
|
|
| if ( $result ) {
|
| $synced_root++;
|
| } else {
|
| $errors[] = $plugin['file'];
|
| }
|
| }
|
|
|
|
|
| foreach ( $mu_subfolders as $folder ) {
|
| foreach ( $folder['files'] as $file_info ) {
|
| $result = kic_sync_subfolder_file( $file_info );
|
|
|
| if ( $result ) {
|
| $synced_subfolder++;
|
| } else {
|
| $errors[] = $folder['folder_name'] . '/' . $file_info['filename'];
|
| }
|
| }
|
| }
|
|
|
|
|
| kic_cleanup_deleted_mu_plugins( $mu_plugins, $mu_subfolders );
|
|
|
| $total = $synced_root + $synced_subfolder;
|
|
|
| return array(
|
| 'success' => true,
|
| 'message' => sprintf(
|
| 'Synced %d root MU-plugins + %d subfolder files (%d total).',
|
| $synced_root,
|
| $synced_subfolder,
|
| $total
|
| ),
|
| 'synced_root' => $synced_root,
|
| 'synced_subfolder' => $synced_subfolder,
|
| 'synced' => $total,
|
| 'errors' => $errors,
|
| );
|
| }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| function kic_cleanup_deleted_mu_plugins( $current_plugins, $mu_subfolders = array() ) {
|
|
|
| $current_ids = array();
|
| foreach ( $current_plugins as $plugin ) {
|
| $current_ids[] = 'mu_' . sanitize_key( $plugin['basename'] );
|
| }
|
|
|
|
|
| foreach ( $mu_subfolders as $folder ) {
|
| foreach ( $folder['files'] as $file_info ) {
|
| $basename = basename( $file_info['filename'], '.php' );
|
| $current_ids[] = 'mu_subfolder_' . sanitize_key( $folder['folder_name'] ) . '_' . sanitize_key( $basename );
|
| }
|
| }
|
|
|
|
|
| $sync_posts = get_posts( array(
|
| 'post_type' => 'wpcode_snippets_sync',
|
| 'posts_per_page' => -1,
|
| 'meta_query' => array(
|
| 'relation' => 'OR',
|
| array(
|
| 'key' => 'source_type',
|
| 'value' => 'mu-plugin',
|
| ),
|
| array(
|
| 'key' => 'source_type',
|
| 'value' => 'mu-plugin-subfolder',
|
| ),
|
| ),
|
| 'fields' => 'ids',
|
| 'no_found_rows' => true,
|
| ) );
|
|
|
| foreach ( $sync_posts as $sync_post_id ) {
|
| $kic_id = get_field( 'kic_snippet_id', $sync_post_id );
|
|
|
| if ( ! in_array( $kic_id, $current_ids, true ) ) {
|
|
|
| $code_file = get_field( 'snippet_code_file', $sync_post_id );
|
| if ( $code_file && is_array( $code_file ) && ! empty( $code_file['ID'] ) ) {
|
| wp_delete_attachment( $code_file['ID'], true );
|
| }
|
|
|
|
|
| wp_delete_post( $sync_post_id, true );
|
| }
|
| }
|
| }
|
|
|
|
|
|
|
|
|
|
|
| add_action( 'admin_notices', function() {
|
| $screen = get_current_screen();
|
|
|
|
|
| if ( ! $screen || 'edit-wpcode_snippets_sync' !== $screen->id ) {
|
| return;
|
| }
|
|
|
|
|
| if ( ! current_user_can( 'manage_options' ) ) {
|
| return;
|
| }
|
|
|
| $mu_plugins = kic_scan_mu_plugins();
|
| $mu_count = count( $mu_plugins );
|
|
|
|
|
| $mu_subfolders = kic_scan_mu_subfolders();
|
| $subfolder_count = count( $mu_subfolders );
|
| $subfolder_file_count = 0;
|
| foreach ( $mu_subfolders as $folder ) {
|
| $subfolder_file_count += $folder['file_count'];
|
| }
|
|
|
|
|
| $synced_mu = get_posts( array(
|
| 'post_type' => 'wpcode_snippets_sync',
|
| 'posts_per_page' => -1,
|
| 'meta_query' => array(
|
| array(
|
| 'key' => 'source_type',
|
| 'value' => 'mu-plugin',
|
| ),
|
| ),
|
| 'fields' => 'ids',
|
| 'no_found_rows' => true,
|
| ) );
|
| $synced_mu_count = count( $synced_mu );
|
|
|
|
|
| $synced_subfolder = get_posts( array(
|
| 'post_type' => 'wpcode_snippets_sync',
|
| 'posts_per_page' => -1,
|
| 'meta_query' => array(
|
| array(
|
| 'key' => 'source_type',
|
| 'value' => 'mu-plugin-subfolder',
|
| ),
|
| ),
|
| 'fields' => 'ids',
|
| 'no_found_rows' => true,
|
| ) );
|
| $synced_subfolder_count = count( $synced_subfolder );
|
|
|
|
|
| $synced_wpcode = get_posts( array(
|
| 'post_type' => 'wpcode_snippets_sync',
|
| 'posts_per_page' => -1,
|
| 'meta_query' => array(
|
| 'relation' => 'OR',
|
| array(
|
| 'key' => 'source_type',
|
| 'value' => 'wpcode',
|
| ),
|
| array(
|
| 'key' => 'source_type',
|
| 'compare' => 'NOT EXISTS',
|
| ),
|
| ),
|
| 'fields' => 'ids',
|
| 'no_found_rows' => true,
|
| ) );
|
| $synced_wpcode_count = count( $synced_wpcode );
|
|
|
| ?>
|
| <div class="kic-sync-controls" style="background: #fff; border: 1px solid #ccd0d4; border-left: 4px solid #2271b1; padding: 15px 20px; margin: 15px 0; box-shadow: 0 1px 1px rgba(0,0,0,.04);">
|
| <div style="display: flex; flex-wrap: wrap; gap: 30px; align-items: flex-start;">
|
|
|
| <!-- Stats Section -->
|
| <div style="flex: 1; min-width: 200px;">
|
| <h3 style="margin: 0 0 10px 0; font-size: 14px;">📊 Sync Status</h3>
|
| <table class="widefat striped" style="width: auto; min-width: 320px;">
|
| <tr>
|
| <td><strong>WPCode Snippets:</strong></td>
|
| <td><?php echo esc_html( $synced_wpcode_count ); ?> synced</td>
|
| </tr>
|
| <tr>
|
| <td><strong>MU-Plugins (root):</strong></td>
|
| <td><?php echo esc_html( $synced_mu_count ); ?> / <?php echo esc_html( $mu_count ); ?> synced</td>
|
| </tr>
|
| <tr>
|
| <td><strong>Subfolders:</strong></td>
|
| <td><?php echo esc_html( $synced_subfolder_count ); ?> / <?php echo esc_html( $subfolder_file_count ); ?> files (<?php echo esc_html( $subfolder_count ); ?> folders)</td>
|
| </tr>
|
| <tr>
|
| <td><strong>MU-Plugins Dir:</strong></td>
|
| <td><code style="font-size: 11px;"><?php echo esc_html( basename( kic_get_mu_plugins_dir() ) ); ?>/</code></td>
|
| </tr>
|
| </table>
|
| </div>
|
|
|
| <!-- MU-Plugins Sync Button -->
|
| <div style="flex: 0 0 auto;">
|
| <h3 style="margin: 0 0 10px 0; font-size: 14px;">🔌 MU-Plugins</h3>
|
| <form method="post" action="" style="margin: 0;">
|
| <?php wp_nonce_field( 'kic_sync_mu_plugins_action', 'kic_mu_nonce' ); ?>
|
| <button type="submit" name="kic_sync_mu_plugins" class="button button-primary">
|
| 🔄 Sync MU-Plugins Now
|
| </button>
|
| </form>
|
| <p style="margin: 8px 0 0 0; font-size: 12px; color: #666;">
|
| <?php echo esc_html( $mu_count ); ?> root + <?php echo esc_html( $subfolder_file_count ); ?> subfolder files
|
| </p>
|
| </div>
|
|
|
| <!-- WPCode Sync Button -->
|
| <div style="flex: 0 0 auto;">
|
| <h3 style="margin: 0 0 10px 0; font-size: 14px;">📝 WPCode Snippets</h3>
|
| <form method="post" action="" style="margin: 0;">
|
| <?php wp_nonce_field( 'kic_sync_wpcode_snippets_action', 'kic_wpcode_nonce' ); ?>
|
| <button type="submit" name="kic_sync_wpcode_snippets" class="button button-secondary">
|
| 🔄 Sync WPCode Now
|
| </button>
|
| </form>
|
| <?php
|
| $wpcode_total = wp_count_posts( 'wpcode' );
|
| $wpcode_source_count = isset( $wpcode_total->publish ) ? $wpcode_total->publish : 0;
|
| $wpcode_draft_count = isset( $wpcode_total->draft ) ? $wpcode_total->draft : 0;
|
| ?>
|
| <p style="margin: 8px 0 0 0; font-size: 12px; color: #666;">
|
| <?php echo esc_html( $wpcode_source_count ); ?> active + <?php echo esc_html( $wpcode_draft_count ); ?> inactive
|
| </p>
|
| </div>
|
|
|
| <!-- MU-Plugins List (Expandable) -->
|
| <?php if ( $mu_count > 0 || $subfolder_count > 0 ) : ?>
|
| <div style="flex: 1; min-width: 250px;">
|
| <?php if ( $mu_count > 0 ) : ?>
|
| <details style="margin-bottom: 10px;">
|
| <summary style="cursor: pointer; font-weight: bold; font-size: 14px; margin-bottom: 8px;">
|
| 📁 Root MU-Plugins (<?php echo esc_html( $mu_count ); ?>)
|
| </summary>
|
| <ul style="margin: 8px 0 0 15px; padding: 0; list-style: disc; font-size: 12px; max-height: 100px; overflow-y: auto;">
|
| <?php foreach ( $mu_plugins as $plugin ) :
|
| $data = isset( $plugin['data'] ) ? $plugin['data'] : kic_get_mu_plugin_data( $plugin['path'] );
|
| $name = ! empty( $data['Name'] ) ? $data['Name'] : $plugin['file'];
|
| ?>
|
| <li style="margin-bottom: 4px;">
|
| <strong><?php echo esc_html( $name ); ?></strong>
|
| <?php if ( ! empty( $data['Version'] ) ) : ?>
|
| <span style="color: #666;">(v<?php echo esc_html( $data['Version'] ); ?>)</span>
|
| <?php endif; ?>
|
| </li>
|
| <?php endforeach; ?>
|
| </ul>
|
| </details>
|
| <?php endif; ?>
|
|
|
| <?php if ( $subfolder_count > 0 ) : ?>
|
| <details>
|
| <summary style="cursor: pointer; font-weight: bold; font-size: 14px; margin-bottom: 8px;">
|
| 📂 Subfolders (<?php echo esc_html( $subfolder_count ); ?>)
|
| </summary>
|
| <ul style="margin: 8px 0 0 15px; padding: 0; list-style: disc; font-size: 12px; max-height: 100px; overflow-y: auto;">
|
| <?php foreach ( $mu_subfolders as $folder ) : ?>
|
| <li style="margin-bottom: 4px;">
|
| <strong><?php echo esc_html( $folder['folder_name'] ); ?>/</strong>
|
| <span style="color: #666;">(<?php echo esc_html( $folder['file_count'] ); ?> files)</span>
|
| </li>
|
| <?php endforeach; ?>
|
| </ul>
|
| </details>
|
| <?php endif; ?>
|
| </div>
|
| <?php endif; ?>
|
|
|
| </div>
|
|
|
| <p style="margin: 12px 0 0 0; font-size: 11px; color: #888;">
|
| 💡 <strong>Source Types:</strong>
|
| <code>wpcode</code> = WPCode snippets |
|
| <code>mu-plugin</code> = Root MU-plugins |
|
| <code>mu-plugin-subfolder</code> = Subfolder files
|
| </p>
|
| </div>
|
| <?php
|
| }, 5 ); // Priority 5 to show before other notices
|
|
|
| /**
|
| * Handle MU-Plugins sync form submission
|
| * BEST PRACTICE: Capability check BEFORE nonce verification (per WPCS/Patchstack)
|
| */
|
| add_action( 'admin_init', function() {
|
|
|
| if ( ! isset( $_POST['kic_sync_mu_plugins'] ) ) {
|
| return;
|
| }
|
|
|
|
|
| if ( ! current_user_can( 'manage_options' ) ) {
|
| wp_die(
|
| esc_html__( 'You do not have permission to sync MU-plugins.', 'kic-wpcode-sync' ),
|
| esc_html__( 'Permission Denied', 'kic-wpcode-sync' ),
|
| array( 'response' => 403 )
|
| );
|
| }
|
|
|
|
|
|
|
| if ( ! isset( $_POST['kic_mu_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['kic_mu_nonce'] ) ), 'kic_sync_mu_plugins_action' ) ) {
|
| wp_die(
|
| esc_html__( 'Security check failed. Please try again.', 'kic-wpcode-sync' ),
|
| esc_html__( 'Security Error', 'kic-wpcode-sync' ),
|
| array( 'response' => 403 )
|
| );
|
| }
|
|
|
|
|
| $result = kic_sync_all_mu_plugins();
|
|
|
|
|
| set_transient( 'kic_mu_sync_result', $result, 30 );
|
|
|
|
|
| $redirect_url = wp_get_referer();
|
| if ( ! $redirect_url ) {
|
| $redirect_url = admin_url( 'edit.php?post_type=wpcode_snippets_sync' );
|
| }
|
|
|
| wp_safe_redirect( add_query_arg( 'mu_synced', '1', $redirect_url ) );
|
| exit;
|
| } );
|
|
|
|
|
|
|
|
|
| add_action( 'admin_notices', function() {
|
|
|
| if ( ! isset( $_GET['mu_synced'] ) ) {
|
| return;
|
| }
|
|
|
|
|
| $screen = get_current_screen();
|
| if ( ! $screen || false === strpos( $screen->id, 'wpcode_snippets_sync' ) ) {
|
| return;
|
| }
|
|
|
| $result = get_transient( 'kic_mu_sync_result' );
|
| delete_transient( 'kic_mu_sync_result' );
|
|
|
| if ( ! $result ) {
|
| return;
|
| }
|
|
|
| $class = $result['success'] ? 'notice-success' : 'notice-error';
|
| ?>
|
| <div class="notice <?php echo esc_attr( $class ); ?> is-dismissible">
|
| <p><strong><?php esc_html_e( 'MU-Plugins Sync:', 'kic-wpcode-sync' ); ?></strong> <?php echo esc_html( $result['message'] ); ?></p>
|
| <?php if ( ! empty( $result['errors'] ) ) : ?>
|
| <p><?php esc_html_e( 'Failed:', 'kic-wpcode-sync' ); ?> <?php echo esc_html( implode( ', ', $result['errors'] ) ); ?></p>
|
| <?php endif; ?>
|
| </div>
|
| <?php
|
| } );
|
|
|
| /**
|
| * Handle WPCode sync form submission (from the control panel)
|
| * BEST PRACTICE: Capability check BEFORE nonce verification (per WPCS/Patchstack)
|
| */
|
| add_action( 'admin_init', function() {
|
|
|
| if ( ! isset( $_POST['kic_sync_wpcode_snippets'] ) ) {
|
| return;
|
| }
|
|
|
|
|
| if ( ! current_user_can( 'manage_options' ) ) {
|
| wp_die(
|
| esc_html__( 'You do not have permission to sync WPCode snippets.', 'kic-wpcode-sync' ),
|
| esc_html__( 'Permission Denied', 'kic-wpcode-sync' ),
|
| array( 'response' => 403 )
|
| );
|
| }
|
|
|
|
|
| if ( ! isset( $_POST['kic_wpcode_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['kic_wpcode_nonce'] ) ), 'kic_sync_wpcode_snippets_action' ) ) {
|
| wp_die(
|
| esc_html__( 'Security check failed. Please try again.', 'kic-wpcode-sync' ),
|
| esc_html__( 'Security Error', 'kic-wpcode-sync' ),
|
| array( 'response' => 403 )
|
| );
|
| }
|
|
|
|
|
| if ( ! function_exists( 'kic_sync_all_wpcode_snippets' ) ) {
|
| set_transient( 'kic_wpcode_sync_result', array(
|
| 'success' => false,
|
| 'message' => 'WPCode Sync Engine (AD_SYNC) not installed or inactive.',
|
| ), 30 );
|
|
|
| $redirect_url = wp_get_referer();
|
| if ( ! $redirect_url ) {
|
| $redirect_url = admin_url( 'edit.php?post_type=wpcode_snippets_sync' );
|
| }
|
| wp_safe_redirect( add_query_arg( 'wpcode_synced', '1', $redirect_url ) );
|
| exit;
|
| }
|
|
|
|
|
| $result = kic_sync_all_wpcode_snippets();
|
|
|
|
|
| set_transient( 'kic_wpcode_sync_result', $result, 30 );
|
|
|
|
|
| $redirect_url = wp_get_referer();
|
| if ( ! $redirect_url ) {
|
| $redirect_url = admin_url( 'edit.php?post_type=wpcode_snippets_sync' );
|
| }
|
|
|
| wp_safe_redirect( add_query_arg( 'wpcode_synced', '1', $redirect_url ) );
|
| exit;
|
| } );
|
|
|
|
|
|
|
|
|
| add_action( 'admin_notices', function() {
|
|
|
| if ( ! isset( $_GET['wpcode_synced'] ) ) {
|
| return;
|
| }
|
|
|
|
|
| $screen = get_current_screen();
|
| if ( ! $screen || false === strpos( $screen->id, 'wpcode_snippets_sync' ) ) {
|
| return;
|
| }
|
|
|
| $result = get_transient( 'kic_wpcode_sync_result' );
|
| delete_transient( 'kic_wpcode_sync_result' );
|
|
|
| if ( ! $result ) {
|
| return;
|
| }
|
|
|
| $class = $result['success'] ? 'notice-success' : 'notice-error';
|
| ?>
|
| <div class="notice <?php echo esc_attr( $class ); ?> is-dismissible">
|
| <p><strong><?php esc_html_e( 'WPCode Sync:', 'kic-wpcode-sync' ); ?></strong> <?php echo esc_html( $result['message'] ); ?></p>
|
| <?php if ( ! empty( $result['errors'] ) ) : ?>
|
| <p><?php esc_html_e( 'Failed:', 'kic-wpcode-sync' ); ?> <?php echo esc_html( implode( ', ', $result['errors'] ) ); ?></p>
|
| <?php endif; ?>
|
| </div>
|
| <?php
|
| } );
|
|
|
| /**
|
| * WP-CLI command for syncing MU-plugins
|
| *
|
| * ## EXAMPLES
|
| *
|
| * # Sync all MU-plugins (root + all subfolders)
|
| * wp kic sync-mu-plugins
|
| *
|
| * # Sync everything (WPCode + MU-plugins)
|
| * wp kic sync-all
|
| */
|
| if ( defined( 'WP_CLI' ) && WP_CLI ) {
|
|
|
| WP_CLI::add_command( 'kic sync-mu-plugins', function( $args, $assoc_args ) {
|
| WP_CLI::log( 'Starting MU-plugins sync (root + all subfolders)...' );
|
|
|
| $result = kic_sync_all_mu_plugins();
|
|
|
| if ( $result['success'] ) {
|
| WP_CLI::success( $result['message'] );
|
| if ( ! empty( $result['errors'] ) ) {
|
| WP_CLI::warning( 'Some files failed to sync: ' . implode( ', ', $result['errors'] ) );
|
| }
|
| } else {
|
| WP_CLI::error( $result['message'] );
|
| }
|
| } );
|
|
|
|
|
| WP_CLI::add_command( 'kic sync-all', function( $args, $assoc_args ) {
|
| WP_CLI::log( 'Starting full sync (WPCode + MU-plugins + all subfolders)...' );
|
|
|
|
|
| if ( function_exists( 'kic_sync_all_wpcode_snippets' ) ) {
|
| WP_CLI::log( 'Syncing WPCode snippets...' );
|
| $wpcode_result = kic_sync_all_wpcode_snippets();
|
| WP_CLI::log( $wpcode_result['message'] );
|
| } else {
|
| WP_CLI::warning( 'WPCode sync function not found. Skipping WPCode sync.' );
|
| }
|
|
|
|
|
| WP_CLI::log( 'Syncing MU-plugins + all subfolders...' );
|
| $mu_result = kic_sync_all_mu_plugins();
|
| WP_CLI::log( $mu_result['message'] );
|
|
|
| WP_CLI::success( 'Full sync complete!' );
|
| } );
|
| }
|
| |
| |
Comments