This adds a whole-site Site scan, moves publishing into the content editor, adds subfolder-install support and fixes a handful of data-handling bugs. Only the cms/ directory is changed (18 files: 12 modified, 6 new). Everything was developed and tested on XAMPP/Windows against a real multi-page site.
Added
Site scan (Tools > Site scan, administrators only). Analyses every managed page and the media library: page and folder counts, pages that can be made editable, images without alt text, broken local image/CSS/script references, unused uploads and missing title/description/Open Graph tags.
One click makes pages editable: it tags <main> (or top-level <article> / text-bearing <section>), skipping header/nav/footer/aside/forms and never <body>; marks images and photo placeholders outside editable regions; and inserts only missing SEO tags (existing ones are never overwritten).
Edits are spliced into the page source byte-for-byte (no DOM re-serialisation), a revision is kept for every changed page, and later scans list only pages that still need changes.
Runs in small batches with a progress bar and an "N of M pages" count. New administrator-only actions: listSitePages, analyseSitePages, applySiteTagging.
Click-to-edit images and photo placeholders (role="img" boxes): opens an image dialog with a Media Library picker and alt text.
Subfolder installs (e.g. http://localhost/site/): URL prefix and site root are auto-detected (basePath / siteRoot); root installs behave exactly as before.
Audit coverage: cancelled schedules, image uploads, alt-text changes and failed scheduled publications now appear in the Dashboard feed and the daily audit log (shared Activity class).
Snackbar (success/error) and table-style dialogs for the page picker, revisions, dashboard, shared content, menus and site scan.
Changed
Editor actions are now Save Draft | Schedule Publish | Publish Now | Cancel; saving in the editor (and applying image/SEO changes) stores a private draft. The toolbar no longer has Save Draft/Schedule/Publish.
CMSController split into PagePaths, ContentDom and Activity; entry points share cms/bootstrap.php. Restoring a deleted page uses PageNotFoundException instead of matching an error message.
Fixed
Lost updates on JSON metadata (locked FileStore::update); non-atomic site-wide shared-content/menu writes; non-ASCII text handling.
Scheduled publishing contending for a lock on every request.
Revision pruning could drop the newest revision (revisions gain a ts).
Stale cached pages in the editor preview after a site is replaced.
Saved drafts reloading without stylesheets or the right page path, and Publish discarding a draft that wasn't re-offered in the same session.
HTML entities in page titles; backslashes in folder names on Windows.
Migration
No manual steps. basePath/siteRoot are optional and auto-detected. The analyseSite action was replaced by listSitePages and analyseSitePages.
Testing
The original tests/run.php passes against these changes (apart from its Linux-only permission assertions when run on Windows).
Additional tests (not included here, to keep this PR to cms/) cover concurrency, tagging, batching and audit-log behaviour; happy to add them if you'd like.
Exercised manually in the browser: scan/tag/re-scan, click-to-edit images, draft save/reload/publish, scheduling and cancelling, upload/alt-text logging.
## Summary
This adds a whole-site **Site scan**, moves publishing into the content editor, adds subfolder-install support and fixes a handful of data-handling bugs. Only the `cms/` directory is changed (18 files: 12 modified, 6 new). Everything was developed and tested on XAMPP/Windows against a real multi-page site.
## Added
- **Site scan** (Tools > Site scan, administrators only). Analyses every managed page and the media library: page and folder counts, pages that can be made editable, images without alt text, broken local image/CSS/script references, unused uploads and missing title/description/Open Graph tags.
- One click makes pages editable: it tags `<main>` (or top-level `<article>` / text-bearing `<section>`), skipping header/nav/footer/aside/forms and never `<body>`; marks images and photo placeholders outside editable regions; and inserts only *missing* SEO tags (existing ones are never overwritten).
- Edits are spliced into the page source byte-for-byte (no DOM re-serialisation), a revision is kept for every changed page, and later scans list only pages that still need changes.
- Runs in small batches with a progress bar and an "N of M pages" count. New administrator-only actions: `listSitePages`, `analyseSitePages`, `applySiteTagging`.
- **Click-to-edit images and photo placeholders** (`role="img"` boxes): opens an image dialog with a Media Library picker and alt text.
- **Subfolder installs** (e.g. `http://localhost/site/`): URL prefix and site root are auto-detected (`basePath` / `siteRoot`); root installs behave exactly as before.
- **Audit coverage**: cancelled schedules, image uploads, alt-text changes and failed scheduled publications now appear in the Dashboard feed and the daily audit log (shared `Activity` class).
- Snackbar (success/error) and table-style dialogs for the page picker, revisions, dashboard, shared content, menus and site scan.
## Changed
- Editor actions are now **Save Draft | Schedule Publish | Publish Now | Cancel**; saving in the editor (and applying image/SEO changes) stores a private draft. The toolbar no longer has Save Draft/Schedule/Publish.
- `CMSController` split into `PagePaths`, `ContentDom` and `Activity`; entry points share `cms/bootstrap.php`. Restoring a deleted page uses `PageNotFoundException` instead of matching an error message.
## Fixed
- Lost updates on JSON metadata (locked `FileStore::update`); non-atomic site-wide shared-content/menu writes; non-ASCII text handling.
- Scheduled publishing contending for a lock on every request.
- Revision pruning could drop the newest revision (revisions gain a `ts`).
- Stale cached pages in the editor preview after a site is replaced.
- Saved drafts reloading without stylesheets or the right page path, and Publish discarding a draft that wasn't re-offered in the same session.
- HTML entities in page titles; backslashes in folder names on Windows.
## Migration
No manual steps. `basePath`/`siteRoot` are optional and auto-detected. The `analyseSite` action was replaced by `listSitePages` and `analyseSitePages`.
## Testing
- The original `tests/run.php` passes against these changes (apart from its Linux-only permission assertions when run on Windows).
- Additional tests (not included here, to keep this PR to `cms/`) cover concurrency, tagging, batching and audit-log behaviour; happy to add them if you'd like.
- Exercised manually in the browser: scan/tag/re-scan, click-to-edit images, draft save/reload/publish, scheduling and cancelling, upload/alt-text logging.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
This adds a whole-site Site scan, moves publishing into the content editor, adds subfolder-install support and fixes a handful of data-handling bugs. Only the
cms/directory is changed (18 files: 12 modified, 6 new). Everything was developed and tested on XAMPP/Windows against a real multi-page site.Added
<main>(or top-level<article>/ text-bearing<section>), skipping header/nav/footer/aside/forms and never<body>; marks images and photo placeholders outside editable regions; and inserts only missing SEO tags (existing ones are never overwritten).listSitePages,analyseSitePages,applySiteTagging.role="img"boxes): opens an image dialog with a Media Library picker and alt text.http://localhost/site/): URL prefix and site root are auto-detected (basePath/siteRoot); root installs behave exactly as before.Activityclass).Changed
CMSControllersplit intoPagePaths,ContentDomandActivity; entry points sharecms/bootstrap.php. Restoring a deleted page usesPageNotFoundExceptioninstead of matching an error message.Fixed
FileStore::update); non-atomic site-wide shared-content/menu writes; non-ASCII text handling.ts).Migration
No manual steps.
basePath/siteRootare optional and auto-detected. TheanalyseSiteaction was replaced bylistSitePagesandanalyseSitePages.Testing
tests/run.phppasses against these changes (apart from its Linux-only permission assertions when run on Windows).cms/) cover concurrency, tagging, batching and audit-log behaviour; happy to add them if you'd like.🤖 Generated with Claude Code