New in Craft CMS 5.10
Craft 5.10 came out yesterday. The headline is a deletion workflow that stops you before you break something, and it turns out Craft has had one of these for years without anyone noticing.
Deletion blockers
Delete an element in the control panel, and you may now get a modal listing everything that stands in the way. Relations first: if other entries point at the thing you're deleting, you see them, and you can either swap the relation to a different element or remove it. Once the blockers are cleared, the deletion goes through.
The CKEditor plugin registers a blocker for elements referenced inside CKEditor fields. Commerce 5.7 registers blockers for users with orders or subscriptions.
What makes this more than a warning dialog is what got deprecated alongside it. DeleteUsers, `User::$inheritorOnDelete`, `DefineUserContentSummaryEvent`, and `Craft.DeleteUserModal` are all on the way out. Craft has had this behavior for a decade, but only for users: delete somebody and you get asked what happens to their entries. 5.10 takes that idea, generalizes it into `DeletionBlockerInterface`, and opens it to every element type and every plugin.
That's the pattern I keep seeing in this version line. Something that worked in one corner of the system gets pulled up a level and made general. Matrix blocks became entries. The Title became a field layout element. Now the user deletion prompt becomes a deletion framework.
Relations and deletion
I've had a vague sense for a while that relations and soft deletes are where Craft is least sure of itself. Going back through the changelogs, that's not just a feeling.
5.4 fixed hard-deleting an element without hard-deleting its nested elements, and made it possible to hard-delete nested elements from embedded index views at all. 5.5 fixed restoring a soft-deleted element bringing back nested elements that had been deleted deliberately, and entries soft-deleted along with their section not coming back when the section was restored. 5.7 fixed `getOwner()` and `getPrimaryOwner()` returning wrong results for nested elements queried alongside elements with a different owner type. And 5.10 fixes nested content being updated unexpectedly or deleted after successive edits, plus relation field query params ignoring the query's target sites.
None of these are the same bug. They're the same area: what happens to the things attached to a thing when that thing changes state.
The deletion blockers address the moment before deletion, which is the visible half. The underlying bookkeeping has required a fix in most releases since 5.4. Worth knowing if you've ever had a client report content that came back from the dead, or didn't.
Matrix field actions, revised
In January I wrote about 5.9's bulk actions: select blocks in a Matrix field, then expand, collapse, copy, duplicate, or delete them.
5.10 takes half of that back. Matrix fields no longer have field-level Duplicate and Delete actions. Expand, Collapse, and Copy now always affect every nested entry regardless of what's selected. Element-level actions, meanwhile, now apply to the whole selection when you trigger one from a block that's part of it.
The distinction is between acting on the field and acting on a selection, and 5.9 blurred it. If you selected three blocks and hit a field-level Delete, what did you expect to happen? I'm not sure I knew either. Four months to work that out and reverse it is fast.
There's also a new "Paste above" action in Matrix and Addresses fields, and Addresses fields get a "Copy all addresses" field-level action.
Time zones
There's now a Time Zone user preference, and control panel timestamps include the time zone abbreviation. The `|time` and `|datetime` Twig filters take a `withTimeZone argument.`
Anyone running a single-country project can skip this. Anyone with editors in two places has watched somebody schedule a post for the wrong afternoon.
Alt text from file metadata
Assets uploaded with descriptive text in their metadata now get their Alternative Text field populated automatically.
This depends entirely on the images arriving with the metadata intact, which in my experience means agency photography sometimes and everything else never. But in cases where a photographer or a stock library has done the work, that text used to die somewhere between the shoot and the CMS. Now it arrives.
Min Authors
Sections get a "Min Authors" setting.
Craft 5.0 allowed multiple authors per entry with a Max Authors setting. 5.7 made Max Authors optional for unlimited, and allowed 0 to hide the Author field entirely. 5.10 closes the other end.
Replacing a field in a layout
You can now change which custom field an existing field layout element points to, and component chips have "Replace" actions.
This is a small thing with a specific history. Craft 5 introduced field instances, so the same field can appear several times under different names. That made it much easier to end up with a layout element pointing at the wrong field, and until now the fix was to remove it and add the right one, losing the instance's name, instructions, and conditions in the process.
Further down
Entry post dates are no longer set automatically on creation; they're set when an entry is first saved as enabled. `postDate` is `null` until then, instead of matching `dateCreated`. Check your templates if you've been relying on that.
Twig is at 3.24, which brings null-safe operators. There are new `heading()` and `h1()` through `h6()` Twig functions. Text condition rules get "does not equal", "is one of", and "is not one of"; numeric rules get the last two. GraphQL delete queries take a `hardDelete` argument. And there's `SecFetchSiteFilter` for origin verification, offered as a more modern alternative to CSRF tokens.
Element slideouts now refresh when the same element is edited in another tab. Another gap between slideouts and full edit pages, closed.
The release also fixes three security vulnerabilities: a high-severity remote code execution, plus JavaScript injection and path traversal at moderate severity.
Craft 6 is running alongside
Craft 6.0.0-alpha.2 shipped the same day with everything in 5.10.
I won't be testing it. I ran the Craft 5 beta on a live project and would do that again, but an alpha is a different proposition: the interface isn't settled, and I'd be reporting bugs about things that are going to change anyway. Beta is where my feedback is worth something, and my risk is calculable. Until then I'd rather read about it.
Which does raise the question of how much 5.x is left. Craft 6 is slated for the last quarter of the year, which makes a point release this substantial in May either a sign that the 5 line still has room, or the last big one before everything moves across.
Check the full changelog for everything not covered here.