6a4be1eb11fe0f94be9b1594298a03aff9087d08
[yaffs-website] / web / core / modules / content_translation / src / Access / ContentTranslationManageAccessCheck.php
1 <?php
2
3 namespace Drupal\content_translation\Access;
4
5 use Drupal\Core\Access\AccessResult;
6 use Drupal\Core\Entity\EntityManagerInterface;
7 use Drupal\Core\Language\LanguageInterface;
8 use Drupal\Core\Language\LanguageManagerInterface;
9 use Drupal\Core\Routing\Access\AccessInterface;
10 use Drupal\Core\Routing\RouteMatchInterface;
11 use Drupal\Core\Session\AccountInterface;
12 use Symfony\Component\Routing\Route;
13
14 /**
15  * Access check for entity translation CRUD operation.
16  */
17 class ContentTranslationManageAccessCheck implements AccessInterface {
18
19   /**
20    * The entity type manager.
21    *
22    * @var \Drupal\Core\Entity\EntityManagerInterface
23    */
24   protected $entityManager;
25
26   /**
27    * The language manager.
28    *
29    * @var \Drupal\Core\Language\LanguageManagerInterface
30    */
31   protected $languageManager;
32
33   /**
34    * Constructs a ContentTranslationManageAccessCheck object.
35    *
36    * @param \Drupal\Core\Entity\EntityManagerInterface $manager
37    *   The entity type manager.
38    * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
39    *   The language manager.
40    */
41   public function __construct(EntityManagerInterface $manager, LanguageManagerInterface $language_manager) {
42     $this->entityManager = $manager;
43     $this->languageManager = $language_manager;
44   }
45
46   /**
47    * Checks translation access for the entity and operation on the given route.
48    *
49    * @param \Symfony\Component\Routing\Route $route
50    *   The route to check against.
51    * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
52    *   The parametrized route.
53    * @param \Drupal\Core\Session\AccountInterface $account
54    *   The currently logged in account.
55    * @param string $source
56    *   (optional) For a create operation, the language code of the source.
57    * @param string $target
58    *   (optional) For a create operation, the language code of the translation.
59    * @param string $language
60    *   (optional) For an update or delete operation, the language code of the
61    *   translation being updated or deleted.
62    * @param string $entity_type_id
63    *   (optional) The entity type ID.
64    *
65    * @return \Drupal\Core\Access\AccessResultInterface
66    *   The access result.
67    */
68   public function access(Route $route, RouteMatchInterface $route_match, AccountInterface $account, $source = NULL, $target = NULL, $language = NULL, $entity_type_id = NULL) {
69     /* @var \Drupal\Core\Entity\ContentEntityInterface $entity */
70     if ($entity = $route_match->getParameter($entity_type_id)) {
71       $operation = $route->getRequirement('_access_content_translation_manage');
72       $language = $this->languageManager->getLanguage($language) ?: $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT);
73       $entity_type = $this->entityManager->getDefinition($entity_type_id);
74
75       if (in_array($operation, ['update', 'delete'])) {
76         // Translation operations cannot be performed on the default
77         // translation.
78         if ($language->getId() == $entity->getUntranslated()->language()->getId()) {
79           return AccessResult::forbidden()->addCacheableDependency($entity);
80         }
81         // Editors have no access to the translation operations, as entity
82         // access already grants them an equal or greater access level.
83         $templates = ['update' => 'edit-form', 'delete' => 'delete-form'];
84         if ($entity->access($operation) && $entity_type->hasLinkTemplate($templates[$operation])) {
85           return AccessResult::forbidden()->cachePerPermissions();
86         }
87       }
88
89       if ($account->hasPermission('translate any entity')) {
90         return AccessResult::allowed()->cachePerPermissions();
91       }
92
93       /* @var \Drupal\content_translation\ContentTranslationHandlerInterface $handler */
94       $handler = $this->entityManager->getHandler($entity->getEntityTypeId(), 'translation');
95
96       // Load translation.
97       $translations = $entity->getTranslationLanguages();
98       $languages = $this->languageManager->getLanguages();
99
100       switch ($operation) {
101         case 'create':
102           $source_language = $this->languageManager->getLanguage($source) ?: $entity->language();
103           $target_language = $this->languageManager->getLanguage($target) ?: $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT);
104           $is_new_translation = ($source_language->getId() != $target_language->getId()
105             && isset($languages[$source_language->getId()])
106             && isset($languages[$target_language->getId()])
107             && !isset($translations[$target_language->getId()]));
108           return AccessResult::allowedIf($is_new_translation)->cachePerPermissions()->addCacheableDependency($entity)
109             ->andIf($handler->getTranslationAccess($entity, $operation));
110
111         case 'delete':
112         case 'update':
113           $has_translation = isset($languages[$language->getId()])
114             && $language->getId() != $entity->getUntranslated()->language()->getId()
115             && isset($translations[$language->getId()]);
116           return AccessResult::allowedIf($has_translation)->cachePerPermissions()->addCacheableDependency($entity)
117             ->andIf($handler->getTranslationAccess($entity, $operation));
118       }
119     }
120
121     // No opinion.
122     return AccessResult::neutral();
123   }
124
125 }