View source
<?php
namespace Drupal\file_mdm_exif\Plugin\FileMetadata;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Drupal\file_mdm\Plugin\FileMetadata\FileMetadataPluginBase;
use Drupal\file_mdm_exif\ExifTagMapperInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface;
use lsolesen\pel\PelEntry;
use lsolesen\pel\PelExif;
use lsolesen\pel\PelIfd;
use lsolesen\pel\PelJpeg;
use lsolesen\pel\PelTiff;
class Exif extends FileMetadataPluginBase {
protected $mimeTypeGuesser;
protected $tagMapper;
protected $pelFile;
public function __construct(array $configuration, $plugin_id, array $plugin_definition, CacheBackendInterface $cache_service, ConfigFactoryInterface $config_factory, MimeTypeGuesserInterface $mime_type_guesser, ExifTagMapperInterface $tag_mapper, StreamWrapperManagerInterface $stream_wrapper_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $cache_service, $config_factory, $stream_wrapper_manager);
$this->mimeTypeGuesser = $mime_type_guesser;
$this->tagMapper = $tag_mapper;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('cache.file_mdm'), $container
->get('config.factory'), $container
->get('file.mime_type.guesser'), $container
->get('file_mdm_exif.tag_mapper'), $container
->get('stream_wrapper_manager'));
}
public function getSupportedKeys($options = NULL) {
return $this->tagMapper
->getSupportedKeys($options);
}
protected function getFile() {
if ($this->pelFile !== NULL) {
return $this->pelFile;
}
else {
switch ($this->mimeTypeGuesser
->guess($this
->getUri())) {
case 'image/jpeg':
$this->pelFile = new PelJpeg($this
->getLocalTempPath());
return $this->pelFile !== NULL ? $this->pelFile : FALSE;
case 'image/tiff':
$this->pelFile = new PelTiff($this
->getLocalTempPath());
return $this->pelFile !== NULL ? $this->pelFile : FALSE;
default:
return FALSE;
}
}
}
protected function doGetMetadataFromFile() {
$file = $this
->getFile();
if (!$file) {
return [];
}
if ($file instanceof PelJpeg) {
$exif = $file
->getExif();
if ($exif === NULL) {
return [];
}
$tiff = $exif
->getTiff();
if ($tiff === NULL) {
return [];
}
}
elseif ($file instanceof PelTiff) {
$tiff = $file;
}
$metadata = [];
$keys = $this->tagMapper
->getSupportedKeys();
foreach ($keys as $key) {
$ifd_tag = $this->tagMapper
->resolveKeyToIfdAndTag($key);
if ($entry = $this
->getEntry($tiff, $ifd_tag['ifd'], $ifd_tag['tag'])) {
$metadata[$ifd_tag['ifd']][$ifd_tag['tag']] = $entry;
}
}
return $metadata;
}
protected function getEntry(PelTiff $tiff, $ifd_tag, $key_tag) {
$ifd = $tiff
->getIfd();
switch ($ifd_tag) {
case PelIfd::IFD0:
return $ifd
->getEntry($key_tag);
case PelIfd::IFD1:
$ifd1 = $ifd
->getNextIfd();
if (!$ifd1) {
return NULL;
}
return $ifd1
->getEntry($key_tag);
case PelIfd::EXIF:
$exif = $ifd
->getSubIfd(PelIfd::EXIF);
if (!$exif) {
return NULL;
}
return $exif
->getEntry($key_tag);
case PelIfd::INTEROPERABILITY:
$exif = $ifd
->getSubIfd(PelIfd::EXIF);
if (!$exif) {
return NULL;
}
$interop = $exif
->getSubIfd(PelIfd::INTEROPERABILITY);
if (!$interop) {
return NULL;
}
return $interop
->getEntry($key_tag);
case PelIfd::GPS:
$gps = $ifd
->getSubIfd(PelIfd::GPS);
if (!$gps) {
return NULL;
}
return $gps
->getEntry($key_tag);
}
}
public function isSaveToFileSupported() {
return TRUE;
}
protected function doSaveMetadataToFile() {
$file = $this
->getFile();
if (!$file) {
return FALSE;
}
if ($file instanceof PelJpeg) {
$exif = $file
->getExif();
if ($exif === NULL) {
$exif = new PelExif();
$file
->setExif($exif);
}
$tiff = $exif
->getTiff();
if ($tiff === NULL) {
$tiff = new PelTiff();
$exif
->setTiff($tiff);
}
}
elseif ($file instanceof PelTiff) {
$tiff = $file;
}
$ifd0 = $tiff
->getIfd();
if ($ifd0 === NULL) {
$ifd0 = new PelIfd(PelIfd::IFD0);
$tiff
->setIfd($ifd0);
}
foreach ($this->metadata as $ifd_id => $entries) {
switch ($ifd_id) {
case PelIfd::IFD0:
$this
->setIfdEntries($ifd0, $entries);
break;
case PelIfd::IFD1:
$ifd1 = $ifd0
->getNextIfd();
if ($ifd1 === NULL) {
$ifd1 = new PelIfd(PelIfd::IFD1);
$ifd0
->setNextIfd($ifd1);
}
$this
->setIfdEntries($ifd1, $entries);
break;
case PelIfd::EXIF:
$exif = $ifd0
->getSubIfd(PelIfd::EXIF);
if ($exif === NULL) {
$exif = new PelIfd(PelIfd::EXIF);
$ifd0
->addSubIfd($exif);
}
$this
->setIfdEntries($exif, $entries);
break;
case PelIfd::INTEROPERABILITY:
$exif = $ifd0
->getSubIfd(PelIfd::EXIF);
if ($exif === NULL) {
$exif = new PelIfd(PelIfd::EXIF);
$ifd0
->addSubIfd($exif);
}
$interop = $exif
->getSubIfd(PelIfd::INTEROPERABILITY);
if ($interop === NULL) {
$interop = new PelIfd(PelIfd::INTEROPERABILITY);
$exif
->addSubIfd($interop);
}
$this
->setIfdEntries($interop, $entries);
break;
case PelIfd::GPS:
$gps = $ifd0
->getSubIfd(PelIfd::GPS);
if ($gps === NULL) {
$gps = new PelIfd(PelIfd::GPS);
$ifd0
->addSubIfd($gps);
}
$this
->setIfdEntries($gps, $entries);
break;
}
}
return $file
->saveFile($this
->getLocalTempPath()) === FALSE ? FALSE : TRUE;
}
protected function setIfdEntries(PelIfd $ifd, array $entries) {
foreach ($entries as $tag => $input_entry) {
if ($c = $ifd
->getEntry($tag)) {
if ($input_entry === 'deleted') {
unset($ifd[$tag]);
}
else {
if ($this
->getFile() instanceof PelJpeg) {
$c
->setValue($input_entry
->getValue());
}
else {
$v = $input_entry
->getValue();
if (is_array($v)) {
$c
->setValueArray($v);
}
else {
$c
->setValue($v);
}
}
}
}
else {
if ($input_entry !== 'deleted') {
$ifd
->addEntry($input_entry);
}
}
}
return TRUE;
}
protected function doGetMetadata($key = NULL) {
if (!$this->metadata) {
return NULL;
}
if (!$key) {
return $this->metadata;
}
else {
$ifd_tag = $this->tagMapper
->resolveKeyToIfdAndTag($key);
if (!isset($this->metadata[$ifd_tag['ifd']][$ifd_tag['tag']]) || $this->metadata[$ifd_tag['ifd']][$ifd_tag['tag']] === 'deleted') {
return NULL;
}
$entry = $this->metadata[$ifd_tag['ifd']][$ifd_tag['tag']];
return [
'value' => $entry
->getValue(),
'text' => $entry
->getText(),
];
}
}
protected function doSetMetadata($key, $value) {
$ifd_tag = $this->tagMapper
->resolveKeyToIfdAndTag($key);
if ($value instanceof PelEntry) {
$this->metadata[$ifd_tag['ifd']][$ifd_tag['tag']] = $value;
return TRUE;
}
elseif (isset($this->metadata[$ifd_tag['ifd']][$ifd_tag['tag']])) {
if (is_array($value)) {
$this->metadata[$ifd_tag['ifd']][$ifd_tag['tag']]
->setValueArray($value);
}
else {
$this->metadata[$ifd_tag['ifd']][$ifd_tag['tag']]
->setValue($value);
}
return TRUE;
}
return FALSE;
}
protected function doRemoveMetadata($key) {
if (!$this->metadata || !$key) {
return FALSE;
}
else {
$ifd_tag = $this->tagMapper
->resolveKeyToIfdAndTag($key);
if (isset($this->metadata[$ifd_tag['ifd']][$ifd_tag['tag']])) {
$this->metadata[$ifd_tag['ifd']][$ifd_tag['tag']] = 'deleted';
return TRUE;
}
return FALSE;
}
}
}