annotate core/modules/media/src/MediaSourceBase.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
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 }