You are here

class ExifTagMapper in File metadata manager 8.2

Same name and namespace in other branches
  1. 8 file_mdm_exif/src/ExifTagMapper.php \Drupal\file_mdm_exif\ExifTagMapper

Provides a mapping service for EXIF ifds and tags.

Hierarchy

Expanded class hierarchy of ExifTagMapper

1 string reference to 'ExifTagMapper'
file_mdm_exif.services.yml in file_mdm_exif/file_mdm_exif.services.yml
file_mdm_exif/file_mdm_exif.services.yml
1 service uses ExifTagMapper
file_mdm_exif.tag_mapper in file_mdm_exif/file_mdm_exif.services.yml
Drupal\file_mdm_exif\ExifTagMapper

File

file_mdm_exif/src/ExifTagMapper.php, line 16

Namespace

Drupal\file_mdm_exif
View source
class ExifTagMapper implements ExifTagMapperInterface {

  /**
   * The cache service.
   *
   * @var \Drupal\Core\Cache\CacheBackendInterface
   */
  protected $cache;

  /**
   * The file_mdm logger.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * The config factory service.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The string to IFD map.
   *
   * Maps IFDs or their aliases expressed as literals to the EXIF integer
   * identifier.
   *
   * @var array
   */
  protected $stringToIfdMap;

  /**
   * The string to TAG map.
   *
   * Maps TAGs expressed as literals to the EXIF integer IFD/TAG identifiers.
   *
   * @var array
   */
  protected $stringToTagMap;

  /**
   * The supported metadata 'keys'.
   *
   * A simple array of IFD/TAG combinations, expressed as literals.
   *
   * @var array
   */
  protected $supportedKeysMap;

  /**
   * The supported IFDs.
   *
   * A simple array of IFDs, expressed as literal/integer combinations.
   *
   * @var array
   */
  protected $supportedIfdsMap;

  /**
   * Constructs a ExifTagMapper object.
   *
   * @param \Psr\Log\LoggerInterface $logger
   *   The file_mdm logger.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_service
   *   The cache service.
   */
  public function __construct(LoggerInterface $logger, ConfigFactoryInterface $config_factory, CacheBackendInterface $cache_service) {
    $this->logger = $logger;
    $this->configFactory = $config_factory;
    $this->cache = $cache_service;
  }

  /**
   * {@inheritdoc}
   */
  public function resolveKeyToIfdAndTag($key) {
    if ($key === NULL) {
      throw new FileMetadataException('Missing $key argument', NULL, __METHOD__);
    }
    if (is_string($key)) {
      $tag = $this
        ->stringToTag($key);
      return [
        'ifd' => $tag[0],
        'tag' => $tag[1],
      ];
    }
    if (is_array($key)) {
      if (!isset($key[0]) || !isset($key[1])) {
        throw new FileMetadataException('Invalid $key array specified, must have two values', NULL, __METHOD__);
      }

      // Deal with ifd.
      if (is_int($key[0])) {
        $ifd = $key[0];
      }
      elseif (is_string($key[0])) {
        $ifd = $this
          ->stringToIfd($key[0]);
      }
      else {
        throw new FileMetadataException('Invalid EXIF IFD specified, must be a string or an integer', NULL, __METHOD__);
      }

      // Deal with tag.
      if (is_string($key[1])) {
        $tag = $this
          ->stringToTag($key[1])[1];
      }
      elseif (is_int($key[1])) {
        $tag = $key[1];
      }
      else {
        throw new FileMetadataException('Invalid EXIF TAG specified, must be a string or an integer', NULL, __METHOD__);
      }
      return [
        'ifd' => $ifd,
        'tag' => $tag,
      ];
    }
    throw new FileMetadataException('Invalid $key argument, must be a string or an array', NULL, __METHOD__);
  }

  /**
   * {@inheritdoc}
   */
  public function getSupportedKeys(array $options = NULL) {
    if (isset($options['ifds'])) {
      return $this
        ->getSupportedIfdsMap();
    }
    elseif (isset($options['ifd'])) {
      return array_filter($this
        ->getSupportedKeysMap(), function ($a) use ($options) {
        return strtolower($options['ifd']) === strtolower($a[0]);
      });
    }
    else {
      return $this
        ->getSupportedKeysMap();
    }
  }

