Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\media;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Component\Utility\NestedArray;
|
Chris@14
|
6 use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
|
Chris@14
|
7 use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
|
Chris@0
|
8 use Drupal\Core\Entity\EntityFieldManagerInterface;
|
Chris@0
|
9 use Drupal\Core\Entity\EntityTypeManagerInterface;
|
Chris@0
|
10 use Drupal\Core\Field\FieldTypePluginManagerInterface;
|
Chris@0
|
11 use Drupal\Core\Form\FormStateInterface;
|
Chris@0
|
12 use Drupal\Core\Config\ConfigFactoryInterface;
|
Chris@0
|
13 use Drupal\Core\Plugin\PluginBase;
|
Chris@0
|
14 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
|
Chris@0
|
15 use Symfony\Component\DependencyInjection\ContainerInterface;
|
Chris@0
|
16
|
Chris@0
|
17 /**
|
Chris@0
|
18 * Base implementation of media source plugin.
|
Chris@0
|
19 */
|
Chris@0
|
20 abstract class MediaSourceBase extends PluginBase implements MediaSourceInterface, ContainerFactoryPluginInterface {
|
Chris@0
|
21
|
Chris@0
|
22 /**
|
Chris@0
|
23 * Plugin label.
|
Chris@0
|
24 *
|
Chris@0
|
25 * @var string
|
Chris@0
|
26 */
|
Chris@0
|
27 protected $label;
|
Chris@0
|
28
|
Chris@0
|
29 /**
|
Chris@0
|
30 * The entity type manager service.
|
Chris@0
|
31 *
|
Chris@0
|
32 * @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
Chris@0
|
33 */
|
Chris@0
|
34 protected $entityTypeManager;
|
Chris@0
|
35
|
Chris@0
|
36 /**
|
Chris@0
|
37 * The entity field manager service.
|
Chris@0
|
38 *
|
Chris@0
|
39 * @var \Drupal\Core\Entity\EntityFieldManagerInterface
|
Chris@0
|
40 */
|
Chris@0
|
41 protected $entityFieldManager;
|
Chris@0
|
42
|
Chris@0
|
43 /**
|
Chris@0
|
44 * The field type plugin manager service.
|
Chris@0
|
45 *
|
Chris@0
|
46 * @var \Drupal\Core\Field\FieldTypePluginManagerInterface
|
Chris@0
|
47 */
|
Chris@0
|
48 protected $fieldTypeManager;
|
Chris@0
|
49
|
Chris@0
|
50 /**
|
Chris@0
|
51 * The config factory service.
|
Chris@0
|
52 *
|
Chris@0
|
53 * @var \Drupal\Core\Config\ConfigFactoryInterface
|
Chris@0
|
54 */
|
Chris@0
|
55 protected $configFactory;
|
Chris@0
|
56
|
Chris@0
|
57 /**
|
Chris@0
|
58 * Constructs a new class instance.
|
Chris@0
|
59 *
|
Chris@0
|
60 * @param array $configuration
|
Chris@0
|
61 * A configuration array containing information about the plugin instance.
|
Chris@0
|
62 * @param string $plugin_id
|
Chris@0
|
63 * The plugin_id for the plugin instance.
|
Chris@0
|
64 * @param mixed $plugin_definition
|
Chris@0
|
65 * The plugin implementation definition.
|
Chris@0
|
66 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
Chris@0
|
67 * Entity type manager service.
|
Chris@0
|
68 * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
|
Chris@0
|
69 * Entity field manager service.
|
Chris@0
|
70 * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager
|
Chris@0
|
71 * The field type plugin manager service.
|
Chris@0
|
72 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
Chris@0
|
73 * The config factory service.
|
Chris@0
|
74 */
|
Chris@0
|
75 public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, FieldTypePluginManagerInterface $field_type_manager, ConfigFactoryInterface $config_factory) {
|
Chris@0
|
76 parent::__construct($configuration, $plugin_id, $plugin_definition);
|
Chris@0
|
77 $this->entityTypeManager = $entity_type_manager;
|
Chris@0
|
78 $this->entityFieldManager = $entity_field_manager;
|
Chris@0
|
79 $this->fieldTypeManager = $field_type_manager;
|
Chris@0
|
80 $this->configFactory = $config_factory;
|
Chris@0
|
81
|
Chris@0
|
82 // Add the default configuration of the media source to the plugin.
|
Chris@0
|
83 $this->setConfiguration($configuration);
|
Chris@0
|
84 }
|
Chris@0
|
85
|
Chris@0
|
86 /**
|
Chris@0
|
87 * {@inheritdoc}
|
Chris@0
|
88 */
|
Chris@0
|
89 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
|
Chris@0
|
90 return new static(
|
Chris@0
|
91 $configuration,
|
Chris@0
|
92 $plugin_id,
|
Chris@0
|
93 $plugin_definition,
|
Chris@0
|
94 $container->get('entity_type.manager'),
|
Chris@0
|
95 $container->get('entity_field.manager'),
|
Chris@0
|
96 $container->get('plugin.manager.field.field_type'),
|
Chris@0
|
97 $container->get('config.factory')
|
Chris@0
|
98 );
|
Chris@0
|
99 }
|
Chris@0
|
100
|
Chris@0
|
101 /**
|
Chris@0
|
102 * {@inheritdoc}
|
Chris@0
|
103 */
|
Chris@0
|
104 public function setConfiguration(array $configuration) {
|
Chris@0
|
105 $this->configuration = NestedArray::mergeDeep(
|
Chris@0
|
106 $this->defaultConfiguration(),
|
Chris@0
|
107 $configuration
|
Chris@0
|
108 );
|
Chris@0
|
109 }
|
Chris@0
|
110
|
Chris@0
|
111 /**
|
Chris@0
|
112 * {@inheritdoc}
|
Chris@0
|
113 */
|
Chris@0
|
114 public function getConfiguration() {
|
Chris@0
|
115 return $this->configuration;
|
Chris@0
|
116 }
|
Chris@0
|
117
|
Chris@0
|
118 /**
|
Chris@0
|
119 * {@inheritdoc}
|
Chris@0
|
120 */
|
Chris@0
|
121 public function defaultConfiguration() {
|
Chris@0
|
122 return [
|
Chris@0
|
123 'source_field' => '',
|
Chris@0
|
124 ];
|
Chris@0
|
125 }
|
Chris@0
|
126
|
Chris@0
|
127 /**
|
Chris@0
|
128 * {@inheritdoc}
|
Chris@0
|
129 */
|
Chris@0
|
130 public function getMetadata(MediaInterface $media, $attribute_name) {
|
Chris@0
|
131 switch ($attribute_name) {
|
Chris@0
|
132 case 'default_name':
|
Chris@0
|
133 return 'media:' . $media->bundle() . ':' . $media->uuid();
|
Chris@0
|
134
|
Chris@0
|
135 case 'thumbnail_uri':
|
Chris@0
|
136 $default_thumbnail_filename = $this->pluginDefinition['default_thumbnail_filename'];
|
Chris@0
|
137 return $this->configFactory->get('media.settings')->get('icon_base_uri') . '/' . $default_thumbnail_filename;
|
Chris@0
|
138 }
|
Chris@0
|
139
|
Chris@0
|
140 return NULL;
|
Chris@0
|
141 }
|
Chris@0
|
142
|
Chris@0
|
143 /**
|
Chris@0
|
144 * {@inheritdoc}
|
Chris@0
|
145 */
|
Chris@0
|
146 public function calculateDependencies() {
|
Chris@0
|
147 return [];
|
Chris@0
|
148 }
|
Chris@0
|
149
|
Chris@0
|
150 /**
|
Chris@0
|
151 * Get the source field options for the media type form.
|
Chris@0
|
152 *
|
Chris@0
|
153 * This returns all fields related to media entities, filtered by the allowed
|
Chris@0
|
154 * field types in the media source annotation.
|
Chris@0
|
155 *
|
Chris@0
|
156 * @return string[]
|
Chris@0
|
157 * A list of source field options for the media type form.
|
Chris@0
|
158 */
|
Chris@0
|
159 protected function getSourceFieldOptions() {
|
Chris@0
|
160 // If there are existing fields to choose from, allow the user to reuse one.
|
Chris@0
|
161 $options = [];
|
Chris@0
|
162 foreach ($this->entityFieldManager->getFieldStorageDefinitions('media') as $field_name => $field) {
|
Chris@0
|
163 $allowed_type = in_array($field->getType(), $this->pluginDefinition['allowed_field_types'], TRUE);
|
Chris@0
|
164 if ($allowed_type && !$field->isBaseField()) {
|
Chris@0
|
165 $options[$field_name] = $field->getLabel();
|
Chris@0
|
166 }
|
Chris@0
|
167 }
|
Chris@0
|
168 return $options;
|
Chris@0
|
169 }
|
Chris@0
|
170
|
Chris@0
|
171 /**
|
Chris@0
|
172 * {@inheritdoc}
|
Chris@0
|
173 */
|
Chris@0
|
174 public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
|
Chris@0
|
175 $options = $this->getSourceFieldOptions();
|
Chris@0
|
176 $form['source_field'] = [
|
Chris@0
|
177 '#type' => 'select',
|
Chris@0
|
178 '#title' => $this->t('Field with source information'),
|
Chris@0
|
179 '#default_value' => $this->configuration['source_field'],
|
Chris@0
|
180 '#empty_option' => $this->t('- Create -'),
|
Chris@0
|
181 '#options' => $options,
|
Chris@0
|
182 '#description' => $this->t('Select the field that will store essential information about the media item. If "Create" is selected a new field will be automatically created.'),
|
Chris@0
|
183 ];
|
Chris@0
|
184
|
Chris@0
|
185 if (!$options && $form_state->get('operation') === 'add') {
|
Chris@0
|
186 $form['source_field']['#access'] = FALSE;
|
Chris@0
|
187 $field_definition = $this->fieldTypeManager->getDefinition(reset($this->pluginDefinition['allowed_field_types']));
|
Chris@0
|
188 $form['source_field_message'] = [
|
Chris@0
|
189 '#markup' => $this->t('%field_type field will be automatically created on this type to store the essential information about the media item.', [
|
Chris@0
|
190 '%field_type' => $field_definition['label'],
|
Chris@0
|
191 ]),
|
Chris@0
|
192 ];
|
Chris@0
|
193 }
|
Chris@0
|
194 elseif ($form_state->get('operation') === 'edit') {
|
Chris@0
|
195 $form['source_field']['#access'] = FALSE;
|
Chris@0
|
196 $fields = $this->entityFieldManager->getFieldDefinitions('media', $form_state->get('type')->id());
|
Chris@0
|
197 $form['source_field_message'] = [
|
Chris@0
|
198 '#markup' => $this->t('%field_name field is used to store the essential information about the media item.', [
|
Chris@0
|
199 '%field_name' => $fields[$this->configuration['source_field']]->getLabel(),
|
Chris@0
|
200 ]),
|
Chris@0
|
201 ];
|
Chris@0
|
202 }
|
Chris@0
|
203
|
Chris@0
|
204 return $form;
|
Chris@0
|
205 }
|
Chris@0
|
206
|
Chris@0
|
207 /**
|
Chris@0
|
208 * {@inheritdoc}
|
Chris@0
|
209 */
|
Chris@0
|
210 public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
|
Chris@0
|
211 }
|
Chris@0
|
212
|
Chris@0
|
213 /**
|
Chris@0
|
214 * {@inheritdoc}
|
Chris@0
|
215 */
|
Chris@0
|
216 public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
|
Chris@0
|
217 foreach (array_intersect_key($form_state->getValues(), $this->configuration) as $config_key => $config_value) {
|
Chris@0
|
218 $this->configuration[$config_key] = $config_value;
|
Chris@0
|
219 }
|
Chris@0
|
220
|
Chris@0
|
221 // If no source field is explicitly set, create it now.
|
Chris@0
|
222 if (empty($this->configuration['source_field'])) {
|
Chris@0
|
223 $field_storage = $this->createSourceFieldStorage();
|
Chris@0
|
224 $field_storage->save();
|
Chris@0
|
225 $this->configuration['source_field'] = $field_storage->getName();
|
Chris@0
|
226 }
|
Chris@0
|
227 }
|
Chris@0
|
228
|
Chris@0
|
229 /**
|
Chris@0
|
230 * Creates the source field storage definition.
|
Chris@0
|
231 *
|
Chris@0
|
232 * By default, the first field type listed in the plugin definition's
|
Chris@0
|
233 * allowed_field_types array will be the generated field's type.
|
Chris@0
|
234 *
|
Chris@0
|
235 * @return \Drupal\field\FieldStorageConfigInterface
|
Chris@0
|
236 * The unsaved field storage definition.
|
Chris@0
|
237 */
|
Chris@0
|
238 protected function createSourceFieldStorage() {
|
Chris@0
|
239 return $this->entityTypeManager
|
Chris@0
|
240 ->getStorage('field_storage_config')
|
Chris@0
|
241 ->create([
|
Chris@0
|
242 'entity_type' => 'media',
|
Chris@0
|
243 'field_name' => $this->getSourceFieldName(),
|
Chris@0
|
244 'type' => reset($this->pluginDefinition['allowed_field_types']),
|
Chris@0
|
245 ]);
|
Chris@0
|
246 }
|
Chris@0
|
247
|
Chris@0
|
248 /**
|
Chris@0
|
249 * Returns the source field storage definition.
|
Chris@0
|
250 *
|
Chris@0
|
251 * @return \Drupal\Core\Field\FieldStorageDefinitionInterface|null
|
Chris@0
|
252 * The field storage definition or NULL if it doesn't exists.
|
Chris@0
|
253 */
|
Chris@0
|
254 protected function getSourceFieldStorage() {
|
Chris@0
|
255 // Nothing to do if no source field is configured yet.
|
Chris@0
|
256 $field = $this->configuration['source_field'];
|
Chris@0
|
257 if ($field) {
|
Chris@0
|
258 // Even if we do know the name of the source field, there's no
|
Chris@0
|
259 // guarantee that it exists.
|
Chris@0
|
260 $fields = $this->entityFieldManager->getFieldStorageDefinitions('media');
|
Chris@0
|
261 return isset($fields[$field]) ? $fields[$field] : NULL;
|
Chris@0
|
262 }
|
Chris@0
|
263 return NULL;
|
Chris@0
|
264 }
|
Chris@0
|
265
|
Chris@0
|
266 /**
|
Chris@0
|
267 * {@inheritdoc}
|
Chris@0
|
268 */
|
Chris@0
|
269 public function getSourceFieldDefinition(MediaTypeInterface $type) {
|
Chris@0
|
270 // Nothing to do if no source field is configured yet.
|
Chris@0
|
271 $field = $this->configuration['source_field'];
|
Chris@0
|
272 if ($field) {
|
Chris@0
|
273 // Even if we do know the name of the source field, there is no
|
Chris@0
|
274 // guarantee that it already exists.
|
Chris@0
|
275 $fields = $this->entityFieldManager->getFieldDefinitions('media', $type->id());
|
Chris@0
|
276 return isset($fields[$field]) ? $fields[$field] : NULL;
|
Chris@0
|
277 }
|
Chris@0
|
278 return NULL;
|
Chris@0
|
279 }
|
Chris@0
|
280
|
Chris@0
|
281 /**
|
Chris@0
|
282 * {@inheritdoc}
|
Chris@0
|
283 */
|
Chris@0
|
284 public function createSourceField(MediaTypeInterface $type) {
|
Chris@0
|
285 $storage = $this->getSourceFieldStorage() ?: $this->createSourceFieldStorage();
|
Chris@0
|
286 return $this->entityTypeManager
|
Chris@0
|
287 ->getStorage('field_config')
|
Chris@0
|
288 ->create([
|
Chris@0
|
289 'field_storage' => $storage,
|
Chris@0
|
290 'bundle' => $type->id(),
|
Chris@0
|
291 'label' => $this->pluginDefinition['label'],
|
Chris@0
|
292 'required' => TRUE,
|
Chris@0
|
293 ]);
|
Chris@0
|
294 }
|
Chris@0
|
295
|
Chris@0
|
296 /**
|
Chris@0
|
297 * Determine the name of the source field.
|
Chris@0
|
298 *
|
Chris@0
|
299 * @return string
|
Chris@0
|
300 * The source field name. If one is already stored in configuration, it is
|
Chris@0
|
301 * returned. Otherwise, a new, unused one is generated.
|
Chris@0
|
302 */
|
Chris@0
|
303 protected function getSourceFieldName() {
|
Chris@17
|
304 // Some media sources are using a deriver, so their plugin IDs may contain
|
Chris@17
|
305 // a separator (usually ':') which is not allowed in field names.
|
Chris@17
|
306 $base_id = 'field_media_' . str_replace(static::DERIVATIVE_SEPARATOR, '_', $this->getPluginId());
|
Chris@0
|
307 $tries = 0;
|
Chris@0
|
308 $storage = $this->entityTypeManager->getStorage('field_storage_config');
|
Chris@0
|
309
|
Chris@0
|
310 // Iterate at least once, until no field with the generated ID is found.
|
Chris@0
|
311 do {
|
Chris@0
|
312 $id = $base_id;
|
Chris@0
|
313 // If we've tried before, increment and append the suffix.
|
Chris@0
|
314 if ($tries) {
|
Chris@0
|
315 $id .= '_' . $tries;
|
Chris@0
|
316 }
|
Chris@0
|
317 $field = $storage->load('media.' . $id);
|
Chris@0
|
318 $tries++;
|
Chris@0
|
319 } while ($field);
|
Chris@0
|
320
|
Chris@0
|
321 return $id;
|
Chris@0
|
322 }
|
Chris@0
|
323
|
Chris@14
|
324 /**
|
Chris@14
|
325 * {@inheritdoc}
|
Chris@14
|
326 */
|
Chris@14
|
327 public function getSourceFieldValue(MediaInterface $media) {
|
Chris@14
|
328 $source_field = $this->configuration['source_field'];
|
Chris@14
|
329 if (empty($source_field)) {
|
Chris@14
|
330 throw new \RuntimeException('Source field for media source is not defined.');
|
Chris@14
|
331 }
|
Chris@14
|
332
|
Chris@14
|
333 /** @var \Drupal\Core\Field\FieldItemInterface $field_item */
|
Chris@14
|
334 $field_item = $media->get($source_field)->first();
|
Chris@14
|
335 return $field_item->{$field_item->mainPropertyName()};
|
Chris@14
|
336 }
|
Chris@14
|
337
|
Chris@14
|
338 /**
|
Chris@14
|
339 * {@inheritdoc}
|
Chris@14
|
340 */
|
Chris@14
|
341 public function prepareViewDisplay(MediaTypeInterface $type, EntityViewDisplayInterface $display) {
|
Chris@14
|
342 $display->setComponent($this->getSourceFieldDefinition($type)->getName());
|
Chris@14
|
343 }
|
Chris@14
|
344
|
Chris@14
|
345 /**
|
Chris@14
|
346 * {@inheritdoc}
|
Chris@14
|
347 */
|
Chris@14
|
348 public function prepareFormDisplay(MediaTypeInterface $type, EntityFormDisplayInterface $display) {
|
Chris@14
|
349 // Make sure the source field is placed just after the "name" basefield.
|
Chris@14
|
350 $name_component = $display->getComponent('name');
|
Chris@14
|
351 $source_field_weight = ($name_component && isset($name_component['weight'])) ? $name_component['weight'] + 5 : -50;
|
Chris@14
|
352 $display->setComponent($this->getSourceFieldDefinition($type)->getName(), [
|
Chris@14
|
353 'weight' => $source_field_weight,
|
Chris@14
|
354 ]);
|
Chris@14
|
355 }
|
Chris@14
|
356
|
Chris@0
|
357 }
|