Problem/Motivation
1. Basic behavior of comment_entity_statistics database table
1.1. When a content type has a comment field and a new entity (node in this example) is created, we save a new entry to comment_entity_statistics. When the node has no comments, cid and comment_count are 0.
1.2. When comments are added to this node, the entry for the same entity_id is updated with a reference to the cid and comment_count is updated.
1.3. When a content type does not have comment fields, no entries are created to comment_entity_statistics.
2. Comments and entries in comment_entity_statistic are not deleted after the comment field instance is deleted
2.1. Create a new comment field instance to a content type.
2.2. Create a new node for this content type.
- An entry is created to comment_entity_statistics as expected. cid and comment_count are 0 as expected.
- This is the same thing as in step 1.1.
Also add a new comment to this node that you just created.
2.3. Delete the comment field instance from this content type.
2.5. Notice that the comments are not deleted. Also notice that the entry from step 2.2 remains in comment_entity_statistics.
- When the comment field instance is deleted from a content type, the actual comments are not deleted from the database as expected. The comments are listed on admin/content/comment and they can be manually deleted from there.
- This are also orphan entries left in comment_entity_statistics. The comment field instance field_example_2 has been deleted and the entry is comment_entity_statistics should not be there anymore.
- Additional observation: It is not possible to delete a comment type when there are comment field instances that use the comment type. This part is expected behavior.
Proposed resolution
1. Improve the admin UI so that when the comment field is deleted, the site builder is explicetly warned that all comements of that comment field will be deleted.
- This part is handled separately in the child issue #2908607: Show warning when comment field is about to be deleted
2. When a comment field instance is deleted, all comments of that of that comment field instance should be deleted as well. Otherwise we leave orphan comments in the database. We need to pay special attention for entity types which can have bundles (e.g. node content types) so that if the comment field was deleted from bundle A (e.g. content type A) and the same comment field was also used on bundle B (e.g. content type B), the comments should only be deleted from A. Not all entity types (e.g. User) support this kind of bundling.
3. When a comment field instance is deleted, we must also make sure to delete all relevant records from comment_entity_statistics. Special attention must be paid for the bundling as described above.
Note:
- Changes 2 and 3 are handled under this parent issue 2906470.
- Per to #16-18 the comments should be deleted using batching instead of directly deleting them from the hook_ENTITY_ID_delete implementation.
Needed test cases for 2 and 3: See comment #12.
Important relation to getting experimental core module Migrate Drupal stable
The proposed change 2 and 3 are very important for Migrate Drupal which is currently still an experimental core module. There is currently an open issue which has everything to do with comment_entity_statistics, see #2853872: Migration for forum and article comments: duplicate comment types and incorrect comment_entity_statistics
The problematic part why the proposed change #2-3 is a pre-requisite for getting Migrate Drupal stable is as follows. For longer discussion on the topic, please refer to #2853872 from comment #68 onwards.
- The difficult part here from the migration point of view is that Drupal 8 Standard installation profile comes with a predefined comment type called comment for Article content type. This is specific to Drupal 8 Standard installation profile; migrations can't assume that the Drupal 8 site was installed using Standard installation profile. No other migration has special handling which would be installation profile specific.
- When migrating the comment types from Drupal 7, the migrations are creating a separate comment type for each content type.
The pattern is comment_node_{node_type}, for example comment_node_page and comment_node_article. All comments (except Forum comments, see below) are migrated to these comment field instances. - Forum comments are also diffiicult migration wise because D8 Forum module uses its own comment type called comment_forum. There is an important difference to the D8 Standard Article comments though, and that is that the comment_forum is created when D8 Forum module is installed and hence it is the same for all installation profiles. Hence, the migrations can safely assume that comments for Forum nodes must be migrated to comment_forum in D8.
- The migration issue #2853872: Migration for forum and article comments: duplicate comment types and incorrect comment_entity_statistics is exceptionally difficult to resolve because of the D8 Standard Article comment type. To keep the migrations maintainable, the approach where #2853872 is heading is as follows:
- We let the comment_type, comment_field and comment_field_instance migrations to create comment_node_article even though the D8 site might already have the comment comment type for Article.
- We migrate all D7 Article comments to comment_node_article comment field instance.
- We guide the site builders who use D8 Standard installation profile to manually delete the comment comment field instance from Article content type.
- Now, the problem is that when the site builder deletes the comment comment field instance from Article, the row from comment_entity_statistics is *not* deleted as described in step 2.5 above.
- The orphan records in comment_entity_statistics screw up Views if the view has for example the last updated / commented date field. By screw up we mean that every Article node is listed twice in the View results.
Remaining tasks
Patch
Add tests
Review
Commit
User interface changes
None.
API changes
None.
Data model changes
None.
Original report by masipila
See comment #90 of issue #2853872.
| Comment | File | Size | Author |
|---|---|---|---|
| #32 | 2906470-32.patch | 2.24 KB | andypost |
| #32 | 2906470-interdiff-14.txt | 2.2 KB | andypost |
Comments
Comment #2
masipila commentedAdding tag Migrate Drupal which indicates that this is a blocker for Migrate Drupal becoming stable.
Comment #3
dillix commented@masipila maybe we should add backport tag for version to 8.4.x?
Comment #4
heddnThis is effecting migrate drupal because if a user doesn't delete the base article comment field from the standard install profile, this could/would effect them.
Comment #5
masipila commentedI checked the behavior of other field types when the field instance is deleted. When there is still content left in the database for the field in question, there is no other warning to the site builder than Are you sure you want to delete the field {field_name}? This action cannot be undone.
There is no need to have more warnings for comment field instance deletions when there are still comments left in the database like I originally proposed. Issue summary updated accordingly.
Comment #6
masipila commentedFirst observations.
When the comment field is deleted, hook implementation comment_field_config_delete is invoked.
This attempts to delete all comments of the comment field instance.
Unfortunately this fails to delete any comments because the query seems to return an empty result set. This seems to be because of
$entity_query->condition('entity_type', $field->getEntityTypeId());When we modify this query a bit, we can get the comments deleted as expected. The only thing that we need to be super careful with is that the same comment field can be re-used on multiple content types. For example, the D8 standard comment comment field can be re-used on multiple content types and we need to make sure that we are limiting the deletion to just the content type where we removed the comment field from.
Deleting the entries from comment_entity_statistics is going to be difficult for this same reason. The field_name is too broad WHERE clause because we only want to delete the entries of that content type where the comment field was deleted from.
I can try to work out with the patch in the next couple of days. If somebody else wants to pick this first, feel free to do so. Just assign this to yourself so that we are not doing double effort on this. I'll assign this to myself when I have time to dig deeper...
Cheers,
Markus
Comment #7
dillix commented@masipila Will your proposed solution work for already migrated sites? Or it for new ones?
Comment #8
masipila commentedRe: #7.
This issue will resolve the issue for Article content type (when using D8 Standard) even if the site was migrated earlier. After this issue is resolved, the site builder can delete the comment comment field from Article and that will remove the duplicate entries from comment_entity_statistics. The deletion of comment comment field of Article should be safe to do because the comments were migrated to a comment field comment_node_article.
This issue will not help for Forum comments that were migrated earlier. The reason is that comment migration incorrectly migrated the Forum comments to comment_node_forum instead of comment_forum. #2853872: Migration for forum and article comments: duplicate comment types and incorrect comment_entity_statistics will fix that Forum comments will be migrated correctly after #2853872 lands but even that will not fix the already migrated Forum comments.
The Forum comment topic is anyway in the scope of #2853872, not this issue.
Cheers,
Markus
Comment #9
masipila commentedUpdated the issue title to better describe the two issues we have here:
1) Comments are not deleted when the comment field is deleted
2) We are also leaving orphan entries to comment_entity_statistics
Comment #10
masipila commentedComment #11
masipila commentedI'll most probably have time this week to write the first patch.
Notes to self for the patch:
Hook implememtation for comment_field_config_delete()
We need to have two parts here:
1. First find all comments where a) comment field name equals the comment field instance that was deleted and b) bundle (for example content type) equals the bundle where the comment field instance was deleted from. Then delete these comments with entity_delete_multiple like we try to do now.
2. comment_entity_statistics table alone doesn't have all the information that is needed for deleting the data from that table. The reason is that field_name is too broad selection criteria due to a fact that a comment field can be used on multiple bundles (e.g. node content types).
We know the bundle (e.g. node content type) where the comment field was deleted from. We also know the comment field_name. Therefore:
First obtain a list of entity_ids (for example node ids) of the bundle where the comment field was deleted from. Then, delete all records from comment_entity_statistics where entity_id is on this list AND comment field_name is the comment field which was just deleted.
Comment #12
masipila commentedThe attached patch should do the trick.
Setting to Needs Review to get feedback on the approach. Tests are not included, I'll have to leave that to someone who is more experienced with test automation. Please set this back to Needs work at least for the test but possibly also for other needed updates.
I would like to thank heddn for IRC mentoring regarding the "bundleability" of different entity types. heddn++
Proposed test cases:
1. Comment field shared between two node content types
2. Content type has two comment fields
3. User comments
Cheers,
Markus
Comment #13
heddnNo need to number the comments. If additional code is ever added, then the numbers will get off. Just put these comments in sentence format. See https://www.drupal.org/docs/develop/coding-standards/api-documentation-a...
These are all chainable. No need to create a query object.
i.e.
Comment #14
masipila commentedThanks for your review heddn!
Cheers,
Markus
Comment #15
masipila commentedChanged the version to 8.4.x. Reasons:
1) This bug leads to orphan entries in the database. I'm not quite sure if orphan entries in the database are considered as corruption of stored data which would justify this to be critical. I'll leave this to major even though the corrupted / orphan entries in comment_entity_statistics do cause issues with for example views that have last commented / updated field.
2) As long as this bug is present the upgrade path to D8 is broken if D8 site was installed using Standard install profile and the site uses Article content type with comments (see issue summary for further details on this aspect).
3) Because of 2, this blocks migrate drupal from being stable in core.
Cheers,
Markus
Comment #16
andypostJust read awesome summary! I'm sure this elephant needs split
1) Migrate part already #2853872: Migration for forum and article comments: duplicate comment types and incorrect comment_entity_statistics
2) Clean-up of comments & statistics
3) Forum case
Clean-up also needs split basically because we can't delete unpredictable amount of comment entities in one request.
I'd prefer to take the same approach as core use - delete orphans by cron job
But first is UI - we need to Warn user that comments (if exists) will be lost! Node module already do that so comment must as well, and deletion of comment type could be more friendly (separate task)
Then if user using admin UI we can start batch to clean-up all comments & statistics
For drush case that could be done in one request but deleting entities can trouble cache #2558857: Migrations invalidate entity caches when trying to reclaim memory, should flush
Comment #17
larowlanI agree with @andypost on this one. Thanks
Comment #18
masipila commentedHi @andypost and @larowlan!
Re: #16-17 and the proposed split.
Re: 16.1: I think we have a consensus that the migration part should be handled under #2853872: Migration for forum and article comments: duplicate comment types and incorrect comment_entity_statistics.
Re: 16.3: I don't see how Forum would need separate handling for this issue which is about deleting *any* comment field. If you were referring to the migration of Forum comments, that should be covered under #2853872: Migration for forum and article comments: duplicate comment types and incorrect comment_entity_statistics.
To summarize the remaining tasks (from 16.2)
1. Enhance the UI for comment field deletion
2. Handle the deletion of comments and comment statistics as a batch job
comment_field_config_delete@andypost, @larowlan: could you please review and confirm that this is the approach you prefer? I can then update the issue summary accordingly.
Cheers,
Markus
Comment #19
larowlanYep, that sounds good to me.
Comment #20
masipila commentedChild issue #2908607: Show warning when comment field is about to be deleted created for the improved UI part and issue summary updated to reflect #16-19.
Comment #21
andypostComment #22
masipila commented@andypost, I read through the related issue that you mentioned: #2282119: Make the Entity Field API handle field purging
That looks really promising. However, it has a separate follow-up issue for bundle fields, see #2907780: Add a field purger service. I read through that as well and my understanding is that we need that as well.
Before postponing this issue on those two, could you please check if this also your understanding so that we don't postpone this for nothing?
Cheers,
Markus
Edit: fixed the related issue for purging bundle fields, I originally linked to an incorrect issue.
Comment #23
masipila commentedComment #24
masipila commentedRaised to critical as per webchick's comment here: https://www.drupal.org/node/2853872
Markus
Comment #25
masipila commented#2282119: Make the Entity Field API handle field purging just landed but my understanding is that we still need #2907780: Add a field purger service.
Comment #26
amateescu commentedThe ability to delete bundle fields was committed as part of #2282119: Make the Entity Field API handle field purging so there's no need to wait on anything else :)
Comment #27
masipila commentedHi all,
amateescu or anyone else, could you please bump me into the correct direction so that I could give this another shot?
Previously, the patch #14 implemented hook_ENTITY_ID_delete which was invoked when a comment field instance was deleted. Now that we have #2282119: Make the Entity Field API handle field purging, I understood that we should have improved capabilities to delete the comments when the comment field instance is deleted.
By reading the change record and issue summary of #2282119: Make the Entity Field API handle field purging, it is unfortunately not clear to me how this should be implemented. Could somebody clarify this a bit? We're trying to get the Migrate Drupal stable in core and as mentioned in the issue summary, this issue is a blocker for that.
Summary
When a comment field instance is deleted from a bundle, the comments of that field must be deleted. Could someone please give a piece of advice what is the proper way to do that?
Cheers,
Markus
Comment #28
amateescu commented@masipila, the field purging process works by invoking the
delete()method on a field item list class, which, by default, delegates the call to each field item.In this case, you should be able to implement the
delete()method in\Drupal\comment\Plugin\Field\FieldType\CommentItem, where you have access to$this->cid. Now, I see that thecidproperty from\Drupal\comment\Plugin\Field\FieldType\CommentItem::propertyDefinitions()says it's the "Last comment ID", so I'm not sure if that is very useful or not for deleting all the comments from the field instance that was removed.Probably a maintainer of the comment module which knows its architecture better than me would be able to give a better direction for this issue...
Comment #30
dillix commentedThis issue is really annoyed. After migration comment field and comment type was created for every content type. We deleted fields from node types which not need comments. But we cant delete comment types.
Comment #31
andypostThis is wrong! In this hook deleted field, not field storage that affects all bundles!
This "IN" must be replaced by subquery because each database type has own limits for number of items that can pass to "in"
Comment #32
andypostIgnore #31.1
Patch fixes lost "entity_type" condition for comments & adds subquery for entities
Comment #33
masipila commentedHi, thanks for taking the time @andypost for this issue!
I'm a bit confused, though. In #16 your guidance was to NOT delete the database entries directly from a hook implementation but using the Field API purging...?
Markus
Comment #34
andypost@masipila I still have no idea how clean-up could be made on cron run, basically you will have comments which broken to display
Also comment field could be deleted by config sync so the database could be in unpredictable state
How we can allow load comments to delete if there's no field they attacjed to?
Comment #35
dillix commentedI think we also need to delete orphan comments when we delete comment field from entity or when we delete comment type.
Comment #36
catchThe number of potential comments on a comment field are unbounded, so we can't delete them in the API - the best we could do is batch operation in the UI.
For most situations like this we've taken the opposite approach - prevent deletion of configuration if there is content that depends on it, this allows an administrator to bulk-delete the comments then delete the field afterwards.
Comment #39
dawehneri do agree 100% with catch's comment. We should not automatically delete comments. Looking at
\Drupal\comment\Form\CommentTypeDeleteForm::buildFormthough we already invalidate whether there are remaining comments / comment field usages. Nevertheless the comment_entity_statistics entry is still filled out.Maybe for
comment_entity_statisticsyou could argue though that it's just an automatic aggregation which means it would be okay to automatically clean up.Comment #41
catchThis isn't actually deleting the comments, it's only deleting the comment statistics, might just need to update the comment although still needs test coverage.
Also wondering whether we should try to clean up the table on sites that already have this problem, although that could be a follow-up.
Comment #46
stephencamilo commentedComment #47
larowlan