Problem/Motivation
Content entities may support weights and may want to use a list builder with drag-and-drop capabilities. Unfortunately DraggableListBuilder is only available for config entities.
While it probably doesn't make sense to add a draggable list builder for content entities in core without actually having an example implementation, a lot of the logic is not really specific to config entities so it would be unfortunate to duplicate it.
Proposed resolution
Extract the common logic into a trait. The only config-entity specific bits are extracted into public function getWeight($entity) and public function setWeight($entity, $weight) which DraggableListBuilder implements for config entities. This will ease adding a draggable content entity list builder in contrib. In fact I hope to add it Entity API.
| Comment | File | Size | Author |
|---|
Issue fork drupal-2989889
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 2989889-draggable-list-builder-trait
changes, plain diff MR !5154
Comments
Comment #2
tstoecklerHere we go. Clicked around a bit on a couple draggable list builders and didn't seem to break anything.
Comment #4
tstoecklerHehe, vocabularies were not among those I tested. So thought the
$this->hasWeightwas a nice cleanup because we don't actually need the weight key in the generic code, but I didn't realize that I accidentally introduced a BC-break. This one should be better.Comment #5
tstoecklerNow added a patch for Entity API over at #2990784-2: Add a draggable list builder for content entities so you can see how this would help.
Comment #6
joachim commentedHow is that going to work when subclasses need to
Does it make sense to allow FALSE here?
Comment #7
tstoecklerI'm not actually sure why the current supports setting this to
FALSEthat has always seemed pretty pointless to me. However, in order to not break BC, I think we need to keep supporting this.Comment #8
bojanz commentedThank you tstoeckler, this is a great idea.
I first reviewed #4, and had the thought of "but wait, $this->weightKey isn't actually used".
I do prefer the approach of #2, but realize that it's too risky. Even Commerce uses the unset($this->weightKey) trick which caused the VocabularyListBuilder breakage.
My only remaining question is here:
Is it odd for a trait to reach into \Drupal?
If this was a Commerce trait I'd just expect the parent class to set $this->formBuilder in the constructor, with no fallback or method, but core is usually more tolerant.
Comment #9
andypostMaybe return
$thisin setter?Comment #10
dww+1 to this issue overall.
+1 to #7. The cost of possible BC breakage outweighs the tech debt of keeping this API.
+1 to #8. I agree that if you use this trait, you should properly set
$this->formBuilderin your constructor via good DI, not this. However, the existing code "does it wrong", so I'm not sure if fixing this is scope creep here. I'd probably just try to fix it now, but maybe a follow-up is better.+1 to #9.
Thanks,
-Derek
Comment #16
idebr commented#8 I went with the smallest change possible to make it easier to get this issue committed.
#9 The setter now does
return $thisComment #17
idebr commentedFixed code style
Comment #18
joachim commentedLGTM, though follow-ups need to be filed for the various suggestions for follow-ups in the comments.
Comment #21
spokjeBack to RTBC per #18 after #3255836: Test fails due to Composer 2.2 solved the unrelated test failure.
Comment #25
andrew answer commented+1 to release.
Comment #26
alexpottCan use a return tyephint.
We can and should use scalar typehints - plus we can use return typehints too ...not sure what it would be.
These inheritdocs are from \Drupal\Core\Entity\EntityListBuilder and it's interface
These are from \Drupal\Core\Form\FormInterface
... not sure what to do but @inheritdoc here is incorrect. We're not inheriting any docs.
Comment #29
tstoecklerConverted the patch into a MR now, with #17 as the initial commit so my changes are easily reviewable. Went ahead and implemented #8 now with a tiny change in
EntityListBuilder(to set$this->formBuilder) (but not changes required in any sub-classes). And also fixed #26. Verified that everything still works and also verified that adding more property or return type hints causes breakage because that would require sub-classes to also specify those.Comment #30
smustgrave commentedSeems points #26 have been addressed in MR 5154. Since this was previously RTBC before that going to restore
Comment #31
catchStarted leaving comments about adding more type hints on the MR, then I realised I should have read #29 properly, of course it will affect subclasses.
Committed a993304 and pushed to 11.x (which will also become 10.3.x). Thanks!
Comment #34
joachim commentedI was going to file a follow-up for the injection of formBuilder, but #3123209: Replace non-test usages of \Drupal::formBuilder() with IoC injection should cover it.
Comment #35
andypostIt missing change notice
Comment #36
andypostComment #37
jurgenhaasThe commit from #33 expects a return value
int|floatfor thegetWeightmethod inDraggableListBuilder. I just came across a config entity, that has a weight property, but that may be NULL. In that case, this throws an exception.Should the
getWeightmethod maybe fall back to 0, if the weight property has no value?Comment #38
tstoecklerRe #35: fair enough, makes sense. Added a draft change notice: https://www.drupal.org/node/3425054. Feel free to publish if you think it's alright. (And then ideally set the issue back to fixed)
Re #37: Wow, never thought of that possibility, but yeah, totally makes sense to not blow up in that case, doesn't really cost much to add that fallback: Opened #3425058: [regression] Add a fallback in DraggableListBuilder::getWeight() to support entities with a NULL weight Sorry for the trouble and thanks for reporting it.
Comment #39
smustgrave commentedMarking RTBC for the CR. Would like a committer to also see before publishing it.
Comment #40
alexpottCR looks great. Publishing.
Comment #41
joachim commented> The commit from #33 expects a return value int|float for the getWeight method in DraggableListBuilder. I just came across a config entity, that has a weight property, but that may be NULL. In that case, this throws an exception.
Similar issue -- I've just tried to use DraggableListBuilder on a config entity, and got a crash because the weight is a string not an int.
Comment #42
joachim commentedFollow-up -- and I wonder whether we should fix this rather than document it: #3425848: DraggableListBuilder / DraggableListBuilderTrait need to document that buildRow() behaves completely differently from the parent class.
Comment #43
tstoecklerRe #41: Interesting, that didn't come up here because that would be fixed as soon as you add config schema to your entity type. But I guess it wouldn't hurt to add a
(float)type-cast togetWeight(). I can open a follow-up for that, if people think that makes sense.Comment #44
joachim commentedAh yeah, the bug is that environment_indicator has declared this incorrectly:
> But I guess it wouldn't hurt to add a (float) type-cast to getWeight(). I can open a follow-up for that, if people think that makes sense.
On second thoughts, we shouldn't babysit that, but we should instead add something to the trait docs to say the weight field must be an int.