run(); } } // Hook into WordPress init add_action('plugins_loaded', 'wp_notes_init', 10); // Register activation and deactivation hooks register_activation_hook(__FILE__, 'wp_notes_activate'); register_deactivation_hook(__FILE__, 'wp_notes_deactivate'); /** * Plugin activation handler */ function wp_notes_activate() { // Ensure PHP version is compatible if (version_compare(PHP_VERSION, '7.2', '<')) { deactivate_plugins(basename(__FILE__)); wp_die('This plugin requires PHP version 7.2 or higher.'); } // Initialize plugin settings add_option('wp_notes_version', WP_NOTES_VERSION); // Create database tables wp_notes_create_tables(); // Backup existing notes $existing_notes = get_option('wp_notes', array()); $existing_done_notes = get_option('wp_done_notes', array()); if (!empty($existing_notes)) { update_option('wp_notes_backup', $existing_notes); } if (!empty($existing_done_notes)) { update_option('wp_done_notes_backup', $existing_done_notes); } } /** * Plugin deactivation handler */ function wp_notes_deactivate() { delete_option('wp_notes_version'); } /** * Create required database tables */ function wp_notes_create_tables() { global $wpdb; require_once(ABSPATH . 'wp-admin/includes/upgrade.php'); $charset_collate = $wpdb->get_charset_collate(); $sql = array(); // Notes table $sql[] = "CREATE TABLE IF NOT EXISTS {$wpdb->prefix}wp_notes ( id bigint(20) NOT NULL AUTO_INCREMENT, user_id bigint(20) NOT NULL, note_content text NOT NULL, note_status varchar(20) NOT NULL DEFAULT 'active', created_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY user_id (user_id), KEY note_status (note_status) ) $charset_collate;"; foreach ($sql as $query) { dbDelta($query); } } // Initialize plugin add_action('plugins_loaded', 'wp_notes_init'); // Set text domain for translations function wp_notes_load_textdomain() { load_plugin_textdomain('a-wp-notes', false, dirname(plugin_basename(__FILE__)) . '/languages'); } add_action('plugins_loaded', 'wp_notes_load_textdomain'); // Include required files if (defined('WP_NOTES_PATH')) { require_once WP_NOTES_PATH . 'inc/admin-bar.php'; require_once WP_NOTES_PATH . 'inc/wp-notes-about.php'; require_once WP_NOTES_PATH . 'inc/wp-notes-feedback.php'; require_once WP_NOTES_PATH . 'inc/wp-notes-display.php'; require_once WP_NOTES_PATH . 'inc/wp-notes-styles.php'; } // Admin Menu function wp_notes_admin_menu() { add_menu_page( 'WP Notes', 'WP Notes', 'manage_options', 'wp-notes', 'wp_notes_page_callback', 'dashicons-admin-generic', 3 ); // Add "Create WP Note" to the Admin Bar menu add_submenu_page( 'wp-notes', // Page title 'Create WP Note', // Menu title 'Create WP Note', 'manage_options', // Capability required to see this item 'wp-notes', // Menu slug 'wp_notes_create_page' // Function to display the page content ); // Settings submenu add_submenu_page( 'wp-notes', 'Settings', 'Settings', 'manage_options', 'wp-notes-settings', 'wp_notes_settings_page' ); // Import/Export submenu add_submenu_page( 'wp-notes', 'Import/Export', 'Import/Export', 'manage_options', 'wp-notes-import-export', 'wp_notes_import_export_page' ); // About WP Notes submenu add_submenu_page( 'wp-notes', 'About WP Notes', 'About WP Notes', 'manage_options', 'wp-notes-about', 'wp_notes_about_page' // Callback for About WP Notes page in wp-notes-about.php ); // Register settings with validation callback register_setting( 'wp_notes_settings', 'wp_notes_settings', array( 'sanitize_callback' => 'wp_notes_validate_settings', 'default' => array( 'default_font' => 'Arial', 'default_size' => '16' ) ) ); add_settings_section( 'wp_notes_main_section', 'General Settings', 'wp_notes_section_callback', 'wp-notes-settings' ); add_settings_field( 'wp_notes_default_font', 'Default Font', 'wp_notes_font_callback', 'wp-notes-settings', 'wp_notes_main_section' ); add_settings_field( 'wp_notes_default_size', 'Default Size', 'wp_notes_size_callback', 'wp-notes-settings', 'wp_notes_main_section' ); } // Settings validation callback function wp_notes_validate_settings($input) { $output = array(); // Validate font $allowed_fonts = ['Arial', 'Helvetica', 'Times New Roman', 'Verdana']; $output['default_font'] = in_array($input['default_font'], $allowed_fonts) ? $input['default_font'] : 'Arial'; // Validate size (8-72px) $size = absint($input['default_size']); $output['default_size'] = ($size >= 8 && $size <= 72) ? $size : 16; add_settings_error( 'wp_notes_settings', 'settings_updated', 'Settings saved successfully.', 'updated' ); return $output; } // Settings page callback function wp_notes_settings_page() { // Show any settings messages settings_errors('wp_notes_settings'); ?>

