The API should include a way of providing default values. E.g. this could be done by a method getDefaultValue() on ItemList and Item objects. Then, on entity creation values could be initialized with the defaults.
| Comment | File | Size | Author |
|---|---|---|---|
| #86 | entity-default-1777956-86.patch | 31.96 KB | klausi |
| #76 | d8_default.patch | 31.94 KB | fago |
| #76 | d8_default.interdiff.txt | 6.17 KB | fago |
| #73 | d8_default.patch | 29.24 KB | fago |
| #73 | d8_default.interdiff.txt | 1.8 KB | fago |
Comments
Comment #1
fagoMoving to core queue.
Comment #2
mitchell commented#1803064: Horizontal extensibility of Fields: introduce the concept of behavior plugins gives an example use-case of "prepopulating" values.
Comment #3
fagoQuoting myself from http://drupal.org/node/1869250#comment-6893050:
Comment #4
fagoQuestion is whether the default value method should go into entity-interfaces or typed data interfaces.
Doing at typed-data level would make it possible to easily have default values for entity.field_text.0.format or so as well, so I guess it would be valuable to do so.
Comment #5
plachClosely related: #1253820-34: It's impossible to submit no value for a field that has a default value.
Comment #6
sunI think we have a really huge Drupalism/DrupalWTF problem if an essential OO concept like default class property values ceases to work. Replacing all object properties with class instances is a very weird concept already, but it is borderline acceptable as long as PHP developers only need minimal adjustments to cater for it.
Destroying the native concept of default values of class properties, however, is really too much IMHO. It's the tipping point at which PHP developers will reasonably blame Drupal for "Re-inventing OO in user-land PHP code" and a PHP class is no longer a PHP class. That's definitely detrimental for Drupal's health and future. A lot of the TypedData abstraction essentially exists to work around PHP's lack of primitive data type support, and PHP developers will already blame us for inventing and doing that; one doesn't have to look very far to find answers from PHP developers who strongly recommend to NOT do what we've done, for plethora of very good reasons; performance being a major one, and as you know, we're experiencing the consequences in various benchmarks already. Also, following the entire logic, one can only guess that one of the next steps is to invent polymorphism and mixins in this user-space OO layer (because, really, what prevents us from doing it? Nothing!) - ultimately rewriting PHP's native C code for OO support in PHP code.
I believe that this should ring all available alarm bells, and instead of abstracting even more, we should try hard to scale things back where possible.
Why can't we do something like this?
Comment #8
fagoI don't think we are re-inventing it - we are leveraging it and we are OO-ifying stuff that's not OO-ified in the language. But yes, I fully agree that we should avoid making typed data an abstraction layer above PHP-classes, but embrace them. See related #1867880: Bring data type plugins closer to their PHP classes.
However, PHP lacks a way to define an object as default value for a class property. Thus, we have to care about that ourselves somehow.
The patch suggested in #6 has the following problems:
- It suggests a simple value for a property, e.g. 'string', where it will be an object holding the string. Thus, the specified default there is wrong as an entity field will never be simply that value. But moreover it implies to devs that the object property / entity field would be just a plain string, what's not TRUE and so a DX WTF.
- We need to support dynamic values also, e.g. to support field API default values or simple cases as date fields defaulting to NOW. That could be solved via hook_entity_create() as discussed at #1253820: It's impossible to submit no value for a field that has a default value, but having it in a class method would be more straight-forward imho.
Comment #9
fagoComing from #1839066: Implement the new entity field API for the image field type where we had a test fail related to default handling. Currently, we have some default values in the hook_schema() implementations, but that does not make much sense to me. We should have default values on entity-api level, such that entity_create() adds them in. If there is no default value, NULL must be a valid value and thus stored as that.
So maybe as a follow-up to this one, we should make sure our hook_schema() implementations do not provide default values and correctly allow NULL values if a field does not have a NOT NULL validation constraint.
Comment #10
fagoDefault values can be at different levels, e.g. we can have
$entity->langcode have the default of array(0 => array('value' => und)) or we can have $entity->field_text->format default to the default formatter *if* a new item is created.
So it makes sense to specify the default value for the fields of the entity as well as for the values of an item, such that those are created when the whole structure is created. But it does not make sense to have default values for an individual item or a list. If you create an individual item, e.g. $string you either provide a value for it or not - I do not see it useful to have a $string to default to anything ;-). It only makes sense if a property is created as part of a complex data structure and no value for a property is provided.
Comment #11
fagook, here is an implementation that adds in default value support via typed data, i.e. you can define it per-field level as well as for stuff like $entity->field_text->format.
Attached implements default values for language fields, uuid fields and for the format of text field items. It also adds a simple way to specify static default values for fields via the field settings, such that stuff like having a comment name default of '' does not force you to create a new class. While the patch implements both, I've not verified the default-format functionality works.
What's missing from the patch is tests. I'd suggest adding the following unit test cases:
- Create a new entity and verify it has the langcode default set.
- Create an entity with an text field and add new field items. Make sure it adds in the default format as default value and that a newly created item with an empty text qualifies as isEmpty().
Setting to "Needs tests" - so someone could pick it up.
Comment #12
dasjoadded tests for default language & uuids.
Comment #13
berdirNot sure I understand that comment, there's no such file?
Comment #14
dasjore #13, yeah I just copied this comment over together with the uuid-related code borrowed from UuidUnitTest
Comment #15
berdirCan you try without those two lines? Shouldn't be necessary.
Comment #16
fago#12: d8_default_value_12.patch queued for re-testing.
Comment #18
fagoRe-rolled patch and fix the comment at both places.
Comment #19
fagoRe-rolled again against latest 8.x, no other changes.
Comment #21
fagook, meanwhile NodeNG got in and quite some tests make use of nodes - also unit tests. Those tests would depend on filter_default_format() to work with that as default value, but that a) requires role permissions schema and b) have a valid format defined.
Both isn't the case for unit-test-cases, so instead of adding that in everywhere it might be better to properly inject the filter system as dependency and mock it in the tests. But that is really out of scope for this issue, thus attached patch removes the addition of the filter_default_format() for now.
Also fixed NodeNG to use uuid_field. Let's see what the bot says now.
Comment #23
andypostSuppose uuid hinks should be filed in other issue
Comment #24
fagoUpdated the patch since the latest changes (notify+term-ng). I slightly improved the approach such that field item classes can define their own default value, i.e. moved language defaults to the language item and analogously for uuid-fields.
The patch triggered some problems of #1869562: Avoid instantiating EntityNG field value objects by default, so I debugged this and fixed those. Looks like there are quite some fails left with node-ng and term-ng related issues - let's track them down too.
Comment #25
fagoBot, have fun.
Comment #27
klausiComing from #1979260: Automatically populate the author default value with the current user, I also want this to work:
That throws Exceptions currently if comment module is enabled, because the node author is not set.
Comment #28
effulgentsia commentedRaising to major because of #27. It's a major (if not critical) bug for non-form-based creation of nodes to throw errors.
Comment #29
fagook, took another stab on fixing the test fails. Most interestingly:
* The patch changed entity create to ignore values for non-defined fields. That should have caused most test fails.
* Due to the default NULL values for all field items we trigger the problem of #1957888: Exception when a field is empty on programmatic creation in a test, thus incorporated a fix here. See the new cleanValue() method.
Also I Improved the test case a bit. See attached interdiff. Let's how this patch goes.
Comment #30
ParisLiakos commented#1957888: Exception when a field is empty on programmatic creation is already major
Comment #32
berdirSee the interdiff's in #1818570-38: Convert users to the new Entity Field API and comment #40 for a fix for the failing forum tests.
Comment #33
yched commentedFunny, for #1969728: Implement Field API "field types" as TypedData Plugins I needed to add a Field::filterEmpty() method that's basically the cleanValue() method added here.
Mine was a bit more straightforward though:
(+ may I bikeshed that maybe 'filter empty" is more explicit than "clean" as to what the function does ? filterEmptyValues() maybe ?)
Comment #34
yched commentedAlso, most probably not for this issue, but I'm a bit perplexed at the "default NULL values for all field items" behavior - i.e, an "empty field" is a Field *with* a FieldItem, that happens to have NULL properties - why is that exactly ?
Comment #35
yched commentedBTW, both the cleanValue() method in the current patch and the alternative code proposed in #33 will leave an "empty" Field with an empty $this->list - which breaks the behavior mentioned above (an "empty field" is a Field *with* a FieldItem, that happens to have NULL properties).
"Sometimes there is an empty FieldItem, sometimes there isn't" sounds wrong ?
Comment #36
fagoWe've an empty field item object by default such that this gets cloned during prototyping the field object, thus speeds up getting further field objects.
Besides that, does this patch extend the behaviour to initialize a single field item as an array with NULL properties on entity_create(). I think having one field item by default is reasonable, as that way you can easily add a field item class with a given default - see the language reference field in the patch for example. Still, you can define defaults having multiple field items using the 'default_value' setting or by overriding applyDefaultValue() of the Field class.
Good suggestion! I re-named the method and added in your more stream-lined implementation :-) Also fixed the remaining test fails and updated the patch.
Comment #37
fago> "Sometimes there is an empty FieldItem, sometimes there isn't" sounds wrong ?
Opened #1988492: Avoid having empty field items by default and answered there, hopefully we can improve that.
Still, this patch would add in empty items for newly created entities returned by entity_create(), as that is the default value. But if we manage to do #1988492: Avoid having empty field items by default they would not re-appear once you save/load the entity.
Comment #39
fagoAdded in berdir's interdiff from #1818570-40: Convert users to the new Entity Field API also ;-)
Comment #40
fago#39: d8_default.patch queued for re-testing.
Comment #41
fagosetting tag for focus
Comment #42
das-peter commentedIsn't here a
return $this;missing? According to the function documentation it should allow chaining.Shouldn't that be "Only do a shadow copy if this is not a new node."?
The word "check" seems to be a leftover from an earlier sentence.
That's all I've found so far :)
Comment #43
fagoThanks, addressed that and re-rolled.
Comment #44
berdirAs discussed in #1957888: Exception when a field is empty on programmatic creation, the check there is actually correct. And this issue will need a re-roll once the other one is in :)
Comment #45
fagook, it got committed so re-rolled. I've kept the hunk that improved the comment (as noted by das-peter above) of the forum.module fix though.
Comment #46
berdirIt's not an improvement :)
The previous comment is correct as explained in the other issue, in case the node is not new, we are *checking* if we have to create a shadow copy.
Comment #47
fagotrue - I should have had a closer look - it's not referring to the if clause. Removed that hunk and re-rolled the hunk.
Comment #48
berdirTalking about applying a default value for UUID is a bit weird as we're actually generating a new one here but can't do much about this.
This would allow to both set the default for the first field item and also multiple values. Not very intuitive, should we document this better here?
In case of configurable text fields, it depends on the configuration of the field if it should be NULL (check_plain(), or filter_default_format(). Should we respect that here?
We can also do it in a follow-up, but then @todo should be slightly reworded I think.
Patch nicely shows the code duplication of entity reference/term/file/image fields. There's an RTBC patch that converts term to extend from entity and use target_id and a green needs review patch for files/images. Would be nice if that could go in first I think, I hope that happens soon.
Comment #49
berdirAbout the default value setting, I think we should also try to find a better place to document the settings a certain class supports. Possibly simply define them with default value in the plugin definition? As we move to annotations, that would be almost the same place but then it's also obvious to search there for documentation.
Comment #50
fagoNo one says that a default value is not dynamic - to me that makes perfectly sense?
As discussed, this isn't special to default values. So while we should probably document it better somewhere(?), this documentation should be generic and not apply to default values only.
Having default settings at the type definition might be an option - as discussed. This is applicable to more than default_value though, so that's another issue.
Comment #51
fagoIt should, yes. But we cannot do it easily, because for that we need filter_default_format() which then makes us depend on filters actually working. But that makes lots of drupal unit test cases fail now (see above), so let's better don't hold this issue on it but implement it in a follow-up. (see @todo)
Comment #53
klausiThis all looks very good to me, fixed the old language constant in the test case.
Comment #55
fago#53: entity-default-1777956-53.patch queued for re-testing.
Comment #56
das-peter commentedPatch looks really good and I'm tempted to set it to RTBC but I found some nitpicky stuff:
I think that should be adjusted to
Language::LANGCODE_NOT_SPECIFIEnow, right?Missing trailing comma.
Do we need / have a follow up issue for that? This was mentioned already by Berdir in #48.
Comment #57
fagook, addressed the points raised.
Comment #58
fagoCreated follow-up issue #2004672: Add a default value for filter format item properties
Comment #59
klausiDo not use the fully qualified namespace here, always use use statements.
Fixed that.
Comment #60
das-peter commentedAccording to the interdiffs all my nitpicky stuff was addressed and since I'm afraid that klausi will punch me if I don't set it to RTBC now - here we go. :P
Comment #61
andypostThis would be nice addition for #731724: Convert comment settings into a field to make them work with CMI and non-node entities
+1 to RTBC
Comment #62
andypostComment #63
tim.plunkettWhy is this only changed for DatabaseStorageController? Is there a follow-up to keep ConfigStorageController up to date?
Comment #64
klausiHm, we just forgot to keep the config storage controller in sync. I think that should not hold up this issue, because we need this urgently elsewhere. So I created this follow-up for the config stuff: #2004756: Defining default values for config entities.
Comment #65
fagoYep, let's move it over into the EntityStorageControllerBase in that follow-up.
Comment #66
fago#59: entity-default-1777956-59.patch queued for re-testing.
Comment #67
fago#59: entity-default-1777956-59.patch queued for re-testing.
Comment #69
fagoNot sure why re-testing failed, works locally. So here is a re-rolled patch without any further changes.
Comment #70
effulgentsia commentedI haven't reviewed this patch, but have confirmed that it has no actual code changes relative to #59, so back to RTBC.
Comment #71
fago#69: d8_default_value.patch queued for re-testing.
Comment #73
fagoPatch needs a re-roll since validation landed. I've updated it and move the existing UUID constraint of length 128 to a uuid-field default constraint, since this is what all uuid columns have as length by now. I think the max-length of it should be less, but changing this is not in scope of this issue.
Also, updated the patch to make use of uuid-field so that defaults are applied.
Comment #74
berdirdefault values for User seem to be not removed?
Outdated comment.
Do we need the tables as we don't seem the save the entities here?
Also, might be a useful helper function for EntityUnitTestBase for which we could create a novice issue.
@inheritdoc. Also not consistent with EntityBCDecorator, but at last that one will go away so it doesn't matter :)
Comment #75
berdirComment #76
fago>Outdated comment.
Imho this one is fine. As noted already somewhere above, I don't think we have to repeat the namespace in the comment, it should be clear which constant we talk about.
>Do we need the tables as we don't seem the save the entities here?
Indeed, no. Now the test case runs in "0seconds" on my machine :D
>default values for User seem to be not removed?
I overlooked that user has that $values defined - I just looked at create() I guess. So I've updated the patch to account for them - those were quite some actually. I'm not sure what a default value of '' brings us though, howsoever I don't think it's in scope of this patch to change the actual default values being used.
Updated the patch to account for the other points raised + re-rolled and fixed conflicts in ViewUI.
Comment #77
fagoAlso, raising priority to major. Imo, a sane way to define default values is a major feature an entity field API is expected to provide.
Comment #79
fago#76: d8_default.patch queued for re-testing.
Comment #81
ParisLiakos commented#76: d8_default.patch queued for re-testing.
Comment #82
das-peter commentedGave this another visual review. I'd say RTBC again.
Unrelated but while reviewing I came across following code in
UserStorageController::baseFieldDefinitions(), is it intention to use "Name" for all the labels?Shall I open a novice follow-up for a clean-up? --> Follow-up: #2019741: Set appropriate labels in the user entity base field definition
Comment #83
fagoThanks!
Comment #84
alexpott#76: d8_default.patch queued for re-testing.
Comment #86
klausiSimple reroll, no other changes, so straight back to RTBC assuming the bot is happy.
Merge remote-tracking branch 'origin/8.x' into entity-defaults-1777956
Conflicts:
core/lib/Drupal/Core/Entity/EntityBCDecorator.php
core/modules/views_ui/lib/Drupal/views_ui/ViewUI.php
Comment #88
tim.plunkett#86: entity-default-1777956-86.patch queued for re-testing.
Comment #90
berdir#86: entity-default-1777956-86.patch queued for re-testing.
Comment #91
fagoBack to RTBC then.
Comment #92
alexpottCommitted 851d7d0 and pushed to 8.x. Thanks!
Comment #93
berdirWe probably need to create or update some change notices for this.
Comment #94
andypostClosely related #1919834: Field instance got no default value when created in field UI
Comment #95
andypostfix tags
Comment #96
klausiChange record created: https://drupal.org/node/2031221
Not sure the wording is correct like "type data definition", please fix where you see fit.
Comment #97
fagoThanks, I worked a bit over it, see https://drupal.org/node/2031221/revisions/view/2746677/2746719
Comment #98
klausiExcellent, so let's call this fixed.
Comment #99
ParisLiakos commentedRemoving tag
Comment #100
berdirRemoving sprint tag.
Comment #102
yched commentedNote : #2050801: Unify handling of default values between base and configurable fields has a patch to move the handling of configurable field default values.
Comment #103
tim.plunkettReminding everyone that while I asked for this to be done equally to both config and content entities, it is still undone for config entities: #2004756: Defining default values for config entities