v0.31.10.0 — Critical Module Deletion Fix
·
22 commits
to master
since this release
This release ships a critical data-loss fix in the module uninstall pipeline along with sitemap correctness fixes, CSRF token-sync repairs, and several frontend cleanups. All ci4ms deployments should upgrade — prior versions would wipe the entire database when uninstalling a single module due to a misuse of CodeIgniter 4's MigrationRunner::regress() API.
⚠️ Critical
- Single Module Deletion Wiped Entire Database.
ModuleInstaller::rollbackModuleMigrations()calledMigrationRunner::regress(0)aftersetNamespace(), expecting namespace-scoped rollback. CI4'sregress()nulls$this->namespaceinternally and walks the full migration history, so uninstalling any module would down every registered module's migrations and drop the entire database. The rollback path now iterates only the target module's namespace history and callsforce()per migration in reverse order, with afinallyblock that resets the shared runner singleton.
🛠️ Fixed
- Sitemap URL Duplication.
BlogModelandPagesModelsitemap entries returned fully-qualified URLs viasite_url()whileci4seopro\SitemapBuilderprependsbaseUrl, producing malformed<loc>https://hosthttps://host/...</loc>values. Models now return path-onlylocvalues, matching the package contract. - Sitemap Multilingual Coverage. Both sitemap models now
LEFT JOINtheir*_langstables so localized records are included instead of being filtered out by the primary-table-only query. - Backend CSRF Hidden Input Stale.
setCsrfHash()now syncs everycsrf_field()hidden input on the page after token regeneration; non-AJAX form submissions following an AJAX request no longer hit403 Forbidden. - Backend CSRF Empty-Body POSTs.
ajaxPrefilterwrites a pre-encoded URL string for empty POST bodies instead of building an object that jQuery would later re-serialize back to empty, stripping the token from the request. - Frontend Captcha Auto-Fire.
captchaF()no longer issues aPOST /commentCaptchaon every public page load; the bootstrap is now gated on the presence of.captchamarkup. - Methods Update View — Broken Route. Back-to-list link now resolves to the correct
methodListroute alias (waslist, which does not exist). - Methods Update View — Checkbox Active State.
inNavigation,isBackoffice, andhasChildflags now render correctly checked for existing records; added(bool)casts to compare integer storage (1/0) against strict boolean equality.
♻️ Changed
- elFinder Dialog Reuse.
pageImgelfinderDialog()andpageMultipleImgelfinderDialog()cache and reopen their existing jQuery wrapper instead of rebuilding the dialog on every invocation. Eliminates leaked event handlers, redundantcssAutoLoadHTTP requests, and the per-secondsyncexception when polling a destroyed instance (now wrapped intry/catch). - Captcha Refresh Trigger. Refresh button migrated from inline
onclick="captchaF()"to a.captcha-refreshclass bound via the existing delegated handler insidecaptchaF()— cleaner markup/behavior separation.
➕ Added
.gitignoreEntries.CLAUDE.mdandci4ms-specs/are now excluded so per-developer agent tooling artifacts stay out of version control.
⬆️ Upgrade Notes
- Pull the new release; no schema migration is required for the framework itself.
- Run
php spark cache:clearafter deploying so the cached settings, menu, and permission entries pick up the newapp.version. - The
app.versionvalue in your existing.envis not rewritten automatically — bump it to0.31.10.0manually if you rely on that key (the installer andci4ms:setupCLI command already use the new value for fresh installations). - Before uninstalling any module on a pre-0.31.10.0 deployment, take a full database backup — the legacy code path is destructive. After upgrading, module uninstall is safe and properly scoped.
- If you maintain a fork or downstream module pipeline that touched
MigrationRunner::regress(0), audit it for the same antipattern — the framework method does not honorsetNamespace().
Full changelog: 0.31.9.0...0.31.10.0