Problem/Motivation

Coming from #3566536: [meta] eliminate core .module files

The user account cancellation feature looks like is left behind but is also buggy (see #3135592: Cannot implement a custom user cancellation method). There is also #3043725: Provide a Entity Handler for user cancelation, which aims to give entity types a mechanism to react to user deletion.

Proposed resolution

  • Create a new AccountCancellation service to replace all procedural code dealing with user account cancellation.
  • Convert account cancellation methods to plugins. This would also solve #3135592: Cannot implement a custom user cancellation method).
  • Deprecate hook_user_cancel_methods_alter() hook. Any custom cancel method should create a plugin. Altering existing methods is done by altering the plugin definitions.
  • Provide BC

Note that this refactoring is not replacing #3043725: Provide a Entity Handler for user cancelation, but is complimentary to that. However, is solving the bug from #3135592: Cannot implement a custom user cancellation method.

Remaining tasks

None.

User interface changes

None.

Introduced terminology

None.

API changes

See the change record

Data model changes

None.

Issue fork drupal-3580682

Command icon 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:

Comments

claudiu.cristea created an issue. See original summary.

claudiu.cristea’s picture

Title: Create a service for use cancelation » Create a service for user account cancellation
claudiu.cristea’s picture

function user_cancel($edit, $uid, $method): void {
  ...
}

The 1st argument seems to me a relic from ancestral Drupal versions. Is mixing UI/form with API. User cancellation seems more an API. It's not used in core but is it used in contrib? A search shows ~120 hook implementations. Maybe we should deprecate passing this argument or name it $context?

claudiu.cristea’s picture

The code evolved in a more in-deep direction

claudiu.cristea’s picture

Issue tags: +Needs tests

I think with the new architecture, the current tests are not enough

claudiu.cristea’s picture

Title: Create a service for user account cancellation » Create a service for user account cancellation. Convert cancel methods to plugins
Issue summary: View changes
Issue tags: -Needs change record, -Needs issue summary update, -Needs title update
Related issues: +#3135592: Cannot implement a custom user cancellation method, +#3043725: Provide a Entity Handler for user cancelation
claudiu.cristea’s picture

Assigned: claudiu.cristea » Unassigned
Status: Active » Needs review
Issue tags: -Needs tests +Needs subsystem maintainer review

Added tests for a custom cancellation method (the lack of such a test made possible #3135592: Cannot implement a custom user cancellation method)

Given this is an architectural change, I'm tagging with "Needs subsystem maintainer review". Also, a question remains whether user_cancel_url() deprecation is related to this change.

nicxvan’s picture

This is huge, but I don't see a logical way to split it up to be honest.

This will definitely need subsystem and maybe framework manager review.

Honestly as part of the.module elimination we try to keep our touch as light as possible, but I think this functionality is one of the ones we should update fully.

I took a really high level look and it makes sense to me, but I definitely want to do a deeper review.

solideogloria’s picture

The 1st argument seems to me a relic from ancestral Drupal versions.

Yeah, I definitely wouldn't keep it as $edit. It's a Drupal 7 and earlier thing. Renaming should be done, at least, if it's not removed during the changes.

claudiu.cristea’s picture

Issue summary: View changes

Small IS fixes

kristiaanvandeneynde’s picture

I like that we want to put the cancellation methods into plugins. This makes a lot of sense and allows for way more flexibility when trying to offer other ways of cancellation.

Having said that, the fact that #3043725: Provide a Entity Handler for user cancelation exists must be taken into account here. It's not something we can just fix after this issue lands, only to then realize we made the API hard to work with.

Ideally, we step away from the notion of only being able to choose one cancellation method altogether. Instead, we should have a bunch of granular plugins that do one thing and one thing only, i.e.:

  • Block the account
  • Delete the account
  • Unpublish content
  • Reassign content
  • Etc.

Then the form should allow you to choose one or multiple actions as you cancel an account. This means we will not have a mess of plugins that are 90% similar but yet slightly different because we needed most of another plugin's behavior with this one special change. We could simply combine the pieces we do want with one custom piece that is specific to our site.

If we were to achieve this, then the entity handler from the other issue could be as simple as checking whether the reassign_content (or whatever) plugin was used, get the necessary metadata from said plugin and go to town. This would work with all possible combinations of plugins and only if you wanted a custom behavior other than reassigning, would you have to overwrite the default entity handler's behavior.

But then you'd fall back into the trap we still have of only one module being able to swap out an entity handler. A problem I have long fixed in Group by making handlers decoratable services. So that won't do either. Which means we'd rather have two methods on an optional UserCancelEntityImpactInterface (or whatever) that the plugins can implement instead:

public function shouldAlterEntities(EntityTypeInterface $entity_type): bool;
public function alterEntities(EntityTypeInterface $entity_type): void;

Now the solution is simple: If a cancel plugin was selected that implements the UserCancelEntityImpactInterface, the entity handler passes its entity type definition to the plugin to see if it's interested. This could be by checking for owner interface, published interface, etc. Then, if interested, do we pass the entity type definition again, allowing the plugin to grab the storage and start doing the heavy lifting.

So, long story short:

  1. Plugins must be additive, not mutually exclusive
  2. An optional interface must exist, solving #3043725: Provide a Entity Handler for user cancelation
  3. I suck at naming things, feel free to improve
kristiaanvandeneynde’s picture

To reduce scope creep, we may want to push ahead with the current MR under the following schedule:

  • Step 1: Convert current code to plugins like the MR does, leave it at that.
  • Step 2: Fix #3043725: Provide a Entity Handler for user cancelation the way I suggested by having these plugins implement an interface and then checking for that. This removes the burden from the entity type modules by centralizing it.
  • Step 3: Stop checking for plugin ID as a means to identify cancel methods, rely on interfaces altogether
  • Step 4: Now that we have plugins (and people can provide their own) and a way to make plugins act on entities, revisit the idea of making them smaller and easier to work with and rework the UI

I'd love to see a PoC MR on Step 2 as soon as we have a fully reviewed MR here just so we can see if it all works the way we expect before committing to an API here, but that would not be a hard blocker for me as I understand it's asking for even more of people's time. It would be a nice-to-have for sure, though.

znerol’s picture

Left a couple of suggestions. Feel free to ignore any/all of them.

needs-review-queue-bot’s picture

Status: Needs review » Needs work
StatusFileSize
new91 bytes

The Needs Review Queue Bot tested this issue. It no longer applies to Drupal core. Therefore, this issue status is now "Needs work".

This does not mean that the patch necessarily needs to be re-rolled or the MR rebased. Read the Issue Summary, the issue tags and the latest discussion here to determine what needs to be done.

Consult the Drupal Contributor Guide to find step-by-step guides for working with issues.