X-Git-Url: http://www.aleph1.co.uk/gitweb/?p=yaffs-website;a=blobdiff_plain;f=web%2Fmodules%2Fcontrib%2Ffile_mdm%2Ffile_mdm_exif%2Fsrc%2FPlugin%2FFileMetadata%2FExif.php;fp=web%2Fmodules%2Fcontrib%2Ffile_mdm%2Ffile_mdm_exif%2Fsrc%2FPlugin%2FFileMetadata%2FExif.php;h=ce532045452b133d2895fef10eb7c1d1c962b205;hp=0000000000000000000000000000000000000000;hb=059867c3f96750652c80f39e44c442a58c2549ee;hpb=f8fc16ae6b862bef59baaad5d051dd37b7ff11b2 diff --git a/web/modules/contrib/file_mdm/file_mdm_exif/src/Plugin/FileMetadata/Exif.php b/web/modules/contrib/file_mdm/file_mdm_exif/src/Plugin/FileMetadata/Exif.php new file mode 100644 index 000000000..ce5320454 --- /dev/null +++ b/web/modules/contrib/file_mdm/file_mdm_exif/src/Plugin/FileMetadata/Exif.php @@ -0,0 +1,399 @@ +mimeTypeGuesser = $mime_type_guesser; + $this->tagMapper = $tag_mapper; + } + + /** + * {@inheritdoc} + */ + 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') + ); + } + + /** + * {@inheritdoc} + */ + public function getSupportedKeys($options = NULL) { + return $this->tagMapper->getSupportedKeys($options); + } + + /** + * Returns the PEL file object for the image file. + * + * @return \lsolesen\pel\PelJpeg|\lsolesen\pel\PelTiff + * A PEL file object. + */ + 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; + + } + } + } + + /** + * {@inheritdoc} + */ + protected function doGetMetadataFromFile() { + // Get the file as a PelJpeg or PelTiff object. + $file = $this->getFile(); + if (!$file) { + return []; + } + + // Get the TIFF section if existing, or return if not. + if ($file instanceof PelJpeg) { + $exif = $file->getExif(); + if ($exif === NULL) { + return []; + } + $tiff = $exif->getTiff(); + if ($tiff === NULL) { + return []; + } + } + elseif ($file instanceof PelTiff) { + $tiff = $file; + } + + // Scans metadata for entries of supported tags. + $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; + } + + /** + * Returns a PelEntry. + * + * @param \lsolesen\pel\PelTiff $tiff + * A PelTiff object. + * @param int $ifd_tag + * The IFD EXIF integer identifier. + * @param int $key_tag + * The TAG EXIF integer identifier. + * + * @return \lsolesen\pel\PelEntry + * The PelEntry for the specified IFD and TAG. + */ + 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); + + } + } + + /** + * {@inheritdoc} + */ + public function isSaveToFileSupported() { + return TRUE; + } + + /** + * {@inheritdoc} + */ + protected function doSaveMetadataToFile() { + // Get the file as a PelJpeg or PelTiff object. + $file = $this->getFile(); + if (!$file) { + return FALSE; + } + + // Get the TIFF section if existing, or create one if not. + if ($file instanceof PelJpeg) { + $exif = $file->getExif(); + if ($exif === NULL) { + // If EXIF section is missing we simply create a new APP1 section + // (a PelExif object) and add it to the PelJpeg object. + $exif = new PelExif(); + $file->setExif($exif); + } + $tiff = $exif->getTiff(); + if ($tiff === NULL) { + // Same for TIFF section. + $tiff = new PelTiff(); + $exif->setTiff($tiff); + } + } + elseif ($file instanceof PelTiff) { + $tiff = $file; + } + + // Get IFD0 if existing, or create it if not. + $ifd0 = $tiff->getIfd(); + if ($ifd0 === NULL) { + // No IFD in the TIFF data, we just create and insert an empty PelIfd + // object. + $ifd0 = new PelIfd(PelIfd::IFD0); + $tiff->setIfd($ifd0); + } + + // Loops through in-memory metadata and update tag entries accordingly. + 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; + } + + /** + * Adds or changes entries for an IFD. + * + * @param lsolesen\pel\PelIfd $ifd + * A PelIfd object. + * @param lsolesen\pel\PelEntry[] $entries + * An array of PelEntry objects. + * + * @return bool + * TRUE if entries were added/changed successfully, FALSE otherwise. + */ + 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 { + $c->setValue($input_entry->getValue()); + } + } + else { + if ($input_entry !== 'deleted') { + $ifd->addEntry($input_entry); + } + } + } + return TRUE; + } + + /** + * {@inheritdoc} + */ + 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(), + ]; + } + } + + /** + * {@inheritdoc} + */ + 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']])) { + $this->metadata[$ifd_tag['ifd']][$ifd_tag['tag']]->setValue($value); + return TRUE; + } + return FALSE; + } + + /** + * {@inheritdoc} + */ + 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; + } + } + +}