Mercurial > hg > isophonics-drupal-site
comparison core/lib/Drupal/Core/ParamConverter/EntityConverter.php @ 14:1fec387a4317
Update Drupal core to 8.5.2 via Composer
author | Chris Cannam |
---|---|
date | Mon, 23 Apr 2018 09:46:53 +0100 |
parents | 4c8ae668cc8c |
children | af1871eacc83 |
comparison
equal
deleted
inserted
replaced
13:5fb285c0d0e3 | 14:1fec387a4317 |
---|---|
2 | 2 |
3 namespace Drupal\Core\ParamConverter; | 3 namespace Drupal\Core\ParamConverter; |
4 | 4 |
5 use Drupal\Core\Entity\EntityInterface; | 5 use Drupal\Core\Entity\EntityInterface; |
6 use Drupal\Core\Entity\EntityManagerInterface; | 6 use Drupal\Core\Entity\EntityManagerInterface; |
7 use Drupal\Core\Entity\RevisionableInterface; | |
8 use Drupal\Core\Entity\TranslatableRevisionableInterface; | |
9 use Drupal\Core\Language\LanguageInterface; | |
10 use Drupal\Core\Language\LanguageManagerInterface; | |
7 use Drupal\Core\TypedData\TranslatableInterface; | 11 use Drupal\Core\TypedData\TranslatableInterface; |
8 use Symfony\Component\Routing\Route; | 12 use Symfony\Component\Routing\Route; |
9 | 13 |
10 /** | 14 /** |
11 * Parameter converter for upcasting entity IDs to full objects. | 15 * Parameter converter for upcasting entity IDs to full objects. |
33 * options: | 37 * options: |
34 * parameters: | 38 * parameters: |
35 * example: | 39 * example: |
36 * type: entity:{entity_type} | 40 * type: entity:{entity_type} |
37 * @endcode | 41 * @endcode |
42 * | |
43 * If your route needs to support pending revisions, you can specify the | |
44 * "load_latest_revision" parameter. This will ensure that the latest revision | |
45 * is returned, even if it is not the default one: | |
46 * @code | |
47 * example.route: | |
48 * path: foo/{example} | |
49 * options: | |
50 * parameters: | |
51 * example: | |
52 * type: entity:node | |
53 * load_latest_revision: TRUE | |
54 * @endcode | |
55 * | |
56 * When dealing with translatable entities, the "load_latest_revision" flag will | |
57 * make this converter load the latest revision affecting the translation | |
58 * matching the content language for the current request. If none can be found | |
59 * it will fall back to the latest revision. For instance, if an entity has an | |
60 * English default revision (revision 1) and an Italian pending revision | |
61 * (revision 2), "/foo/1" will return the former, while "/it/foo/1" will return | |
62 * the latter. | |
63 * | |
64 * @see entities_revisions_translations | |
38 */ | 65 */ |
39 class EntityConverter implements ParamConverterInterface { | 66 class EntityConverter implements ParamConverterInterface { |
40 | 67 |
41 /** | 68 /** |
42 * Entity manager which performs the upcasting in the end. | 69 * Entity manager which performs the upcasting in the end. |
44 * @var \Drupal\Core\Entity\EntityManagerInterface | 71 * @var \Drupal\Core\Entity\EntityManagerInterface |
45 */ | 72 */ |
46 protected $entityManager; | 73 protected $entityManager; |
47 | 74 |
48 /** | 75 /** |
76 * The language manager. | |
77 * | |
78 * @var \Drupal\Core\Language\LanguageManagerInterface | |
79 */ | |
80 protected $languageManager; | |
81 | |
82 /** | |
49 * Constructs a new EntityConverter. | 83 * Constructs a new EntityConverter. |
50 * | 84 * |
51 * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager | 85 * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager |
52 * The entity manager. | 86 * The entity manager. |
53 */ | 87 * @param \Drupal\Core\Language\LanguageManagerInterface|null $language_manager |
54 public function __construct(EntityManagerInterface $entity_manager) { | 88 * (optional) The language manager. Defaults to none. |
89 */ | |
90 public function __construct(EntityManagerInterface $entity_manager, LanguageManagerInterface $language_manager = NULL) { | |
55 $this->entityManager = $entity_manager; | 91 $this->entityManager = $entity_manager; |
92 $this->languageManager = $language_manager; | |
56 } | 93 } |
57 | 94 |
58 /** | 95 /** |
59 * {@inheritdoc} | 96 * {@inheritdoc} |
60 */ | 97 */ |
61 public function convert($value, $definition, $name, array $defaults) { | 98 public function convert($value, $definition, $name, array $defaults) { |
62 $entity_type_id = $this->getEntityTypeFromDefaults($definition, $name, $defaults); | 99 $entity_type_id = $this->getEntityTypeFromDefaults($definition, $name, $defaults); |
63 if ($storage = $this->entityManager->getStorage($entity_type_id)) { | 100 $storage = $this->entityManager->getStorage($entity_type_id); |
64 $entity = $storage->load($value); | 101 $entity_definition = $this->entityManager->getDefinition($entity_type_id); |
65 // If the entity type is translatable, ensure we return the proper | 102 |
66 // translation object for the current context. | 103 $entity = $storage->load($value); |
67 if ($entity instanceof EntityInterface && $entity instanceof TranslatableInterface) { | 104 |
68 $entity = $this->entityManager->getTranslationFromContext($entity, NULL, ['operation' => 'entity_upcast']); | 105 // If the entity type is revisionable and the parameter has the |
106 // "load_latest_revision" flag, load the latest revision. | |
107 if ($entity instanceof RevisionableInterface && !empty($definition['load_latest_revision']) && $entity_definition->isRevisionable()) { | |
108 // Retrieve the latest revision ID taking translations into account. | |
109 $langcode = $this->languageManager() | |
110 ->getCurrentLanguage(LanguageInterface::TYPE_CONTENT) | |
111 ->getId(); | |
112 $entity = $this->getLatestTranslationAffectedRevision($entity, $langcode); | |
113 } | |
114 | |
115 // If the entity type is translatable, ensure we return the proper | |
116 // translation object for the current context. | |
117 if ($entity instanceof EntityInterface && $entity instanceof TranslatableInterface) { | |
118 $entity = $this->entityManager->getTranslationFromContext($entity, NULL, ['operation' => 'entity_upcast']); | |
119 } | |
120 | |
121 return $entity; | |
122 } | |
123 | |
124 /** | |
125 * Returns the ID of the latest revision translation of the specified entity. | |
126 * | |
127 * @param \Drupal\Core\Entity\EntityInterface|\Drupal\Core\Entity\RevisionableInterface $entity | |
128 * The default revision of the entity being converted. | |
129 * @param string $langcode | |
130 * The language of the revision translation to be loaded. | |
131 * | |
132 * @return \Drupal\Core\Entity\EntityInterface|\Drupal\Core\Entity\RevisionableInterface | |
133 * The latest translation-affecting revision for the specified entity, or | |
134 * just the latest revision, if the specified entity is not translatable or | |
135 * does not have a matching translation yet. | |
136 */ | |
137 protected function getLatestTranslationAffectedRevision(RevisionableInterface $entity, $langcode) { | |
138 $revision = NULL; | |
139 $storage = $this->entityManager->getStorage($entity->getEntityTypeId()); | |
140 | |
141 if ($entity instanceof TranslatableRevisionableInterface && $entity->isTranslatable()) { | |
142 /** @var \Drupal\Core\Entity\TranslatableRevisionableStorageInterface $storage */ | |
143 $revision_id = $storage->getLatestTranslationAffectedRevisionId($entity->id(), $langcode); | |
144 | |
145 // If the latest translation-affecting revision was a default revision, it | |
146 // is fine to load the latest revision instead, because in this case the | |
147 // latest revision, regardless of it being default or pending, will always | |
148 // contain the most up-to-date values for the specified translation. This | |
149 // provides a BC behavior when the route is defined by a module always | |
150 // expecting the latest revision to be loaded and to be the default | |
151 // revision. In this particular case the latest revision is always going | |
152 // to be the default revision, since pending revisions would not be | |
153 // supported. | |
154 /** @var \Drupal\Core\Entity\TranslatableRevisionableInterface $revision */ | |
155 $revision = $revision_id ? $this->loadRevision($entity, $revision_id) : NULL; | |
156 if (!$revision || ($revision->wasDefaultRevision() && !$revision->isDefaultRevision())) { | |
157 $revision = NULL; | |
69 } | 158 } |
159 } | |
160 | |
161 // Fall back to the latest revisions if no affected revision for the current | |
162 // content language could be found. This is acceptable as it means the | |
163 // entity is not translated. This is the correct logic also on monolingual | |
164 // sites. | |
165 if (!isset($revision)) { | |
166 $revision_id = $storage->getLatestRevisionId($entity->id()); | |
167 $revision = $this->loadRevision($entity, $revision_id); | |
168 } | |
169 | |
170 return $revision; | |
171 } | |
172 | |
173 /** | |
174 * Loads the specified entity revision. | |
175 * | |
176 * @param \Drupal\Core\Entity\EntityInterface|\Drupal\Core\Entity\RevisionableInterface $entity | |
177 * The default revision of the entity being converted. | |
178 * @param string $revision_id | |
179 * The identifier of the revision to be loaded. | |
180 * | |
181 * @return \Drupal\Core\Entity\EntityInterface|\Drupal\Core\Entity\RevisionableInterface | |
182 * An entity revision object. | |
183 */ | |
184 protected function loadRevision(RevisionableInterface $entity, $revision_id) { | |
185 // We explicitly perform a loose equality check, since a revision ID may | |
186 // be returned as an integer or a string. | |
187 if ($entity->getLoadedRevisionId() != $revision_id) { | |
188 $storage = $this->entityManager->getStorage($entity->getEntityTypeId()); | |
189 return $storage->loadRevision($revision_id); | |
190 } | |
191 else { | |
70 return $entity; | 192 return $entity; |
71 } | 193 } |
72 } | 194 } |
73 | 195 |
74 /** | 196 /** |
114 $entity_type_id = $defaults[$entity_type_slug]; | 236 $entity_type_id = $defaults[$entity_type_slug]; |
115 } | 237 } |
116 return $entity_type_id; | 238 return $entity_type_id; |
117 } | 239 } |
118 | 240 |
241 /** | |
242 * Returns a language manager instance. | |
243 * | |
244 * @return \Drupal\Core\Language\LanguageManagerInterface | |
245 * The language manager. | |
246 * | |
247 * @internal | |
248 */ | |
249 protected function languageManager() { | |
250 if (!isset($this->languageManager)) { | |
251 $this->languageManager = \Drupal::languageManager(); | |
252 // @todo Turn this into a proper error (E_USER_ERROR) in | |
253 // https://www.drupal.org/node/2938929. | |
254 @trigger_error('The language manager parameter has been added to EntityConverter since version 8.5.0 and will be made required in version 9.0.0 when requesting the latest translation-affected revision of an entity.', E_USER_DEPRECATED); | |
255 } | |
256 return $this->languageManager; | |
257 } | |
258 | |
119 } | 259 } |