It's no doubt that having a strongly linked content schema helps you find the information you need, when you need it. But what happens when we attempt to (un)publish or delete interconnected resources?
Most CMSs are terrible at handling this sort of thing. Contentful for example simply leaves a ghost references to a records that no longer exists, and calls it a day. Their philosophy seems to be "users will take care of filtering this garbage somehow on the frontend, not our problem!".
What distinguishes us the most from competition is a greater care in keeping the saved contents coherent and always consistent. It is our problem to ensure that, not yours. You've better things to do.
Today, we're happy to introduce additional settings that allow you to specify exactly what behavior to adopt when such events occur. And since different settings may make sense depending on the specific context, you can specify different behaviours for every Link, Links and Structured Text in your project.
If you have ever worked with databases, you will surely notice a similarity with the DELETE CASCADE settings that you can set on the foreign keys of a table:
With this change, editors won't have to guess the right pattern to solve intricate cases of dependencies between records, since the developers have already taken care of that for them. And scheduled publish/unpublish operations will be much more secure and deterministic than before.
The default settings you'll find in the existing fields are the ones that were in place until now, so don't worry, nothing will change unless you decide to do so.
If you want to massively change these settings, you can conveniently do so via the Content Management API and migrations.
In this example, we're changing settings for every Link, Links and Structured field in a project, so that when a publishing is requested and a field references some unpublished records, the resolution strategy is to also publish the referenced records:
module.exports = async (client) => {const itemTypes = await client.itemTypes.all();for (const itemType of itemTypes) {const fields = await client.fields.all(itemType.id);const interestingFields = fields.filter((f) =>['link', 'links', 'structured_text'].includes(f.fieldType),);for (const field of interestingFields) {const validatorFor =field.fieldType === 'link'? 'itemItemType': field.fieldType === 'links'? 'itemsItemType': 'structuredTextLinks';if (field.validators[validatorFor].onPublishWithUnpublishedReferencesStrategy !== 'publish_references') {await client.fields.update(field.id, {validators: {...field.validators,[validatorFor]: {...field.validators[validatorFor],onPublishWithUnpublishedReferencesStrategy:'publish_references',},},});}}}};