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