Problem/Motivation
fieldable/isFieldable() in the entity type annotation/on EntityTypeInteface is misnamed. It is not about having fields, the point is being able to add/update/remove fields, like field.module does.
Same for the FieldableEntityStorageInterface,
Proposed resolution
Remove the flag completely. All content entities are supposed to support it if the storage supports it. The only thing that has to be specified is the field_ui_base_route, that tells field_ui where the integration point is for the Manage fields and related local tasks. The interface is renamed to DynamicallyFieldableEntityStorageInterface and also rename the corresponding FieldableEntityStorageSchemaInterface to DynamicallyFieldableEntityStorageSchemaInterface.
There are now 3 different things to check for, depending on what the code is doing:
1. Can have fields/is a content entity:
// On the entity. there is an issue that adds a FieldableEntityInterface.
$entity instanceof ContentEntityInterface.
// On the entity type. This is not great DX, but there is an issue for this too.
$entity_type->isSubclassOf('\Drupal\Core\Entity\ContentEntityInterface')
Use case: Check if an entity type can have fields. Every content entity type has at least one base field, and config entity types do not have any fields.
2. Check if the storage allows for field (storages) to be added, removed, or updated.
$entity_manager->getStorage($entity_type_id) instanceof DynamicallyFieldableEntityStorageInterface
Use case: As a module storing data for other/all entity types, check which entity types that can be done for.
3. Check if field UI is enabled for a given entity type.
\Drupal::moduleHandler()->moduleExists('field_ui') && $entity_type->get('field_ui_base_route')
Use case: Extend/integrate with field UI.
Additionally, the onBundleCreate(), onBundleRename() and onBundleDelete() methods are moved from DynamicallyFieldableEntityStorageInterface to a new EntityBundleListenerInterface, similar to EntityTypeListenerInterface. The entity manager now also implements the same interface instead of slightly different methods. The order of arguments has been adapted and changed.
The UI for view modes, form modes and comment type creation is limited to entity types that specify a field UI base route. This is done because those all require the field UI to be used (manage displays, create comment fields).
Remaining tasks
User interface changes
API changes
As described above.
Original report by @fago
The entity definition / entity info key 'fieldable' does not fit any more - all content entities have fields now. So we should rename this + fix the name of FieldableEntityStorageControllerInterface // the base class to match that. We do not have that distinction yet anyway though, but I think this is where "field_ui" should move in the long-run.
Comment | File | Size | Author |
---|---|---|---|
#78 | fieldable-field_ui-2100343-78-interdiff.txt | 4.2 KB | Berdir |
#78 | fieldable-field_ui-2100343-78.patch | 59.3 KB | Berdir |
Comments
Comment #1
fagoWe discussed configurable entity field storage in Prague. So what we dicussed here is that we want to work on we right now call "fieldable entity storage" to work with entity fields in general, i.e. any module can use the API to create storage for its own fields - not being field API / field.module fields.
Reasoning
So what we came up with related to 'fieldable' and the entity definition in general is the following:
Please read up on the meeting notes for other details on the idea. [TODO: create and link issue for other stuff]
Comment #2
amateescu CreditAttribution: amateescu commentedComment #3
fagoThis is critical for understanding the new concept of "fieldable".
Comment #4
yched CreditAttribution: yched commented"beta target" -> bumping priority accordingly
Comment #5
fagoLet's get started and implement the suggestion of #1 and
- add the flag "configurable_fields"
- rename "fieldable"
Can we agree on to go with "extensible_storage" instead of "fieldable", or are there any better suggestions meanwhile?
Comment #6
fagoAlso we've got
FieldableEntityStorageControllerInterface
and related base classes, so those would have to renamed as well, i.e.FieldableEntityStorageControllerInterface
->ExtensibleEntityStorageControllerInterface
Comment #7
andypostSuppose this should be
Extendable
because extensible more like "stretchable"Otoh do we really need the flag "fieldable" suppose better to check the storage controller interface, because the storage implementation actually affects a "fieldability"
Comment #8
BerdirNo, that is not the same thing.
Just because the storage controller is capable of doing so does not mean that the specific entity type does.
If we rename the storage controllers, I'd suggest Content as a prefix, because that's what it is...
Alternatively provide a different storage controller for non-fieldable/extendable ones. DatabaseStorageController can *not* be used for content entities.
Comment #9
fagoIn particular, as the base class is able to do do you might want to inherit from it without enabling it.
For the base class yes, but the interface is explicitly about the field API storage mechanism.
True, seems that extendable is what we want.
Comment #10
BerdirWe might want to rename the storage classes in #2188613: Rename EntityStorageController to EntityStorage because that issue is renaming every single one of them anyway.
Comment #11
andypostComment #12
BerdirOk, we discussed that we will do the storage class renames either the related issue or somewhere else.
Which should make it possible to do this as a Novice issue.
Start with this:
- Rename "fieldable" to "extendable" in the all the entity type annotations and the documentation for it
- Rename isFieldable() to isExtendable(), update all usages.
Comment #13
tamasd CreditAttribution: tamasd commentedComment #14
tamasd CreditAttribution: tamasd commentedComment #16
sriharsha.uppuluri CreditAttribution: sriharsha.uppuluri commentedFixing the failed test cases.
Comment #17
sriharsha.uppuluri CreditAttribution: sriharsha.uppuluri commentedBefore creating the patch there are issues with simpletest/TestBase.php. Except those remaining are fixed.
Comment #18
BerdirI think the description here also needs to be updated.
Same here.
Comment #20
sriharsha.uppuluri CreditAttribution: sriharsha.uppuluri commented17: drupal8-rename-fieldable-key-in-entity-definitions-2100343-17.patch queued for re-testing.
Comment #22
visabhishek CreditAttribution: visabhishek commentedi am updating the patch as per #18. Please review.
Comment #24
sriharsha.uppuluri CreditAttribution: sriharsha.uppuluri commentedComment #25
martin107 CreditAttribution: martin107 commentedpatch no longer applied, so reroll
Comment #26
martin107 CreditAttribution: martin107 commentedComment #28
BerdirWhen discussing Extensible vs. Extendable vs. Fieldable in the entity storage controller rename issue, @alexpott argued that fieldable made still more sense to him, as he interprets it as "Being able to add additional fields", which has the advantage that is more specific than just "extendable", which doesn't explain what is extendable exactly.
That's why we rolled back the Fieldable* interface and base class and it should be a tiny change to rename those, which we now should do here if we decide to go with the rename.
Comment #29
alexpott@Berdir is spot on - what do extendable, extendible, or extensible say about how the storage is being augmented... what about augmentable :P
Fieldable
has the advantage of using terminology people know - yes the entity already has fields but to me fieldable says I can add more fields.Comment #30
yched CreditAttribution: yched commentedNot a big fan of the alternatives either, but : then you could have a "non-fieldable" entity type with fields ?
Comment #31
BerdirWe discussed this a bit in IRC, here's the log:
Comment #32
fagoTo me Fieldable says I can put fields on it. As developer providing an entity type and putting fields on it saying it's not fieldable is a contradiction?
I've not idea whether extensible/extendable fits better, but I dislike keeping fieldable.
Comment #33
fagook, so here is a start to rename to "extensible". Based on above discussion it seems to be better suited than extendable.
However, when writing docs I figured that the "extensible" flag actually means "ui extensible" now as the interface already means that entity storage is capable of storing additional fields. So should $entity_type->isExtensible() just check the interface and "fieldable" become something like "ui_extensible"? -> This boils into #2226567: Rename 'field ui' to 'configurable_fields' and introduce a new 'admin ui' entity type property then.
Comment #34
sunIn light of that assessment, wouldn't
$entity_type->isConfigurable()
be more accurate?Comment #35
andypost+1 to Configurable content entities!
Comment #36
fago$entity_type->isConfigurable()
together withExtensibleEntityStorageInterface
does seem to fit rather well. However, formatters and widgets of *existing* fields could be still configurable, while you may not add new fields to a non-configurable entity type. Not sure that's reflected by the term?Comment #37
yched CreditAttribution: yched commentedHmm, dunno...
Unfortunate clashing IMO.
I don't think "adding fields to an entity bundle through the UI" can be seen as "configuring the Entity type".
Comment #38
fagoGood point. Any other suggestions?
What about "ui_extensible" along side with
Comment #39
yched CreditAttribution: yched commentedTBH, I've somewhat lost track here, so let's see if I got the concepts right:
0) ContentEntities have fields. All of them. That's what they do.
1) A StorageController can support (or not) "dynamically adding new fields", such as (but not restricted to) ConfigFields.
--> notion of "extendable storage"
2) An entity type can support (or not) adding custom ConfigFields through the UI.
It if it does, it needs to use an "extensible storage" class.
If can also chose *not* to allow ConfigFields, even if the storage class it uses could support it.
--> this has to be a dedicated flag on the entity type, independently of the storage class the entity type uses.
3) Regardless of the above, any entity type can enable "out-of-the-box" UI screens provided by field_ui (which could be renamed entity_ui, but different story)
If it doesn't support ConfigFields, it gets "Manage Display" screens, which is still useful for non-ConfigFields
If it does support ConfigFields, it additionally gets a "Manage Fields" screen to add / configure / remove ConfigFields
If the above is a correct assessment, then my suggestion atm would be :
1) "extendable" seems fine to qualify storages
2) regarding an entity type supporting ConfigFields or not, we failed to find a concise / non-ambiguous name for the flag so far, so maybe we need to be litteral : 'supports_config_fields' / supportsConfigFields() ?
3) Allowing out-of-the-box UI screens requires the entity type to provide admin path/route info to attach those pages to, and this is in place already, not sure we need to change whatever there ?
Then again, it's entirely possible I'm missing some of the stakes here :-)
Comment #40
fagoThe assessment is correct, yes.
However, regarding 2:
I do not think we really need a flag for that, do we? We need a flag for the having configurable fields in the UI, yes - but if the storage is extendable/extensible, why not have field module support it from API/config?
Comment #41
yched CreditAttribution: yched commentedWell, that would be the equivalent of D7's 'fieldable' ? "if an entity type is not fieldable, D7 doesn't try to load or save configurable field data".
If for some reason an entity type sees fit to state "no admin-defined fields here, please", I don't think this should be enforced just by not displaying a UI. It should really be "do not look in config for field definitions at all".
The storage we ship in core and use for all content entities by default (ContentEntityDatabaseStorage) *is* extendable (i.e is *able* to support dynamic fields). A Mongo storage will be extendable too. So in practice all content entity storage are going to be "extendable" (which, BTW, makes me question whether we really need a term to qualify that).
So we can't say "an entity type supports configurable fields if it uses an 'extendable' storage", because all storages are going to be extandable, and so in practice no entity type could say "no ConfigFields please", which would be a regression compared to D7.
Or we'd need to make a separate, non-extendable version of ContentEntityDatabaseStorage (and same with MongoStorage, etc) which feels absurd. Better to have feature-rich storages, and let the entity type specify whether it actually wants to leverage the feature ?
Comment #42
andypost@yched great arguments! otoh that means it would be hard to make performant entities to make them skip field hooks
Comment #43
fagoYep, but different to d7 there is would be no extra weight any more as config fields go into the same field definition repository and are handled as any other extended field.
Yeah, I'm not sure there is a use-case for having config but no UI for it, so I'd be fine with disabling it as a whole.
Yeah, because being extendable is still optional and not every storage will be able to support it; e.g. when exposing read-only remote data you really don't want it.
which field hooks? ;-) There are no entity-level config field hooks that go beyond what we have for base fields - it's all unified!
Comment #44
yched CreditAttribution: yched commentedAh right, forgot about read-only storages. But then that is a split bewteen read-only and read-write. Would it be safe to assume a read-write storage has to be extendable ?
Comment #45
fagoI don't think so, assume a web service with read/write - there is no way to extend this then.
Comment #46
andypostAs I remember right this was introduced for menu_links core case, so for now not sure a purpose.
As we suppose to clarify this why not make just a method with default implementation a-la
public function isExtandable() { return self instance_of ContentEntityInterface;}
Comment #47
tstoecklerCaught up on the recent discussion here.
Originally I would have proposed to separate
$entity_type->isExtendable()
from$storage instanceof ExtendableEntityStorageInterface
but #39 makes a compelling case to let entity types disable extendability even if the storage supports it. Thanks for that post @yched, that was very insightful.If I judge the latest comments correctly, it seems we have an agreement between at least @yched and @fago here and the latest patch seems to follow along the same lines. I.e. simply rename
isFieldable()
toisExtendable()
and replace usages. No introduction ofinstanceof
checks.I reviewed the patch and couldn't find anything to complain about. So tentatively marking RTBC. Sorry if I missed anything or if there are in fact still reservations against what I perceived as agreement.
Comment #48
yched CreditAttribution: yched commentedWell, current patch does $entity_type->isExtendable(), which didn't seem to raise concensus as being clear about what it means (see #28 to #37).
#39 proposed to
- keep "is extendable" to qualify EntityStorage classes
- use a litteral & explicit "supportsConfigFields()" for EntityType classes
Not that I'm married to it, just clarifying the basis of the recent discussion as far as I get it :-)
Comment #49
tstoecklerOK, thanks for the clarification.
Comment #50
fagoad #48 - so does that mean isExtendable() checks for the interface and supportsConfigFields() a respective config_fields = TRUE|FALSE?
on extensible/extendable - I've no idea which one fits better, based on berdir's discussions with alexpott I though "extensible", but I'd be glad to go with which of the two is right for people.
Comment #51
yched CreditAttribution: yched commentedSorry for the delay, let that one slip through :-/
Sounds right to me ?
No strong opinion either, but I kind of agree with the remarks made earlier that "extensible" feels like "stretchable", so I'm temptatively +1 on "extendable".
Then again, those all came from non-native english speakers, so maybe we should let @alexpott decide (is "extendable" even a word ? ;-)
Comment #52
fagoTalked to alex_pott about it again, and he feels like "extendable" does not get it right as people might think "extending storage" be like adding additional data, i.e. entities. We could not come up with a better term though.
I'll think a little bit more about a good term, but if we are not able to come up with anything better I think we'll have to go with "extendable", as "fieldable" does not work anymore.
Comment #53
andypost#39.2 said
supportsConfigFields()
but this is not only about flag in annotation, the entity class should implementContentEntityInterface
, is not it?About #39.3 - entity type annotation should provide the annotation key with route name #2309187: Fix double-link-entry between Entity and Entity Type classes
So let's limit the scope by renaming:
1) annotations key to "field_ui_allowed" or 'field_ui_fields_allowed"
2) the
isFieldable()
toisFieldUIAllowed()
Comment #56
BerdirThe question here is if there is a performance problem if we make the setting just about the UI integration. For loading, we have the entity cache now and for writing, it should probably not hurt too much.
If so, then I agree with @andypost, the easiest option would IMHO be "field_ui = TRUE/FALSE", would work quite well in combination with with "field_ui_base_route" that we have now. And I would actually suggest to *remove* any possibly misleading methods, and just go with get('field_ui') in the few places that would then still have to call it.
Comment #57
andypostThere could be another way - try to re-use "thirdPartyWTF" trait somehow
Comment #58
BerdirI don't think that makes sense, that's about config entities not plugins/annotations.
Here's a first patch that renames it to field_ui, just trying to see what this would mean exactly..
Comment #59
yched CreditAttribution: yched commentedIf we make it just about UI integration, then why do we need a field_ui = true/false flag, the presence/absence of a field_ui_base_route should be enough ? Having both would be redundant ?
Comment #60
BerdirTrue :)
Comment #61
andypostand summry needs clean-up
Comment #63
andypostLooks this not about UI but about ability to load/save configurable fields.
This means that some of isFieldable() should be changed to check the interface of the storage controller...
Comment #64
BerdirFixed the installer, removed field_ui. interdiff would be useless.
Comment #65
BerdirComment #67
Berdiradd content entity check.
use field_ui_base_route, because code.
same as above.
check storage?
check the route thing too.
same.
same
Above review is fixed, the tests should also be passing.
Comment #68
BerdirRenamed FieldableEntityStorageInterface to DynamicallyFieldableEntityStorageInterface and moved the onBundle* methods to a separate interface. They're not related to that.
Comment #70
BerdirRe-rolled, updated the issue summary.
Comment #72
BerdirChecking the wrong interface.
Comment #73
effulgentsia CreditAttribution: effulgentsia commentedComment #74
effulgentsia CreditAttribution: effulgentsia commentedComment #75
BerdirForgot about FieldableEntityStorageSchemaInterface.
Comment #76
BerdirComment #77
BerdirCreated change record: https://www.drupal.org/node/2346455
Comment #78
Berdir@swentel found a few issues:
- Some left-over debug()s
- Reference to FieldInstance, but HEAD was already wrong there in a different way
- "synced" the example in hook_entity_field_storage_info() with the real implementation, so the diff is smaller.
Comment #79
swentel CreditAttribution: swentel commentedLooks good, thanks, should be green as they are only doc changes.
Comment #80
webchickThat middle hunk unfortunately doesn't look like docs changes so have to wait for testbot. :(
Comment #81
BerdirThat part is only a hook example, copied from field module. Changed it only to make the patch smaller.
Comment #82
webchickCommitted and pushed to 8.x. Thanks!
Comment #84
BerdirGreat! :)
Published [#2346455], will go through existing change records tomorrow, there's one about onBundle*() for example.