  /**
   * Returns the list of supported IFDs.
   *
   * Builds and caches the list as needed.
   *
   * @return array
   *   A simple array of IFDs, expressed as literal/integer combinations.
   */
  protected function getSupportedIfdsMap() {
    if (!$this->supportedIfdsMap) {
      $cache_id = 'supportedIfds';
      if ($cache = $this
        ->getCache($cache_id)) {
        $this->supportedIfdsMap = $cache->data;
      }
      else {
        $this->supportedIfdsMap = [];
        $ifd_types = [
          PelIfd::IFD0,
          PelIfd::IFD1,
          PelIfd::EXIF,
          PelIfd::GPS,
          PelIfd::INTEROPERABILITY,
        ];
        foreach ($ifd_types as $type) {
          $this->supportedIfdsMap[] = [
            PelIfd::getTypeName($type),
            $type,
          ];
        }
        $this
          ->setCache($cache_id, $this->supportedIfdsMap);
      }
    }
    return $this->supportedIfdsMap;
  }

  /**
   * Returns the list of supported metadata 'keys'.
   *
   * Builds and caches the list as needed.
   *
   * @return array
   *   A simple array of IFD/TAG combinations, expressed as literals.
   */
  protected function getSupportedKeysMap() {
    if (!$this->supportedKeysMap) {
      $cache_id = 'supportedKeys';
      if ($cache = $this
        ->getCache($cache_id)) {
        $this->supportedKeysMap = $cache->data;
      }
      else {
        $this->supportedKeysMap = [];
        foreach ($this
          ->getSupportedIfdsMap() as $ifd) {
          $ifd_obj = new PelIfd($ifd[1]);
          $valid_tags = $ifd_obj
            ->getValidTags();
          foreach ($valid_tags as $tag) {
            $this->supportedKeysMap[] = [
              $ifd[0],
              PelTag::getName($ifd[1], $tag),
            ];
          }
        }
        $this
          ->setCache($cache_id, $this->supportedKeysMap);
      }
    }
    return $this->supportedKeysMap;
  }

  /**
   * Returns the IFD/TAG integers for a TAG literal.
   *
   * @param string $value
   *   A TAG literal.
   *
   * @return array
   *   A simple array of with IFD and TAG, expressed as integers.
   *
   * @throws \Drupal\file_mdm\FileMetadataException
   *   When the IFD/TAG combination could not be found.
   */
  protected function stringToTag($value) {
    $v = strtolower($value);
    $tag = isset($this
      ->getStringToTagMap()[$v]) ? $this
      ->getStringToTagMap()[$v] : NULL;
    if ($tag) {
      return $tag;
    }
    throw new FileMetadataException("No EXIF TAG found for key '{$value}'", "EXIF");
  }

  /**
   * Returns the map of TAG strings to IFD/TAG integers.
   *
   * Builds and caches the list as needed.
   *
   * @return array
   *   An associative array where keys are TAG literals, and values a simple
   *   array of IFD/TAG integer identifiers.
   */
  protected function getStringToTagMap() {
    if (!$this->stringToTagMap) {
      $cache_id = 'stringToTag';
      if ($cache = $this
        ->getCache($cache_id)) {
        $this->stringToTagMap = $cache->data;
      }
      else {
        foreach ($this
          ->getSupportedIfdsMap() as $ifd) {
          $ifd_obj = new PelIfd($ifd[1]);
          $valid_tags = $ifd_obj
            ->getValidTags();
          foreach ($valid_tags as $tag) {
            $tag_name = strtolower(PelTag::getName($ifd[1], $tag));
            if (!isset($this->stringToTagMap[$tag_name])) {
              $this->stringToTagMap[$tag_name] = [
                $ifd[1],
                $tag,
              ];
            }
          }
        }
        $this
          ->setCache($cache_id, $this->stringToTagMap);
      }
    }
    return $this->stringToTagMap;
  }