WP Notes Settings

Configure default settings for WP Notes.

'; } // Font setting callback function wp_notes_font_callback() { $options = get_option('wp_notes_settings'); $current = $options['default_font'] ?? 'Arial'; ?> Font size in pixels (8-72) getMessage()), 'error' ); } } // Get current settings for display $options = get_option('wp_notes_settings'); ?>

Import/Export Notes

Export Notes

Download your notes as JSON or CSV file.

Import Notes

Import notes from JSON or CSV file.

$notes, 'completed_notes' => $done_notes, 'export_date' => current_time('mysql') ); if ($format === 'json') { header('Content-Type: application/json'); header('Content-Disposition: attachment; filename=wp-notes-export-' . date('Y-m-d') . '.json'); echo wp_json_encode($data, JSON_PRETTY_PRINT); } else { header('Content-Type: text/csv'); header('Content-Disposition: attachment; filename=wp-notes-export-' . date('Y-m-d') . '.csv'); $output = fopen('php://output', 'w'); fputcsv($output, array('Type', 'Text', 'Created By', 'Created On', 'Status')); foreach ($notes as $note) { fputcsv($output, array( 'active', $note['text'], $note['author_name'] ?? 'Unknown', $note['timestamp'] ?? '', 'Active' )); } foreach ($done_notes as $note) { fputcsv($output, array( 'completed', $note['text'], $note['author_name'] ?? 'Unknown', $note['timestamp'] ?? '', 'Completed' )); } fclose($output); } exit; } // Import functionality function wp_notes_import_data() { if (!isset($_POST['import_nonce']) || !wp_verify_nonce($_POST['import_nonce'], 'wp_notes_import')) { wp_die('Security check failed'); } $file = $_FILES['import_file']; $ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION)); if ($ext === 'json') { $content = file_get_contents($file['tmp_name']); $data = json_decode($content, true); if (json_last_error() === JSON_ERROR_NONE) { if (isset($data['active_notes'])) { update_option('wp_notes', $data['active_notes']); } if (isset($data['completed_notes'])) { update_option('wp_done_notes', $data['completed_notes']); } add_settings_error('wp_notes_import', 'import_success', 'Notes imported successfully', 'updated'); } else { add_settings_error('wp_notes_import', 'import_error', 'Invalid JSON file'); } } elseif ($ext === 'csv') { $handle = fopen($file['tmp_name'], 'r'); $headers = fgetcsv($handle); $notes = array(); $done_notes = array(); while (($data = fgetcsv($handle)) !== false) { $note = array( 'text' => $data[1], 'author_name' => $data[2], 'timestamp' => $data[3], 'color' => '#000000', 'size' => '16', 'font' => 'Arial' ); if ($data[0] === 'active') { $notes[] = $note; } else { $done_notes[] = $note; } } fclose($handle); update_option('wp_notes', $notes); update_option('wp_done_notes', $done_notes); add_settings_error('wp_notes_import', 'import_success', 'Notes imported successfully', 'updated'); } else { add_settings_error('wp_notes_import', 'import_error', 'Invalid file format. Please use JSON or CSV files.'); } } add_action('admin_menu', 'wp_notes_admin_menu'); // Add "Create WP Note" to the Tools menu 29th Oct 2024. function wp_notes_add_tools_menu() { add_management_page( 'Create WP Note', // Page title 'Create WP Note', // Menu title 'manage_options', // Capability required to see this item 'wp-notes-create', // Menu slug 'wp_notes_create_page' // Function to display the page content ); } add_action('admin_menu', 'wp_notes_add_tools_menu'); // Enqueue Scripts function wp_notes_enqueue_scripts() { // wp_enqueue_script('wp-notes-activity-tracker', WP_NOTES_URL . 'js/wp-notes-activity.js', ['jquery'], null, true); // Activity tracking removed 2025-05-09 wp_enqueue_script('wp-notes-feedback', WP_NOTES_URL . 'js/wp-notes-feedback.js', ['jquery'], null, true); wp_localize_script('wp-notes-feedback', 'wp_notes_feedback_vars', array( 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('wp_notes_feedback_nonce') )); } add_action('admin_enqueue_scripts', 'wp_notes_enqueue_scripts'); // Emoji picker initialization add_action('admin_footer', 'wp_notes_emoji_picker_init'); function wp_notes_emoji_picker_init() { ?>

