1<?php 2 3namespace Drupal\content_translation\Access; 4 5use Drupal\content_translation\ContentTranslationManager; 6use Drupal\content_translation\ContentTranslationManagerInterface; 7use Drupal\Core\Access\AccessResult; 8use Drupal\Core\Entity\ContentEntityInterface; 9use Drupal\Core\Entity\EntityTypeManagerInterface; 10use Drupal\Core\Routing\Access\AccessInterface; 11use Drupal\Core\Routing\RouteMatchInterface; 12use Drupal\Core\Session\AccountInterface; 13use Drupal\language\Entity\ContentLanguageSettings; 14use Drupal\workflows\Entity\Workflow; 15 16/** 17 * Access check for entity translation deletion. 18 * 19 * @internal This additional access checker only aims to prevent deletions in 20 * pending revisions until we are able to flag revision translations as 21 * deleted. 22 * 23 * @todo Remove this in https://www.drupal.org/node/2945956. 24 */ 25class ContentTranslationDeleteAccess implements AccessInterface { 26 27 /** 28 * The entity type manager. 29 * 30 * @var \Drupal\Core\Entity\EntityTypeManagerInterface 31 */ 32 protected $entityTypeManager; 33 34 /** 35 * The content translation manager. 36 * 37 * @var \Drupal\content_translation\ContentTranslationManagerInterface 38 */ 39 protected $contentTranslationManager; 40 41 /** 42 * Constructs a ContentTranslationDeleteAccess object. 43 * 44 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $manager 45 * The entity type manager. 46 * @param \Drupal\content_translation\ContentTranslationManagerInterface $content_translation_manager 47 * The content translation manager. 48 */ 49 public function __construct(EntityTypeManagerInterface $manager, ContentTranslationManagerInterface $content_translation_manager) { 50 $this->entityTypeManager = $manager; 51 $this->contentTranslationManager = $content_translation_manager; 52 } 53 54 /** 55 * Checks access to translation deletion for the specified route match. 56 * 57 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match 58 * The parameterized route. 59 * @param \Drupal\Core\Session\AccountInterface $account 60 * The currently logged in account. 61 * 62 * @return \Drupal\Core\Access\AccessResultInterface 63 * The access result. 64 */ 65 public function access(RouteMatchInterface $route_match, AccountInterface $account) { 66 $requirement = $route_match->getRouteObject()->getRequirement('_access_content_translation_delete'); 67 $entity_type_id = current(explode('.', $requirement)); 68 $entity = $route_match->getParameter($entity_type_id); 69 return $this->checkAccess($entity); 70 } 71 72 /** 73 * Checks access to translation deletion for the specified entity. 74 * 75 * @param \Drupal\Core\Entity\ContentEntityInterface $entity 76 * The entity translation to be deleted. 77 * 78 * @return \Drupal\Core\Access\AccessResultInterface 79 * The access result. 80 */ 81 public function checkAccess(ContentEntityInterface $entity) { 82 $result = AccessResult::allowed(); 83 84 $entity_type_id = $entity->getEntityTypeId(); 85 $result->addCacheableDependency($entity); 86 // Add the cache dependencies used by 87 // ContentTranslationManager::isPendingRevisionSupportEnabled(). 88 if (\Drupal::moduleHandler()->moduleExists('content_moderation')) { 89 foreach (Workflow::loadMultipleByType('content_moderation') as $workflow) { 90 $result->addCacheableDependency($workflow); 91 } 92 } 93 if (!ContentTranslationManager::isPendingRevisionSupportEnabled($entity_type_id, $entity->bundle())) { 94 return $result; 95 } 96 97 if ($entity->isDefaultTranslation()) { 98 return $result; 99 } 100 101 $config = ContentLanguageSettings::load($entity_type_id . '.' . $entity->bundle()); 102 $result->addCacheableDependency($config); 103 if (!$this->contentTranslationManager->isEnabled($entity_type_id, $entity->bundle())) { 104 return $result; 105 } 106 107 /** @var \Drupal\Core\Entity\ContentEntityStorageInterface $storage */ 108 $storage = $this->entityTypeManager->getStorage($entity_type_id); 109 $revision_id = $storage->getLatestTranslationAffectedRevisionId($entity->id(), $entity->language()->getId()); 110 if (!$revision_id) { 111 return $result; 112 } 113 114 /** @var \Drupal\Core\Entity\ContentEntityInterface $revision */ 115 $revision = $storage->loadRevision($revision_id); 116 if ($revision->wasDefaultRevision()) { 117 return $result; 118 } 119 120 $result = $result->andIf(AccessResult::forbidden()); 121 return $result; 122 } 123 124} 125