Problem/Motivation
When editing a taxonomy term which has more than one parent, where one of the parents is root, root will be lost on save.
Steps to reproduce:
- Create a term (term1).
- Create another term (term2) which has the parents set to root and term1.
- Edit term2, save without editing the parents.
- Term2 will now only have one parent, term1. It would've lost root as a parent.
This is because when loading a terms parents it loads an array of terms, root is not a term so this doesn't get loaded.
Proposed resolution
Don't assume a parent is always a term entity.
Remaining tasks
- Reroll the latest patch based on 9.4.x.
- Manual testing after patch can be applied.
- Patch needss review
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #71 | 2898903-2-71.patch | 6.49 KB | alexpott |
| #71 | 56-71-interdiff.txt | 1.69 KB | alexpott |
| #58 | After Patch.mp4 | 3.11 MB | prasanth_kp |
| #58 | Before Patch.mp4 | 3.75 MB | prasanth_kp |
| #55 | 2898903-55.patch | 4.4 KB | alexpott |
Comments
Comment #2
tetranz commentedComment #3
tetranz commentedConfirmed. I'm going to look into it further.
I noticed what I think is another bug. When you give parents of root plus a real term, the drag handles disappear from the term list. That's correct and as expected but they don't return again if the term is then intentionally saved with another term as its only parent. The only way to make the drag handles return seems to be to save with root being the only parent.
I edited the description. Angle brackets around the word root was making it disappear as an unknown html tag. :)
Comment #4
tetranz commentedLets try this.
I added the TermStorage::hasRootAsParent method rather than change TermStorage::loadParents to include root because there is code that calls loadParents which expects to get only entities back.
Comment #5
timmillwoodThis needs tests, but so far looking awesome @tetranz! Thanks!
Comment #6
tetranz commentedThanks @timmillwood. I'll add a test in the next day or so.
Comment #7
tetranz commentedComment #9
tetranz commentedI guess we need to sort.
Comment #10
tetranz commentedComment #11
tetranz commentedI've created a related issue https://www.drupal.org/node/2900139. It's tempting to fix them both in one patch but I guess it's best to keep them separate. It will be easy to fix that one after this one is committed.
Comment #12
timmillwoodLooking good, I think this is a pretty nice, simple fix.
Comment #13
catchTermStorage isn't a base class, so I'm not 100% sure if we can add a method to TermStorageInterface.
Has anyone checked whether this bug exists in 7.x? A quick review of the code suggests that it does. I can see this surviving for years given multiple parents usage is rare, and multiple parents with root as one of the parents likely rarer.
Comment #14
timmillwoodInstead of adding a new interface for
hasRootAsParent()we could add it as a protected method on TermForm?I am assuming this is an issue in Drupal 7 too, but agree it's a very rare edge case.
Switching to "Needs work" to find a solution for not adding to TermStorageInterface.
Comment #15
tetranz commentedI don't think we'd want to add hasRootAsParent() to TermForm. That would mean injecting database into TermForm which doesn't feel good but I guess that would work.
I don't really understand what the problem is adding an additional method to TermStorageInterface. I guess I'm missing something because it seems that not being a base class, i.e., being taxonomy specific, is a good thing. I can understand that adding taxonomy specific code to its parent, ContentEntityStorageInterface would clearly be wrong.
Comment #16
timmillwood@tetranz - The issue with adding a new method to the interface is that if any contrib (or custom) modules are implementing the interface they will need to also add the new method. If there was a base class then we could add the new method there and it would be assumed that any contrib/custom modules would be extending the base class and therefore get the new method automatically. We are only using the new
asRootAsParent()method in TermForm, so although it's not ideal to inject the database there, it saves us from having to resolve and backwards compatibility issues.Comment #17
tetranz commentedThat makes sense. I see what you mean.
I'm happy to do another patch with that method in TermForm if you think that's the right thing to do I wonder if that causes a bigger issue. It would totally tie TermForm to SQL. I would have thought something like TermForm should be storage agnostic. That might be more a theory than reality but it seems to be way too far down the inheritance chain to be aware of storage implementation.
Comment #18
timmillwoodYeh, that's a good point about making TermForm SQL dependent. My next suggestion then would be to add a new interface to TermStorage, then make TermForm handle the case of when the hasRootAsParent() method doesn't exist.
I'm sure @catch has a better idea though, he always does.
Ping @catch!
Comment #19
catch+1 to #18. With no base class I don't see a way around the additional interface - we can have it extend TermStorageInterface and deprecate TermStorageInterface for 9.x
Comment #20
tetranz commentedok sounds good.
So I should make a new interface extending TermStorageInterface. Any thoughts on what I should call the new interface?
Comment #21
catchCould we do something like Drupal\taxonomy\Entity\TermStorageInterface? Usually we don't put the handlers inside the entity namespace but I don't really see why not? Or Drupal\taxonomy\Term\TermStorageInterface if not?
Comment #22
tetranz commentedSee how this goes. I went for Drupal\taxonomy\Entity\TermStorageInterface
I wasn't sure what, if any, comment I should put at the top of either the old or new interface.
I removed an unnecessary query for $parent.
Comment #23
michaellenahan commentedComment #24
michaellenahan commentedComment #25
kork commentedworking on it as part of the DrupalCon Vienna sprints
Comment #34
quietone commentedI tested on Drupal 9.4.x and confirmed this is still a problem. I am postponing the related issue on this one.
Comment #35
mradcliffeI added some remaining tasks and tags to clarify Novice tag. The issue summary also could be updated with @catch's proposed resolution in the proposed resolution section as well as filling out other sections based on the latest patch.
Comment #37
immaculatexavier commentedRerolled patch for #22 against 9.4
Comment #38
ranjith_kumar_k_u commentedComment #39
ranjith_kumar_k_u commentedComment #40
ranjith_kumar_k_u commentedComment #41
immaculatexavier commentedRerolled patch against #37 for 9.4.x. Fixed custom commands
Comment #42
rajandro commentedCouple of change suggestions:
As per 8.6.0 release note (https://www.drupal.org/node/2936675)
taxonomy_term_hierarchyis deprecated, so we can change it to something like this...Comment #43
smustgrave commentedLooks like patch #41 add some issues and #42 some suggestions that should be looked at.
Comment #44
Ratan Priya commentedComment #45
Ratan Priya commented@smustgrave,
I made the changes as required at comments #42
Needs review.
Comment #46
Ratan Priya commented@smustgrave,
Sorry for the previous patch.
I made the changes as required in point 1 at comments #42
Needs review.
Comment #47
smustgrave commentedStill looks like the patch is having issues
Comment #48
smustgrave commentedFixed a syntax issue
Comment #50
smustgrave commentedFixing test case
Comment #51
abhijith s commentedApplied patch #49 and it fixes the issue.Attaching screen recordings for reference.
Comment #52
smustgrave commentedIf you feel the issue is fixed please move to RTBC
Comment #53
vinaymahale commentedI have tested the patch from comment #50 on 9.4.6-dev and 9.5.0-dev. Verified and the patch is applied successfully fixing the issue on both 9.4.6-dev and 9.5.0-dev.
Moving to RTBC
Looks good to Merge!
Comment #54
vinaymahale commentedLooks good to merge!
Comment #55
alexpottI don't think we need to add a new method using SQL to term storage for this. I think we can get the parents from the entity and be done. See attached patch.
Comment #56
alexpottWhoops my test didn't fail against HEAD because of caching stuff and the test not testing what it says it was testing.
Comment #58
prasanth_kp commented#55 Patch Applied on 9.5.x-dev and it fixes the issue.
Comment #60
smustgrave commentedAlso manually tested this and appears working.
Also from the videos in #58 think remvoing the manual testing is fine.
Comment #64
catchphpstan was complaining, fixed this on commit:
Committed to 10.1.x and cherry-picked back through to 9.4.x, thanks!
Comment #65
alexpottReverting as this broke HEAD :(
Comment #70
alexpottThe patch in #56 is no longer good for 10.x - works on 9.5 and 9.4 though...
Comment #71
alexpottFixed the test. This was caused by #2826592: No redirection to term view display page from term edit page. The new patch will work on Drupal 9 and 10 and as the changes are test only setting back to RTBC.
Comment #74
catchWhoops, thanks for fixing. Committed/pushed to 10.1.x and cherry-picked back to 9.4.x again.
Comment #76
claudiu.cristeaThis change broke the
rdf_taxonomysub-module of https://www.drupal.org/project/rdf_entity:Specifically, we're swapping the storage of the
taxonomy_termentity in order to store the terms in a triplestore backend. Along with this, the TIDs are strings (URIs), not integers. Casting here as integers is prohibiting us to useTermFormas it is.At least, is it possible to move the parents computing in a protected method, so it would make easier to extend the class w/o copy/paste the whole
TermForm::form()method?Comment #77
claudiu.cristeaI've created #3332877: Added TermForm::getParentIds for allowing to override in contrib to fix the issue.