Lee RowlandsSenior Developer
We could add default content to Drupal core, but what would that mean?
There has been some movement of late around adding some default content to the standard profile.
This was originally reignited by Roy Scholten in his getting something in the box post.
As author and co-maintainer of the default content module for Drupal 8, I wanted to share my thoughts on the potential of adding it to Drupal core.
The Snowman initiative is not a new one. And no-one would dispute that the 'You haven't got any content' message you see as soon as you install Drupal is a fairly ordinary first experience.
So it makes sense to try and improve that experience by adding some sample content.
We've been talking about it for ten years (yes that is a 5 digit issue number).
However it's not as simple as 'adding default content module to core as an experimental module' and away we go.
Default content is great insofar as it doesn't rely on any modules other than those provided by core.
But it's a two-edged sword.
It works by looking for default content in the form of json files inside a module's folder structure. These files live in content/{entity type} inside the module.
This content is stored in hal+json format as output by core's Rest and HAL modules.
The content is imported during hook_modules_installed which fires when a module is installed, but before its configuration is imported.
Issue 1
This is one of the first hard problems. Adding default content to standard profile would mean that none of the profile's configuration would have been imported yet. Which would result in exceptions/partial imports. You cannot import content into the page content type if it does not exist.
Profiles that make use of default content do things a little differently.
They put their configuration in a module which the profile depends on.
They put their default content in another module, which depends on the configuration module. For an example, see how aGov does it.
That way the install order happens like this:
- The configuration module is enabled and all the content types and fields etc are created
- The default content module is enabled, creating the content as required. An option to disable this can be added to the installer screen steps, since not everyone wants to start with default content.
- The install profile is enabled. It is always enabled last - this is non-negotiable.
This isn't how the current standard profile is structured - so there is considerable work to be done to reorganize how the configuration is structured.
Issue 2
The second issue here is that the default content module relies on the Rest, HAL and serialization modules in core. The HAL module provides the hal+json format. The Rest module provides the link managers that allow reverse resolving of embedded links to entity types and fields. The serialization module provides the serializer service which handles normalizing entities to arrays and then serializing them to a given format - in this case hal+json.
The issue is that you shouldn't need to enable these three modules just to import default content. If your site isn't providing an API in the form of Rest endpoints, you shouldn't need to have them available just to install default content. Those who build Drupal sites for a living normally steer clear of enabling modules they don't need. Comment module in standard profile is a good example of something that core enables by default but many sites don't use. Its the same issue here.
To resolve this, we need to do a lot of shuffling.
There is a valid argument that the serialization module is critical to core's functionality and hence should be disolved into the \Drupal\Core namespace instead of \Drupal\serialization. Being able to turn our data objects such as entities, field item lists and field items into arrays and back is a genuine core piece of Drupal functionality. We should support this in the low-level plumbing. Particularly for things like the MapItem typed data type. Using PHPs built in serialize/unserialize to convert our objects to and from arrays is a bad idea - just ask the PHP maintainers - this functionality was added to support user sessions and was never meant to be used the way it is.
So bringing serialization services into core resolves one of the three dependencies. The issue for that is here.
The next dependency is the HAL module. The key piece of functionality it provides is the embedding of entity references in the body of the serialized entities during normalizing. For example, if you normalize a node, you also get a reference to the author embedded - with the link done by UUID so it can be de-referenced. The large parts of default content module are concerned with sorting this dependency tree so that content is imported in the right order, with the dependencies intact. This is probably the easiest bit to swap out - and support for this has existed in the serialization module since Drupal 8.1.x - Default content module hasn't been updated to support it yet - because we don't want to break people's existing exports.
This leaves the Rest module as the final dependency. The main pieces it provides are the link manager services that allow generating canonical links to referenced/embedded entities and then de-referencing these into entity type, field name and bundle information during denormalizing. E.g. When you normalize a node, the author reference is stored using a URI that contains information about the entity type, the bundle and the field name. During denormalizing (which happens on content import) this information can be extrapolated so things end up in the right place. Fortunately we have an issue to move these out of the Rest module.
Issue 3
The next issue is perhaps the biggest one. There are shortcomings in core's normalizers. The main ones are around fields that resemble entity references but really aren't and fields with calculated values. And then there's normalizing files and images. The issues here are as follows:
- Term's parent field doesn't behave like a normal entity reference field, and so terms are normalized without a reference to their parent.
- File and images can't be embedded yet. aGov gets around this using Sam Becker's Better Normalizers sandbox. Other modules like Entity Pilot and File Entity have their own normalizer. All three of these essentially run the same code and the File Entity one formed the basis of the first core patch. If we're serious about default content - we need to support images too.
- Menu links that point to content are normalized with serial IDs instead of UUIDs. So menu links that point to content can't be imported without considerable hard-coding.
- Paths aren't present in normalized output and therefore pretty URLs cannot be reinstated by default content.
Issue 4
The final issue is probably the most contentious. Just because we could add default content to the standard profile - does that mean we should? The standard profile isn't a product. A product is created to solve a problem or fill a need. The standard profile does not do that. It is a random assortment of features that once resembled a blogging site but no longer does.
We need a real product. Or several products. This was the basis of the platform initiative and also the Snowman group. Personally I feel that is a better use of our limited time and resources. Much of the platform initiative was put on hold while we focussed on the unofficial framework initiative. This was a five-year effort focussed on untangling the spaghetti like nature of core. We got a long way towards that goal.
Perhaps now its time to revisit the platform initiative.
I have some thoughts around how this might look - but will cover those in a future post.