  /**
   * Returns the IFD integer for an IFD literal.
   *
   * @param string $value
   *   An IFD literal.
   *
   * @return int
   *   The IFD identifier.
   *
   * @throws \Drupal\file_mdm\FileMetadataException
   *   When the IFD could not be found.
   */
  protected function stringToIfd($value) {
    $v = strtolower($value);
    if (isset($this
      ->getStringToIfdMap()[$v])) {
      return $this
        ->getStringToIfdMap()[$v];
    }
    throw new FileMetadataException("Invalid EXIF IFD '{$value}' specified", "EXIF");
  }

  /**
   * Returns the map of IFD strings to IFD integers.
   *
   * Builds and caches the list as needed.
   *
   * @return array
   *   An associative array where keys are IFD literals, and values the IFD
   *   integer identifiers.
   */
  protected function getStringToIfdMap() {
    if (!$this->stringToIfdMap) {
      $cache_id = 'stringToIfd';
      if ($cache = $this
        ->getCache($cache_id)) {
        $this->stringToIfdMap = $cache->data;
      }
      else {
        $config_map = $this->configFactory
          ->get('file_mdm_exif.file_metadata_plugin.exif')
          ->get('ifd_map');
        $this->stringToIfdMap = [];
        foreach ($config_map as $value) {
          foreach ($value['aliases'] as $alias) {
            $k = strtolower($alias);
            $this->stringToIfdMap[$k] = $value['type'];
          }
        }
        $this
          ->setCache($cache_id, $this->stringToIfdMap);
      }
    }
    return $this->stringToIfdMap;
  }

  /**
   * Gets a cache entry.
   *
   * @param string $id
   *   The cache id to get.
   *
   * @return object|null
   *   The cache item or NULL on failure.
   */
  protected function getCache($id) {
    if ($cache = $this->cache
      ->get("map:exif:{$id}")) {
      return $cache;
    }
    else {
      return NULL;
    }
  }

  /**
   * Sets a cache entry.
   *
   * @param string $id
   *   The cache id to set.
   * @param mixed $value
   *   The value to cache.
   *
   * @return $this
   */
  protected function setCache($id, $value) {
    $config = $this->configFactory
      ->get('file_mdm_exif.file_metadata_plugin.exif');
    $this->cache
      ->set("map:exif:{$id}", $value, Cache::PERMANENT, $config
      ->getCacheTags());
    return $this;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
ExifTagMapper::$cache protected property The cache service.
ExifTagMapper::$configFactory protected property The config factory service.
ExifTagMapper::$logger protected property The file_mdm logger.
ExifTagMapper::$stringToIfdMap protected property The string to IFD map.
ExifTagMapper::$stringToTagMap protected property The string to TAG map.
ExifTagMapper::$supportedIfdsMap protected property The supported IFDs.
ExifTagMapper::$supportedKeysMap protected property The supported metadata 'keys'.
ExifTagMapper::getCache protected function Gets a cache entry.
ExifTagMapper::getStringToIfdMap protected function Returns the map of IFD strings to IFD integers.
ExifTagMapper::getStringToTagMap protected function Returns the map of TAG strings to IFD/TAG integers.
ExifTagMapper::getSupportedIfdsMap protected function Returns the list of supported IFDs.
ExifTagMapper::getSupportedKeys public function Returns a list of default metadata 'keys' supported. Overrides ExifTagMapperInterface::getSupportedKeys
ExifTagMapper::getSupportedKeysMap protected function Returns the list of supported metadata 'keys'.
ExifTagMapper::resolveKeyToIfdAndTag public function Resolves a metadata 'key' to the default EXIF IFD and TAG. Overrides ExifTagMapperInterface::resolveKeyToIfdAndTag
ExifTagMapper::setCache protected function Sets a cache entry.
ExifTagMapper::stringToIfd protected function Returns the IFD integer for an IFD literal.
ExifTagMapper::stringToTag protected function Returns the IFD/TAG integers for a TAG literal.
ExifTagMapper::__construct public function Constructs a ExifTagMapper object.