diff --git a/core/modules/media_entity/config/schema/media_entity.schema.yml b/core/modules/media_entity/config/schema/media_entity.schema.yml index bff9c1e..ca58bc2 100644 --- a/core/modules/media_entity/config/schema/media_entity.schema.yml +++ b/core/modules/media_entity/config/schema/media_entity.schema.yml @@ -36,6 +36,17 @@ media_entity.bundle.*: sequence: type: string +media_entity.bundle.type.image: + type: mapping + label: 'Media Image type configuration' + mapping: + source_field: + type: string + label: 'Field with embed code/URL' + gather_exif: + type: boolean + label: 'Gather EXIF metadata' + action.configuration.media_delete_action: type: action_configuration_default label: 'Delete media configuration' diff --git a/core/modules/media_entity/images/icons/no-thumbnail.png b/core/modules/media_entity/images/icons/no-thumbnail.png new file mode 100644 index 0000000..c50e3c7 --- /dev/null +++ b/core/modules/media_entity/images/icons/no-thumbnail.png @@ -0,0 +1,6 @@ +PNG + + IHDRetEXtSoftwareAdobe ImageReadyqe<0IDATx1O"[ݛb6TRQYA4Ra쬬 +o +=+2,sȲ{z4wf<3~zߤe#Cp!8CCp!8CpHp!8Cp !8Cp!8$8Cp!8C[sjvoWRQ.7 x}}}~~ެM}ʟZ>f8Vl.tJҊq K+t)d%.tp.~8rh4pDa[%H>XpG 8 8 8 8 8 8 8v ˫fpcy'''Jpcy".pt:y9pg`Sן +Gp DFk]7_Q*:NőFC?JjZQx /߿ñ t-F$cEFbqttG:[uRZdőWaEEF8Tq{{;L$͑@p"#ɘ_X]d±4D(Ԏm%(d±sd c,ZV:S.|qZz-GDGh4 #'U׶Ñ8]/pNFp⎪鷀{H­\<# ]k"HҜ[^WZM>,NX^^/|x:uss3W*|l {g=o9S8"p<(s#v2Y#q8j9>Ҳ4]xyKr},|\yqtmAp,Yl-h[[y{{[롴?Z\N L988G%^l!cEp!8CpHp!8Cp !8Cp!8$8Cp!8Cp!8CpmA 0{b~aIENDB` \ No newline at end of file diff --git a/core/modules/media_entity/src/Plugin/MediaEntity/Type/Image.php b/core/modules/media_entity/src/Plugin/MediaEntity/Type/Image.php new file mode 100644 index 0000000..fd4f1f1 --- /dev/null +++ b/core/modules/media_entity/src/Plugin/MediaEntity/Type/Image.php @@ -0,0 +1,284 @@ +imageFactory = $image_factory; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->get('entity_type.manager'), + $container->get('entity_field.manager'), + $container->get('config.factory'), + $container->get('image.factory') + ); + } + + /** + * {@inheritdoc} + */ + public function providedFields() { + $fields = array( + 'mime' => $this->t('Image MIME'), + 'width' => $this->t('Width'), + 'height' => $this->t('Height'), + ); + + if (!empty($this->configuration['gather_exif'])) { + $fields += array( + 'model' => $this->t('Camera model'), + 'created' => $this->t('Image creation datetime'), + 'iso' => $this->t('Iso'), + 'exposure' => $this->t('Exposure time'), + 'aperture' => $this->t('Aperture value'), + 'focal_length' => $this->t('Focal length'), + ); + } + + return $fields; + } + + /** + * {@inheritdoc} + */ + public function getField(MediaInterface $media, $name) { + $source_field = $this->configuration['source_field']; + + // Get the file, image and EXIF data. + /** @var \Drupal\file\FileInterface $file */ + $file = $media->{$source_field}->entity; + $image = $this->imageFactory->get($file->getFileUri()); + $uri = $file->getFileUri(); + + // Return the field. + switch ($name) { + case 'mime': + return $file->getMimeType(); + + case 'width': + return $image->getWidth(); + + case 'height': + return $image->getHeight(); + + case 'size': + return $file->getSize(); + } + + if (!empty($this->configuration['gather_exif']) && $this->canReadExifData()) { + switch ($name) { + case 'created': + /** @var \DateTime $date */ + $date = new DrupalDateTime($this->getExifField($uri, 'DateTimeOriginal')); + return $date->getTimestamp(); + + case 'model': + return $this->getExifField($uri, 'Model'); + + case 'iso': + return $this->getExifField($uri, 'ISOSpeedRatings'); + + case 'exposure': + return $this->getExifField($uri, 'ExposureTime'); + + case 'aperture': + return $this->getExifField($uri, 'FNumber'); + + case 'focal_length': + return $this->getExifField($uri, 'FocalLength'); + } + } + + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state) { + $allowed_field_types = ['file', 'image']; + $options = []; + + /** @var \Drupal\media_entity\MediaBundleInterface $bundle */ + $bundle = $form_state->getFormObject()->getEntity(); + foreach ($this->entityFieldManager->getFieldDefinitions('media', $bundle->id()) as $field_name => $field) { + if ( + in_array($field->getType(), $allowed_field_types) + && !$field->getFieldStorageDefinition()->isBaseField() + ) { + $options[$field_name] = $field->getLabel(); + } + } + + $form['source_field'] = [ + '#type' => 'select', + '#title' => $this->t('Field with source information'), + '#description' => $this->t('Field on media entity that stores Image file. You can create a bundle without selecting a value for this dropdown initially. This dropdown can be populated after adding fields to the bundle.'), + '#default_value' => empty($this->configuration['source_field']) ? NULL : $this->configuration['source_field'], + '#options' => $options, + ]; + + $form['gather_exif'] = [ + '#type' => 'select', + '#title' => $this->t('Whether to gather EXIF data.'), + '#description' => $this->t('Gather EXIF data, if that functionality is provided.'), + '#default_value' => empty($this->configuration['gather_exif']) || $this->canReadExifData() ? $this->configuration['gather_exif'] : 0, + '#options' => [ + 0 => $this->t('No'), + 1 => $this->t('Yes'), + ], + '#ajax' => [ + 'callback' => '::ajaxTypeProviderData', + ], + '#disabled' => !$this->canReadExifData(), + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function getDefaultThumbnail() { + return $this->configFactory->get('media_entity.settings') + ->get('icon_base') . '/no-thumbnail.png'; + } + + /** + * {@inheritdoc} + */ + public function thumbnail(MediaInterface $media) { + $source_field = $this->configuration['source_field']; + + /** @var \Drupal\file\FileInterface $file */ + if ($file = $media->{$source_field}->entity) { + return $file->getFileUri(); + } + + return $this->getDefaultThumbnail(); + } + + /** + * Check does functionality for reading EXIF data exist. + * + * @return bool + * Returns TRUE if functionality for reading of EXIF data is provided. + */ + protected function canReadExifData() { + return function_exists('exif_read_data'); + } + + /** + * Get EXIF field value. + * + * @param string $uri + * The uri for the file that we are getting the EXIF. + * @param string $field + * The name of the EXIF field. + * + * @return string|bool + * The value for the requested field or FALSE if is not set. + */ + protected function getExifField($uri, $field) { + if (empty($this->exif)) { + $this->exif = $this->getExifData($uri); + } + + return !empty($this->exif[$field]) ? $this->exif[$field] : FALSE; + } + + /** + * Read EXIF. + * + * @param string $uri + * The uri for the file that we are getting the Exif. + * + * @return array|bool + * An associative array where the array indexes are the header names and + * the array values are the values associated with those headers or FALSE + * if the data can't be read. + */ + protected function getExifData($uri) { + return exif_read_data($uri, 'EXIF'); + } + + /** + * {@inheritdoc} + */ + public function getDefaultName(MediaInterface $media) { + // The default name will be the filename of the source_field, if present, + // or the parent's defaultName implementation if it was not possible to + // retrieve the filename. + $source_field = $this->configuration['source_field']; + + /** @var \Drupal\file\FileInterface $file */ + if (!empty($source_field) && ($file = $media->{$source_field}->entity)) { + return $file->getFilename(); + } + + return parent::getDefaultName($media); + } + +}