Create a New WP Note









jQuery(document).ready(function($) { // Show edit form $('.edit-note').on('click', function(e) { e.preventDefault(); var noteId = $(this).data('note-id'); $('#edit-note-' + noteId).toggle(); }); // AJAX submit the edit form $('.edit-note-form').on('submit', function(e) { e.preventDefault(); var noteId = $(this).data('note-id'); var formData = $(this).serialize() + '&action=wp_notes_save_edit¬e_id=' + noteId; $.post(ajaxurl, formData, function(response) { if (response.success) { alert('Note updated successfully!'); location.reload(); // Reload to display updated notes } else { alert('Error updating note: ' + response.data); } }); }); }); "; } // Handle saving edited notes add_action('wp_ajax_wp_notes_save_edit', 'wp_notes_save_edit'); function wp_notes_save_edit() { // Security checks if (!current_user_can('edit_posts')) { wp_send_json_error('Insufficient permissions.'); return; } // Security check using nonce check_ajax_referer('wp_notes_nonce', '_wpnonce'); // Validate required fields $required_fields = ['note_id', 'new_text', 'edit_color', 'edit_size', 'edit_font']; foreach ($required_fields as $field) { if (!isset($_POST[$field])) { wp_send_json_error("Missing required field: $field"); return; } } // Get and sanitize data $note_id = absint($_POST['note_id']); $new_text = sanitize_text_field($_POST['new_text']); $new_color = sanitize_hex_color($_POST['edit_color']); $new_size = absint($_POST['edit_size']); // Validate font against allowed list $allowed_fonts = ['Arial', 'Helvetica', 'Times New Roman', 'Verdana']; $new_font = in_array($_POST['edit_font'], $allowed_fonts) ? $_POST['edit_font'] : 'Arial'; // Validate size range if ($new_size < 8 || $new_size > 72) { wp_send_json_error('Font size must be between 8 and 72 pixels.'); return; } $notes = get_option('wp_notes', array()); if (!isset($notes[$note_id])) { wp_send_json_error('Note not found.'); return; } // Update note with validation $notes[$note_id] = array_merge($notes[$note_id], [ 'text' => $new_text, 'color' => $new_color ?: '#000000', 'size' => $new_size, 'font' => $new_font, 'modified_timestamp' => current_time('mysql'), 'modified_by' => get_current_user_id() ]); if (!update_option('wp_notes', $notes)) { wp_send_json_error('Failed to update note.'); return; } wp_send_json_success([ 'message' => 'Note updated successfully', 'note' => $notes[$note_id] ]); } /** * Main WP Notes Page - Central hub for note management */ function wp_notes_page_callback() { if (!current_user_can('edit_posts')) { wp_die(__('You do not have sufficient permissions to access this page.', 'a-wp-notes')); } $notes = get_option('wp_notes', array()); $done_notes = get_option('wp_done_notes', array()); $total_notes = count($notes); $total_done = count($done_notes); // Get user settings $settings = get_option('wp_notes_settings', array( 'default_font' => 'Arial', 'default_size' => '16' )); ?>

Welcome to WP Notes

Version

About WP Notes

Thank you for using WP Notes! This plugin helps you manage your WordPress tasks and notes efficiently. Keep track of your todos, mark them as complete, and export your data for safekeeping.

I made this plugin for my website to log my daily tasks and notes as a logbook for my clients, so they can see the work done by me or you and get clear value for their investment.

Add New Note

Note Formatting Options

Notes Todo List:

' . esc_html__('No notes found.', 'a-wp-notes') . '

'; return; } echo ''; foreach ($notes as $key => $note) { $text = esc_html($note['text']); $color = esc_attr($note['color'] ?? '#000000'); $size = esc_attr($note['size'] ?? '14'); $font = esc_attr($note['font'] ?? 'Arial'); $timestamp = esc_html($note['timestamp'] ?? current_time('mysql')); $author = esc_html($note['author_name'] ?? 'Unknown'); echo ""; } echo '
Note Created By Created On Actions
$text $author $timestamp
'; // JavaScript for form toggling and AJAX submissions ?> ' . esc_html__('No completed notes.', 'a-wp-notes') . '

'; return; } echo '
'; foreach ($done_notes as $key => $note) { echo ''; } echo '
Note Created By Created On Completed By Completed On Last Modified Actions
' . esc_html($note['text']) . ' ' . esc_html($note['author_name'] ?? 'Unknown') . ' ' . esc_html($note['timestamp'] ?? 'Unknown') . ' ' . esc_html($note['completed_by'] ?? 'Unknown') . ' ' . esc_html($note['completed_on'] ?? 'Unknown') . ' ' . esc_html($note['last_modified'] ?? 'N/A') . '
'; // Add JavaScript for select all functionality ?> sanitize_text_field($_POST['wp_notes_text']), 'color' => sanitize_hex_color($_POST['wp_notes_color']) ?: '#000000', 'size' => absint($_POST['wp_notes_size']) ?: 16, 'font' => sanitize_text_field($_POST['wp_notes_font']) ?: 'Arial', 'timestamp' => current_time('mysql'), 'author' => $current_user->ID, 'author_name' => $current_user->display_name ); $notes[] = $new_note; update_option('wp_notes', $notes); wp_redirect(admin_url('admin.php?page=wp-notes')); exit; } // Handle "Mark as Done" submissions if (isset($_POST['mark_done']) && isset($_POST['note_id'])) { $notes = get_option('wp_notes', array()); $done_notes = get_option('wp_done_notes', array()); $note_id = absint($_POST['note_id']); if (isset($notes[$note_id])) { $note = $notes[$note_id]; $note['completed_by'] = $current_user->display_name; $note['completed_on'] = current_time('mysql'); $done_notes[] = $note; unset($notes[$note_id]); update_option('wp_notes', $notes); update_option('wp_done_notes', $done_notes); wp_redirect(admin_url('admin.php?page=wp-notes')); exit; } } // Handle marking notes as done if 'mark_done' action is triggered if (isset($_POST['mark_done']) && isset($_POST['note_ids'])) { $notes = get_option('wp_notes', array()); $done_notes = get_option('wp_done_notes', array()); // Move selected notes to done list foreach ($notes as $key => $note) { if (in_array($key, $_POST['note_ids'])) { $note['completed_by'] = $current_user->display_name; $note['completed_on'] = current_time('mysql'); $done_notes[] = $note; unset($notes[$key]); // Remove from active notes } } // Update both lists in the database update_option('wp_notes', $notes); update_option('wp_done_notes', $done_notes); // Redirect to avoid form resubmission wp_redirect(admin_url('admin.php?page=wp-notes')); exit; } // Handle restore note action if (isset($_POST['restore_note']) && isset($_POST['done_ids'])) { $notes = get_option('wp_notes', array()); $done_notes = get_option('wp_done_notes', array()); $current_user = wp_get_current_user(); $new_done_notes = array(); foreach ($done_notes as $key => $note) { if (in_array($key, $_POST['done_ids'])) { $note['last_modified'] = current_time('mysql'); $note['restored_by'] = $current_user->display_name; $notes[] = $note; } else { $new_done_notes[] = $note; } } update_option('wp_notes', $notes); update_option('wp_done_notes', $new_done_notes); } // Handle edit note action if (isset($_POST['edit_note']) && isset($_POST['note_ids'])) { // Add edit functionality here $notes = get_option('wp_notes', array()); $current_user = wp_get_current_user(); foreach ($_POST['note_ids'] as $key) { if (isset($notes[$key])) { $notes[$key]['last_modified'] = current_time('mysql'); $notes[$key]['modified_by'] = $current_user->display_name; } } update_option('wp_notes', $notes); } } // AJAX handler for editing a note add_action('wp_ajax_wp_notes_edit_note', 'wp_notes_edit_note'); function wp_notes_edit_note() { if (!isset($_POST['note_id']) || !isset($_POST['edit_text'])) { wp_send_json_error('Invalid request'); return; } $note_id = absint($_POST['note_id']); $new_text = sanitize_text_field($_POST['edit_text']); $new_color = sanitize_hex_color($_POST['edit_color']); $new_size = absint($_POST['edit_size']); $new_font = sanitize_text_field($_POST['edit_font']); $notes = get_option('wp_notes', array()); if (isset($notes[$note_id])) { $notes[$note_id]['text'] = $new_text; $notes[$note_id]['color'] = $new_color; $notes[$note_id]['size'] = $new_size; $notes[$note_id]['font'] = $new_font; update_option('wp_notes', $notes); wp_send_json_success(); } else { wp_send_json_error('Note not found.'); } } // Optimize the restore function for performance function wp_notes_restore($note_id) { $done_notes = get_option('wp_done_notes', array()); $notes = get_option('wp_notes', array()); if (isset($done_notes[$note_id])) { $notes[$note_id] = $done_notes[$note_id]; unset($done_notes[$note_id]); update_option('wp_notes', $notes); update_option('wp_done_notes', $done_notes); wp_redirect(admin_url('admin.php?page=wp-notes')); } } // Dashboard widget function wp_notes_dashboard_widget() { wp_notes_list_table(); } function wp_notes_add_dashboard_widgets() { wp_add_dashboard_widget( 'wp_notes_dashboard_widget', 'WP Notes', 'wp_notes_dashboard_widget' ); } add_action('wp_dashboard_setup', 'wp_notes_add_dashboard_widgets'); // Register Custom Post Type for notes function wp_notes_register_cpt() { $labels = array( 'name' => __('Notes', 'a-wp-notes'), 'singular_name' => __('Note', 'a-wp-notes'), 'menu_name' => __('WP Notes', 'a-wp-notes'), 'add_new' => __('Add New', 'a-wp-notes'), 'add_new_item' => __('Add New Note', 'a-wp-notes'), 'edit_item' => __('Edit Note', 'a-wp-notes'), 'new_item' => __('New Note', 'a-wp-notes'), 'view_item' => __('View Note', 'a-wp-notes'), 'search_items' => __('Search Notes', 'a-wp-notes'), 'not_found' => __('No notes found', 'a-wp-notes'), 'not_found_in_trash'=> __('No notes found in trash', 'a-wp-notes'), ); $args = array( 'labels' => $labels, 'public' => false, // show_ui=false: the live UI stores notes in wp_options, not as // CPT posts. show_ui=true caused WordPress to auto-inject "All // Notes" and "Add New" submenus that pointed at post-new.php and // routed users into the standard post editor — which writes to // the wrong storage. The CPT remains registered so the // wp_notes_migrate_to_cpt() helper can still use wp_insert_post. 'show_ui' => false, 'show_in_menu' => false, 'capability_type' => 'post', 'hierarchical' => false, 'supports' => array('title', 'editor', 'author', 'custom-fields'), 'has_archive' => false, 'menu_position' => null, 'show_in_rest' => false, ); register_post_type('wp_note', $args); // Register taxonomy for note categories $tax_labels = array( 'name' => __('Note Categories', 'a-wp-notes'), 'singular_name' => __('Note Category', 'a-wp-notes'), 'search_items' => __('Search Categories', 'a-wp-notes'), 'all_items' => __('All Categories', 'a-wp-notes'), 'parent_item' => __('Parent Category', 'a-wp-notes'), 'parent_item_colon' => __('Parent Category:', 'a-wp-notes'), 'edit_item' => __('Edit Category', 'a-wp-notes'), 'update_item' => __('Update Category', 'a-wp-notes'), 'add_new_item' => __('Add New Category', 'a-wp-notes'), 'new_item_name' => __('New Category Name', 'a-wp-notes'), 'menu_name' => __('Categories', 'a-wp-notes'), ); register_taxonomy('wp_note_category', 'wp_note', array( 'hierarchical' => true, 'labels' => $tax_labels, // Hidden alongside the parent CPT — live UI doesn't surface // categories yet, and showing the taxonomy in admin with the // parent hidden would just dead-link. 'show_ui' => false, 'show_admin_column' => false, 'query_var' => true, 'show_in_rest' => false, )); } add_action('init', 'wp_notes_register_cpt'); // Add custom meta box for note properties function wp_notes_add_meta_boxes() { add_meta_box( 'wp_notes_properties', __('Note Properties', 'a-wp-notes'), 'wp_notes_render_properties_meta_box', 'wp_note', 'side', 'high' ); } add_action('add_meta_boxes', 'wp_notes_add_meta_boxes'); // Render meta box content function wp_notes_render_properties_meta_box($post) { // Add nonce for security wp_nonce_field('wp_notes_meta_box', 'wp_notes_meta_box_nonce'); // Get current values $color = get_post_meta($post->ID, '_wp_note_color', true) ?: '#000000'; $size = get_post_meta($post->ID, '_wp_note_size', true) ?: '16'; $font = get_post_meta($post->ID, '_wp_note_font', true) ?: 'Arial'; $status = get_post_meta($post->ID, '_wp_note_status', true) ?: 'active'; ?>





'sanitize_hex_color', '_wp_note_size' => 'absint', '_wp_note_font' => 'sanitize_text_field', '_wp_note_status' => 'sanitize_text_field' ); foreach ($fields as $key => $sanitize_callback) { if (isset($_POST[str_replace('_', '', $key)])) { $value = call_user_func($sanitize_callback, $_POST[str_replace('_', '', $key)]); update_post_meta($post_id, $key, $value); } } } add_action('save_post_wp_note', 'wp_notes_save_meta_box_data'); // Data Migration Tool function wp_notes_migrate_to_cpt() { $existing_notes = get_option('wp_notes', array()); $done_notes = get_option('wp_done_notes', array()); $migrated_count = 0; $errors = array(); // Start migration foreach ($existing_notes as $note) { $post_data = array( 'post_title' => wp_trim_words($note['text'], 10, '...'), 'post_content' => $note['text'], 'post_status' => 'publish', 'post_type' => 'wp_note', 'post_author' => $note['author'] ?? get_current_user_id(), ); // Insert the post $post_id = wp_insert_post($post_data, true); if (!is_wp_error($post_id)) { // Add note meta data update_post_meta($post_id, '_wp_note_color', $note['color'] ?? '#000000'); update_post_meta($post_id, '_wp_note_size', $note['size'] ?? '16'); update_post_meta($post_id, '_wp_note_font', $note['font'] ?? 'Arial'); update_post_meta($post_id, '_wp_note_status', 'active'); update_post_meta($post_id, '_wp_note_created', $note['timestamp'] ?? ''); update_post_meta($post_id, '_wp_note_author_name', $note['author_name'] ?? ''); $migrated_count++; } else { $errors[] = $post_id->get_error_message(); } } // Migrate completed notes foreach ($done_notes as $note) { $post_data = array( 'post_title' => wp_trim_words($note['text'], 10, '...'), 'post_content' => $note['text'], 'post_status' => 'publish', 'post_type' => 'wp_note', 'post_author' => $note['author'] ?? get_current_user_id(), ); $post_id = wp_insert_post($post_data, true); if (!is_wp_error($post_id)) { update_post_meta($post_id, '_wp_note_color', $note['color'] ?? '#000000'); update_post_meta($post_id, '_wp_note_size', $note['size'] ?? '16'); update_post_meta($post_id, '_wp_note_font', $note['font'] ?? 'Arial'); update_post_meta($post_id, '_wp_note_status', 'completed'); update_post_meta($post_id, '_wp_note_created', $note['timestamp'] ?? ''); update_post_meta($post_id, '_wp_note_completed_by', $note['completed_by'] ?? ''); update_post_meta($post_id, '_wp_note_completed_on', $note['completed_on'] ?? ''); update_post_meta($post_id, '_wp_note_author_name', $note['author_name'] ?? ''); $migrated_count++; } else { $errors[] = $post_id->get_error_message(); } } // Create backup of old data update_option('wp_notes_pre_migration_backup', array( 'notes' => $existing_notes, 'done_notes' => $done_notes, 'migration_date' => current_time('mysql') )); return array( 'success' => true, 'migrated_count' => $migrated_count, 'errors' => $errors ); } // Add migration notice for admin function wp_notes_migration_notice() { if (!current_user_can('manage_options')) { return; } $migrated = get_option('wp_notes_migration_completed'); if (!$migrated) { ?>