From aa5d34717ed9983e61e756bcc709a5480db298f2 Mon Sep 17 00:00:00 2001 From: Mischa Date: Sat, 4 Jul 2026 23:31:25 +0200 Subject: [PATCH] =?UTF-8?q?feat(post-form):=20U1=20=E2=80=94=20shared=20cr?= =?UTF-8?q?eate/edit=20form=20+=20published=20field=20+=20owner=5Fusername?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit One /post form now drives both create and edit (KTD1, Alt B): cache-on-save toggles add-page-by-form's overwrite_mode per submit — 'edit' when the new hidden edit_path field is filled (write back in place, stable URL), 'false' when empty (fresh dated folder via slug_field). add-page-by-form stays stock (no fork); the toggle lives in cache-on-save, which reads edit_path and mutates the /post page header's pageconfig before add-page-by-form's onFormProcessed runs. - post-form.md: overwrite_mode:false (create-safe fallback), hidden edit_path, authoritative published toggle (default on), removed the static pagefrontmatter.published so the field wins on every submit (KTD3). - cache-on-save.php: editPathFromForm + setOverwriteMode helpers. - site.yaml: owner_username (single source of truth for the KTD8 owner gate). Verified against the 2.0.4 container: create writes a fresh dated folder with published:true/false as a real boolean (V1, V2); edit writes in place with the slug/URL unchanged; save-as-draft-on-create works. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01H1FrCYNq6RXdGYbn5PFrhM --- config/site.yaml | 5 ++++ pages/02.post/post-form.md | 35 +++++++++++++++++++++- plugins/cache-on-save/cache-on-save.php | 40 +++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/config/site.yaml b/config/site.yaml index 87f0f32..380f465 100644 --- a/config/site.yaml +++ b/config/site.yaml @@ -7,3 +7,8 @@ metadata: description: 'A travel blog by Mischa' active_trip: /trips/us-canada-mex-2024 travelling: false +# Single source of truth for the site owner's account username. Backs both the +# front-end edit/delete UI gate and the server-side scope guards (KTD8): only +# this user (not merely any authenticated/super-admin account) may edit, delete, +# or see drafts on the active trip's feed. +owner_username: mischa diff --git a/pages/02.post/post-form.md b/pages/02.post/post-form.md index 2badda5..f5a55fb 100644 --- a/pages/02.post/post-form.md +++ b/pages/02.post/post-form.md @@ -6,13 +6,21 @@ access: # Parent (write target) is injected server-side from site.active_trip by the # cache-on-save plugin (onFormValidationProcessed) — no manual sync needed. +# +# overwrite_mode is toggled per submit by cache-on-save (KTD1, Alt B): edit when +# the hidden edit_path field is filled (write back in place), false when empty +# (create a fresh dated folder via slug_field). The static value here is the +# create-safe fallback for if cache-on-save doesn't run — add-page-by-form stays +# stock (no fork), so a static `edit` would break create (empty edit_path -> '.'). pageconfig: slug_field: 'date,title' overwrite_mode: false +# published is NOT a static pagefrontmatter default anymore — it is an +# authoritative form field (below) so every submit (create AND edit) writes the +# owner's chosen publish state. Only `template` stays static here. pagefrontmatter: template: entry - published: true form: name: new-entry @@ -129,11 +137,36 @@ form: 'car': '🚗 Car' 'plane': '✈️ Plane' + # Hidden edit target. Empty on create (add-page-by-form falls through to + # slug_field and writes a fresh dated folder); on edit, post-form.js sets + # it to the entry's path so overwrite_mode:edit writes back in place. + - + name: edit_path + type: hidden + default: '' + # Advanced fields — collapsed behind "More options" (see U5). # No hero_image field: journal entries render their hero from the first # uploaded photo (entry-journal.html.twig uses entry.media.images|first), # so an explicit hero filename was redundant. Stories still use hero_image # but they aren't posted through this form. + - + name: published + label: Published + # Authoritative publish state (replaces the removed static + # pagefrontmatter.published). Default ON so new entries publish; the + # owner flips it OFF to save/keep a draft, or to unpublish on edit. + # validate.type:bool keeps it a real boolean in frontmatter (not '0'). + type: toggle + classes: advanced-field + highlight: 1 + default: 1 + options: + 1: 'Yes' + 0: 'No' + validate: + type: bool + - name: force_connect label: Force connector line diff --git a/plugins/cache-on-save/cache-on-save.php b/plugins/cache-on-save/cache-on-save.php index 75b5cf0..743a8cf 100644 --- a/plugins/cache-on-save/cache-on-save.php +++ b/plugins/cache-on-save/cache-on-save.php @@ -48,6 +48,46 @@ class CacheOnSavePlugin extends Plugin } $form->setData('parent', $this->resolveDailiesParent($activeTrip)); + + // One shared /post form drives both create and edit (KTD1). add-page-by-form + // reads overwrite_mode from the /post page header's pageconfig (not form + // data), so we toggle it here per submit: + // - edit (edit_path present) -> overwrite_mode:edit, writes back in place + // - create (edit_path empty) -> overwrite_mode:false, so stock falls + // through to slug_field (date,title) and writes a fresh dated folder. + // This keeps add-page-by-form stock (no fork), since a static + // overwrite_mode:edit would break create (empty edit_path slugs to '.'). + $editPath = $this->editPathFromForm($form); + $this->setOverwriteMode($editPath === '' ? 'false' : 'edit'); + } + + /** + * The hidden edit_path form field, trimmed. Empty string when creating a new + * entry; the entry's `/entry.md` path when editing (set by post-form.js). + */ + private function editPathFromForm($form): string + { + $value = $form->value('edit_path'); + return is_string($value) ? trim($value) : ''; + } + + /** + * Override add-page-by-form's overwrite_mode by mutating the current (/post) + * page header's pageconfig. add-page-by-form reads + * `$grav['page']->header()->pageconfig['overwrite_mode']` (add-page-by-form.php + * :385) from the same page singleton, and Page::header() returns a cached + * instance, so this write is visible when its onFormProcessed runs afterwards. + */ + private function setOverwriteMode(string $mode): void + { + $page = $this->grav['page'] ?? null; + if (!$page) { + return; + } + $header = $page->header(); + $pageconfig = (isset($header->pageconfig) && is_array($header->pageconfig)) ? $header->pageconfig : []; + $pageconfig['overwrite_mode'] = $mode; + $header->pageconfig = $pageconfig; } /**