diff --git a/CHANGELOG.md b/CHANGELOG.md index 35c1246..df462e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,42 @@ Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) — versi --- +## [3.4.2] — 2026-05-27 + +### Fixed — Restore actually works now (v3.4.1 was incomplete) + +David retested after v3.4.1 and reported the same symptom: *"the restore still not working."* + +Root cause (the real one): the per-row Restore form in `inc/wp-notes-display.php` sends a hidden `$_POST['note_id']` (singular) when the button is clicked — but the handler in `wp_notes_page_callback()` was checking for `$_POST['done_ids']` (plural), an array of IDs that used to come from bulk-action checkboxes **removed in v3.1.0**. So the handler's `isset($_POST['done_ids'])` guard was always false, the handler body never ran, and clicking Restore was a no-op all the way back to v3.1.0. The bug was masked before v3.4.0 because the page re-rendered with both Active and Completed sections visible, so the user could see the (unchanged) completed note still sitting there and assume they'd misclicked. v3.4.0's single-pane render made the no-op symptom unmissable. + +The v3.4.1 redirect added inside the handler was syntactically correct but never reached — the entire `if` block was dead code. + +Fix: rewrite the handler to match the working **single-note** mark-done handler pattern that lives just above it: + +- Check `isset($_POST['note_id'])` (singular) instead of `done_ids` (plural array) +- `absint()` the ID for sanitization +- `isset($done_notes[$note_id])` lookup instead of iterating with `in_array()` +- Move the note across with the existing `restored_by` annotation +- Keep the redirect-to-Active-tab from v3.4.1 + +The handler now mirrors the pattern of the mark-done handler that's been working all along. + +### Why this took two attempts to fix + +v3.4.1's diagnosis stopped at the missing redirect — which was real but not load-bearing because the handler body was unreachable. Lesson recorded: when a handler appears to "do nothing", verify it's being entered at all (matching `$_POST` keys) before assuming the issue is downstream (missing redirect, failed update, etc.). + +### Files changed + +- `wp-notes.php` — Restore handler rewritten (lines around 1340). The change replaces the old bulk-checkbox-era handler with a single-note handler matching the live form. Adds a load-bearing comment block recording the v3.4.1/v3.4.2 bug history so future-Claude understands why the structure mirrors mark-done. +- Plugin header `Version: 3.4.1 → 3.4.2`; `WP_NOTES_VERSION` constant updated to match. PATCH bump (bug fix). + +### Not changed + +- The display code in `inc/wp-notes-display.php` — the form was already correct; the handler was the one out of sync. +- The Active and Completed tabs, storage model, CSS, other handlers — all unchanged. + +--- + ## [3.4.1] — 2026-05-27 ### Fixed — Restore button now sends you to the Active tab where the restored note lives diff --git a/wp-notes.php b/wp-notes.php index 8f55c1e..2e3a15b 100644 --- a/wp-notes.php +++ b/wp-notes.php @@ -5,7 +5,7 @@ * Plugin Name: Logbook * Plugin URI: https://icanhelp.ie/wp-notes * Description: A lightweight task & logbook plugin for WordPress. Log your daily work, mark tasks done, and keep a tidy record inside the dashboard. Perfect for freelancers showing clients what's been delivered and students proving work to teachers. - * Version: 3.4.1 + * Version: 3.4.2 * Requires at least: 5.0 * Requires PHP: 7.2 * Author: IR240474 @@ -33,7 +33,7 @@ if (!isset($wp_notes_init)) { $wp_notes_init = true; // Plugin Constants - if (!defined('WP_NOTES_VERSION')) define('WP_NOTES_VERSION', '3.4.1'); + if (!defined('WP_NOTES_VERSION')) define('WP_NOTES_VERSION', '3.4.2'); if (!defined('WP_NOTES_FILE')) define('WP_NOTES_FILE', __FILE__); if (!defined('WP_NOTES_PATH')) define('WP_NOTES_PATH', plugin_dir_path(__FILE__)); if (!defined('WP_NOTES_URL')) define('WP_NOTES_URL', plugin_dir_url(__FILE__)); @@ -1336,37 +1336,44 @@ function wp_notes_handle_actions() { exit; } - // Handle restore note action - if (isset($_POST['restore_note']) && isset($_POST['done_ids'])) { + // Handle restore note action (per-row form on the Completed tab). + // + // v3.4.2 fix: this handler used to expect $_POST['done_ids'] — an + // array of IDs from bulk-action checkboxes that were removed in + // v3.1.0. The per-row Restore form in inc/wp-notes-display.php + // sends a hidden $_POST['note_id'] (singular) instead, so the old + // handler's isset($_POST['done_ids']) check was always false and + // the handler body never executed. Clicking Restore therefore + // looked like it did nothing — David's "the complete log does not + // return to active." The v3.4.1 redirect added below was correct + // but never reached because the handler was already dead code. + // + // Rewritten to match the working mark-done single-note handler + // pattern: expect note_id (singular), absint() it, isset() lookup + // in $done_notes, move with the restored_by annotation, then + // redirect to the Active tab where the restored note now lives. + if (isset($_POST['restore_note']) && isset($_POST['note_id'])) { $notes = get_option('wp_notes', array()); $done_notes = get_option('wp_done_notes', array()); + $note_id = absint($_POST['note_id']); $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; - } + if (isset($done_notes[$note_id])) { + $note = $done_notes[$note_id]; + $note['last_modified'] = current_time('mysql'); + $note['restored_by'] = $current_user->display_name; + $notes[] = $note; + unset($done_notes[$note_id]); + + update_option('wp_notes', $notes); + update_option('wp_done_notes', $done_notes); + + // Redirect to the Active tab — without this, the page falls + // through and re-renders with the URL's current ?tab=completed, + // so the restored note (now on Active) would be invisible. + wp_redirect(admin_url('admin.php?page=wp-notes')); + exit; } - - update_option('wp_notes', $notes); - update_option('wp_done_notes', $new_done_notes); - - // v3.4.1 fix: redirect to the Active tab so the restored note is - // visible in its new home. Without this redirect, the page falls - // through and re-renders with the URL's current ?tab=completed, - // so the user sees Completed (minus the now-restored note) and - // can't see the restored note on Active. The other action - // handlers above (new note, mark-as-done single, mark-as-done - // bulk) all redirect; restore was the odd one out. Pre-v3.4.0 - // this was masked because both sections rendered on the same - // page — the v3.4.0 single-pane tab render exposed it. - wp_redirect(admin_url('admin.php?page=wp-notes')); - exit; } // Handle edit note action