This is a follow up issue to #1739928-73: Generalize language configuration on content types to apply to terms and other entities

catch said:

+++ b/core/modules/language/language.moduleundefined
@@ -223,6 +222,207 @@ function language_process_language_select($element) {
+function language_get_default_configuration($entity_type, $bundle) {
+  $configuration = config('language.settings')->get(language_get_default_configuration_settings_path($entity_type, $bundle));
+  if (is_null($configuration)) {
+    $configuration = array();
+  }
+  $configuration += array('langcode' => 'site_default', 'language_hidden' => TRUE);
+  return $configuration;

This makes me uncomfortable. We're dynamically storing information about entity types and bundles in CMI here, which is the first place that's going to happen. But at least bundles are likely to become ConfigEntity instances at some point (whether a generic Bundle class or node types. etc. individually).

So, if I want to export a node type, I have no way to know that there is a language.settings config object which is storing information about them somewhere. This is an issue that hasn't been resolved in CMI yet, so it doesn't block this patch going in, but I'd really, really like a @todo pointing to a concrete issue that will try to deal with this so we can revisit it later.

Comments

catch’s picture

Priority: Normal » Major

Bumping this to major. There's a few bits and pieces to this:

- if a module wants to extend a configuration entity, how does it do that? With it's own configuration object or by somehow attaching onto the main one?

- How much do we care about people being able to export a set of configuration (such as everything to do with a specific bundle) and push that separately from other configuration changes?

yched’s picture

So, I see a couple challenges with a pattern where module B adds its own stuff in module A's ConfigEntities files.
For the sake of example, let's use "language settings on a node type", but this would also apply to "comment settings", "pathauto settings", or even possibly "list of field instances on a node type".

- Memory impact : you cannot get any info about the node type without loading *all* the associated info in memory.

- #1648930: Introduce configuration schema and use for translation : node module needs to provide metadata about its config files. In order to do so, he must collect metadata associated with each "additional data".

- Cleaning : What do we do with those 3rd party entries in node.type.article.yml :
When comment or pathauto gets disabled ? We can't delete them, which means we keep loading them in memory.
when comment or pathauto gets uninstalled ? How do we delete them ?

- Updates : when comment module wants to change the name or format of one of its settings, it needs to go and alter the yml files provided by node.module ? That means making assumptions about the filename and structure of those files it doesn't own. I smell nasty cases when node.module wants to change stuff as well.

- ConfigEntities are business objects. They have an internal set of properties, usually populated from the content of their associate config files (following some some specific business logic oftheir own), and business methods to work with those properties.
This doesn't map really well with the idea of a "dumping ground" area, where a ConfigEntity object dumbly holds external properties it has no clue about. It also means that there cannot be business logic around those external properties.

Maybe that defines where the line should be drawn : those 3rd party config entries can only be dumb variable-like values. Anything that would deserve to be its own ConfigEntity cannot be stored within a "parent" config file, but needs its own file.
That is : comment settings might be stored within node.type.article.yml, but not field instances.

yched’s picture

In short - given :
- the list of challenges above,
- the fact that, if I get things right, the main benefit we expect is easier manual inspection of config changes (which I do value),
I would see more value in having a way to let comment settings for article live in a separate file under the node.type.article.* space, than in trying to embed them in the parent node.type.article.yml file itself.

catch’s picture

A separate file seems sensible to me, that also ties in with #1601168: Orphan/obsolete keys and sub-keys *within* configuration objects are retained *forever*.

The language issue though is embedding an array of node type configuration into a locale settings file, although it looks like swentel already updated that to suggest shipping separate, namespaced files for each entity type/bundle instead.

gdd’s picture

Yched's vision above is pretty much how I always saw configuration working for situations where one module is 'extending' the configuration of another. I'm not even sure about this:

That is : comment settings might be stored within node.type.article.yml, but not field instances.

Config should always be owned by (and supplied in a default file from) the module whose functionality it represents. So if the above was true, then node module should also take over the functionality currently provided by comment module which I think we can safely assume nobody is really interested in seeing happen.

So I really think we need to make that a hard and strict rule and figure out a way to make it work. I'm still learning about Configurables so I'm not prepared to start offering implementation solutions at this point.

Anonymous’s picture

"Config should always be owned by (and supplied in a default file from) the module whose functionality it represents."

i think we may need to separate 'owned by' and 'supplied in a default file'. i agree with owned by, and i think it's doable.

supplied in a default file, not so much. that rules out config that a module wants to install based on a the state of the site at install time. so we can't have a strict rule about needing to supply defaults in a file, or, we need to say 'dynamic defaults' are not allowed, which i can't see working out too well. (and i do mean not allowed as in a toothless rule, because we can't stop modules doing it.)

tim.plunkett’s picture

I also think "Config should always be owned by (and supplied in a default file from) the module whose functionality it represents." is unclear, especially if you consider default views provided by modules.

gdd’s picture

The 'owned by' can be confusing because there are two different definitions of owned. Here is the example: Module Kitten provides views.view.last_5_kittens.yml which lists the last five kittens submitted to the site.

- This config is 'owned' by Kitten module, because if Kitten module is uninstalled, then this view will be removed (unless overridden possibly, lets leave that aside for the moment.)
- This config is also a view, and thus to some extent 'owned' by Views, because if Views is uninstalled, then assumedly all the views will be removed as well.

I personally would submit that Kitten module 'owns' this config, which is implemented using Views. I think 'the module whose functionality this config represents' is a similar situation. This config represents functionality of Kitten (a listing of kittens) which is implemented using Views.

However I fully admit that these definitions will be somewhat context-driven and driven by the functionality at hand.

tim.plunkett’s picture

xjm’s picture

Title: export a node type, no way to know that there is a language.settings config object storing information about them (follow up) » Determine how to identify and deploy related sets of configuration
Issue tags: +Needs issue summary update

We talked to catch about this in IRC:

09:55 catch: There's a node type.
09:55 catch: I want to add some arbitrary crap to the node type.
09:55 catch: Like language settings.
09:56 catch: I can't save crap into the node type CMI file itself.
09:56 catch: 'cos that will get ugly.
09:56 catch: But the language patch in the queue was saving it into a completely unrelated CMI objet
09:56 catch: like an array within the language.settings object.
09:56 catch: So there's no way on earth to tell from that that it contains node type config.
09:57 catch: So when you want to deploy a subset of config changes, or export it all to default config provided by a module.
09:57 xjm: ah. and... we need either metadata, or separate files, to find that related config?
09:57 catch: then you'd be looking through all the config files in the system trying to figure it out.
09:57 catch: Yep.
09:57 catch: So yched suggested a naming convention.
09:57 catch: Like entity_type.bundle.foo or something.
09:57 catch: Which seems OK.
09:57 catch: But we need to figure out /something/
09:58 catch: 'cos otherwise in one year people are going to complain.

Essentially, we need a way to determine what configuration needs to be staged together when we want to deploy updates to the node type, if/when some config related to it lives in separate files. This might be a naming convention, as suggested above, or somehow indicated through metadata, but we need to know which changes to deploy.

sun’s picture

I disagree. Entirely.

  • We never had this information in the past, to begin with.
  • Config object names must be namespaced by the owning module. entity_type.bundle... does not fly, at all.
  • The config system does not and should not care about potential relationships. All it cares about are hard dependencies. Dependencies are different, they are only a subset of "related" things, and can be determined at runtime.
  • The config system does not deliver the secondary use-case of Features; i.e., the management of "configuration packages to assemble self-contained and scope-limited functionalities for a specific use-case."

Now, where we might be able to form a consensus is on the following:

  1. Data stored in Drupal can be enhanced in unlimited ways through modules.
  2. Drupal has no capability to determine relationships within the data that it stores.
  3. Despite using a storage engine/system (SQL) that natively supports to create views of related data, Drupal does not use that capability. (Historically, likely due to a lack of SQL experts. Today, it would likely get blocked by NoSQL fanboys. Whatever.)
  4. In order to bundle data into logical units, you need a separate concept and mechanism that is capable of discovering and collecting related data items. And most likely, you want to save/store/cache the results for later re-use.
  5. This is atomic functionality in an own system. This is not a problem of the configuration system, at all.

    (Approaching it from the config system perspective leads to utterly wrong answers for wrongly asked questions in the first place.)

In the end, you want one entity to reference X other entities, so you're able to present/expose and manage that bundle of related business objects for certain administrative use-cases.

tstoeckler’s picture

In the end, you want one entity to reference X other entities, so you're able to present/expose and manage that bundle of related business objects for certain administrative use-cases.

I agree. Since we are already introducing configuration metadata it seems that would be an ideal place to put some sort of a "dependencies" key. To avoid confusion, the above quote is only true when thinking about entities in a general sense, not in a $object instanceof Entity sense, as you might very well want to enhance ConfigEntities with stuff that is merely config, but not a ConfigEntity itself. But since we'll have metadata for all configuration, not only for ConfigEntities, that should not be a problem.

Lars Toomre’s picture

I read #12, but I am at a loss of what is meant. Can you explain further or clarify?

For instance, in this new config world, how does one display on an english website, a node that has been translated to German for certain admin/display fields?

Let us further suppose that the node title needs to be in German in certain cases and in English in others. How is this determined? How does the interface know when to display German or English?

tstoeckler’s picture

1. Nodes are not configuration but content. This might not make sense for all use-cases, but that's a given fact and I don't see that changing any time soon. Therefore this discussion does not relate to nodes at all, for that see #1188388: Entity translation UI in core.

2. For how the interface language and the content language (which are distinct) are determined see the API documentation on language negotiation.

I'm happy to clarify what I said, in case I was unclear, but I didn't yet understand how your questions relate to this discussion. Could you, in turn, clarify your question? :-) Thanks.

andypost’s picture

In my view of things ConfigEntity is nearly equal a cache tag which could be used as bundle for all related entities

Anonymous’s picture

i think i agree largely with #11. i don't think the config system should directly support an operation like 'export all config for this $thing'.

that feels like the job of systems built on top of the config system. do we need any other primitives in the config system to make it easier to build 'export config for $thing'? that is a question i think we need to answer from the CMI perspective.

gdd’s picture

This isn't just a matter of exporting or deploying all config for $thing, it is also a matter of $thing finding all the config that is associated with it (which I assume it will need to.)

As far as namespaced by the owning module, that is a really grey area already. For instance, if module foo provides views.view.foo.yml, then who owns that config? I would argue that module foo does even though it is not in foo's namespace. How are we going to namespace entity types? I suppose entity...yml works. Are they owned by entity module though? I do agree that all config needs to be namespaced to a module, I think.

I disagree that we should build any separate tracking or dependency management into the metadata system. We'll be lucky to get that finished at all at this point, I'm not going to have more features tacked onto it.

plach’s picture

How are we going to namespace entity types? I suppose entity...yml works. Are they owned by entity module though? I do agree that all config needs to be namespaced to a module, I think.

Well, the "entity" prefix wouldn't work then, since we no longer have the Entity module :)

I guess it makes no sense for Core components to determine a prefix, since they should never own config objects, would they?

catch’s picture

I don't think this is about a button for export, it's about setting conventions for organizing related bits of configuration so that it's predictable. It's definitely not a problem for the config system itself, it's a problem for the conversion patches and how we apply the convention to them assuming we can come up with one.

it is also a matter of $thing finding all the config that is associated with it (which I assume it will need to.)

I guess this depends on the $thing, but yeah this also crossed my mind.

andypost’s picture

I agree with thesis in #11. The only question there - how to provide dependencies between module and it's config files!

The module name prefix must be used anyway (as it now), the debatable part - should config system provide a bundles (folders) for each module or not? By default we have file storage which has limits on count of files stored per folder (probably this could be an issue)

I see 2 different cases here:
1) ConfigEntity - each entity has it unique machine name which should be used to define a folder/bundle to import/export.
Each entity knows exactly all its keys. Could property API able to extend it's keys?
The module which defines the entity should care about all possible alterations and call hooks to allow other modules to injected pieces of information to be stored in their own storage or within same config - relation determined by the business logic of hooks.
I think this applies to Views (when some module provides an exported view then views module should care about internals of the file, CMI just provides a dumb import of whole file).

2) Plain config files/properties - known as variables (site.name and others). They could be changed by direct $config->set(...)->save() and CMI should not care about cleanup as suggested in #1601168: Orphan/obsolete keys and sub-keys *within* configuration objects are retained *forever* Let's leave this for contrib for D8 like schema.module does for now.

Also we have States - not sure they are exportable, same as KeyValue storables.

moshe weitzman’s picture

Anything left to do here?

gdd’s picture

Status: Active » Closed (duplicate)

At this point I think this discussion (and the other similar ones) are all hashing out in #1776830: [META-1] Installation and uninstallation of configuration provided by a module that belongs to another module's API. So I'm going to close this as a dupe. If anyone else thinks there's still stuff to discsus here, please reopen.

gdd’s picture

Issue summary: View changes

Improved readability