0

I have defined a custom content entity. (You may find the details below.) If I create an entry in the table and a translation for the entry and then delete the translation it removes the entire entry.

/**
 * @ContentEntityType(
 *   id = "my_custom_entity",
 *   label = @Translation("My Custom Entity"),
 *   handlers = {
 *     "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage",
 *     "access" = "Drupal\my_custom_entity\MyCustomEntityAccessControlHandler",
 *     "form" = {
 *       "default" = "Drupal\my_custom_entity\Form\MyCustomEntityForm",
 *       "delete" = "Drupal\my_custom_entity\Form\MyCustomEntityDeleteForm",
 *     },
 *     "list_builder" = "Drupal\my_custom_entity\Entity\Controller\MyCustomEntityListBuilder",
 *     "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
 *     "views_data" = "Drupal\my_custom_entity\MyCustomEntityViewsData",
 *     "translation" = "Drupal\content_translation\ContentTranslationHandler"
 *   },
 *   translatable = TRUE,
 *   base_table = "my_custom_entity",
 *   data_table = "my_custom_entity_field_data",
 *   fieldable = FALSE,
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "label",
 *     "langcode" = "langcode"
 *   },
 *   links = {
 *     "canonical" = "/my_custom_entity/{my_custom_entity}",
 *     "edit-form" = "/my_custom_entity/{my_custom_entity}/edit",
 *     "delete-form" = "/my_custom_entity/{my_custom_entity}/delete",
 *     "collection" = "/my_custom_entity/list"
 *   },
 *   list_cache_contexts = {"user"}
 * )
 */

Update: I've made a bit of progress on this. The issue seems to be that the entity provides a delete-form. On account of this core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck::access ends up returning AccessResult::forbidden() on line 85 (Drupal 8.3.7) when looking at the path /my_custom_entity/{my_custom_entity}/translations/delete/{language}. Instead it uses /my_custom_entity/{my_custom_entity}/delete. Now I've got to figure out what I'm supposed to do instead. The User entity does not declare a delete-form, but the Node entity does. My initial attempt at removing the delete-form key on my entity resulted in Uncaught PHP Exception Symfony\\Component\\Routing\\Exception\\RouteNotFoundException: "Route "entity.my_custom_entity.delete_form" does not exist." at /var/www/html/drupal8/core/lib/Drupal/Core/Routing/RouteProvider.php line 190. However, I didn't actually uninstall and reinstall the module. I just visited the Extend page and cleared cache.

0

TL;DR: Extend ContentEntityDeleteForm instead of ContentEntityConfirmFormBase.

The solution was to pattern my approach after the way Node and Taxonomy Terms create their delete forms. I changed my delete form to extend ContentEntityDeleteForm instead of extending ContentEntityConfirmFormBase. Look at ContentEntityDeleteForm::submitForm

// Make sure that deleting a translation does not delete the whole entity.
if (!$entity->isDefaultTranslation()) {
  $untranslated_entity = $entity->getUntranslated();
  $untranslated_entity->removeTranslation($entity->language()->getId());
  $untranslated_entity->save();
  $form_state->setRedirectUrl($untranslated_entity->urlInfo('canonical'));
}
else {
  $entity->delete();
  $form_state->setRedirectUrl($this->getRedirectUrl());
}

It explicitly takes care not to delete the whole entity when you are deleting a translation.

ContentEntityConfirmFormBase inherits the ContentEntityForm::submitForm method, which in turn executes the EntityForm::submitForm method. The entity never gets deleted anywhere in that process. Thus, I needed to override the submitForm method in my class. I hadn't included the necessary logic to account for translations, though. Rather than reproducing the necessary logic in an overridden submitForm method, it made more sense to change the class that I was extending.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.