3 namespace Drupal\imagemagick\Plugin\FileMetadata;
5 use Drupal\Core\Cache\CacheBackendInterface;
6 use Drupal\Core\Config\ConfigFactoryInterface;
7 use Drupal\Core\Extension\ModuleHandlerInterface;
8 use Drupal\file_mdm\FileMetadataException;
9 use Drupal\file_mdm\Plugin\FileMetadata\FileMetadataPluginBase;
10 use Drupal\imagemagick\ImagemagickExecArguments;
11 use Drupal\imagemagick\ImagemagickExecManagerInterface;
12 use Symfony\Component\DependencyInjection\ContainerInterface;
15 * FileMetadata plugin for ImageMagick's identify results.
18 * id = "imagemagick_identify",
19 * title = @Translation("ImageMagick identify"),
20 * help = @Translation("File metadata plugin for ImageMagick identify results."),
23 class ImagemagickIdentify extends FileMetadataPluginBase {
26 * The module handler service.
28 * @var \Drupal\Core\Extension\ModuleHandlerInterface
30 protected $moduleHandler;
33 * The ImageMagick execution manager service.
35 * @var \Drupal\imagemagick\ImagemagickExecManagerInterface
37 protected $execManager;
40 * Constructs an ImagemagickIdentify plugin.
42 * @param array $configuration
43 * A configuration array containing information about the plugin instance.
44 * @param string $plugin_id
45 * The plugin_id for the plugin instance.
46 * @param array $plugin_definition
47 * The plugin implementation definition.
48 * @param \Drupal\Core\Cache\CacheBackendInterface $cache_service
50 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
52 * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
53 * The module handler service.
54 * @param \Drupal\imagemagick\ImagemagickExecManagerInterface $exec_manager
55 * The ImageMagick execution manager service.
57 public function __construct(array $configuration, $plugin_id, array $plugin_definition, CacheBackendInterface $cache_service, ConfigFactoryInterface $config_factory, ModuleHandlerInterface $module_handler, ImagemagickExecManagerInterface $exec_manager) {
58 parent::__construct($configuration, $plugin_id, $plugin_definition, $cache_service, $config_factory);
59 $this->moduleHandler = $module_handler;
60 $this->execManager = $exec_manager;
66 public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
71 $container->get('cache.file_mdm'),
72 $container->get('config.factory'),
73 $container->get('module_handler'),
74 $container->get('imagemagick.exec_manager')
82 * 'format' - ImageMagick's image format identifier.
83 * 'width' - Image width.
84 * 'height' - Image height.
85 * 'colorspace' - Image colorspace.
86 * 'profiles' - Image profiles.
87 * 'exif_orientation' - Image EXIF orientation (only supported formats).
88 * 'source_local_path' - The local file path from where the file was
90 * 'frames_count' - Number of frames in the image.
92 public function getSupportedKeys($options = NULL) {
108 protected function doGetMetadataFromFile() {
109 return $this->identify();
113 * Validates a file metadata key.
116 * TRUE if the key is valid.
118 * @throws \Drupal\file_mdm\FileMetadataException
119 * In case the key is invalid.
121 protected function validateKey($key, $method) {
122 if (!is_string($key)) {
123 throw new FileMetadataException("Invalid metadata key specified", $this->getPluginId(), $method);
125 if (!in_array($key, $this->getSupportedKeys(), TRUE)) {
126 throw new FileMetadataException("Invalid metadata key '{$key}' specified", $this->getPluginId(), $method);
134 protected function doGetMetadata($key = NULL) {
136 return $this->metadata;
139 $this->validateKey($key, __FUNCTION__);
141 case 'source_local_path':
142 return isset($this->metadata['source_local_path']) ? $this->metadata['source_local_path'] : NULL;
145 return isset($this->metadata['frames']) ? count($this->metadata['frames']) : 0;
148 return isset($this->metadata['frames'][0][$key]) ? $this->metadata['frames'][0][$key] : NULL;
157 protected function doSetMetadata($key, $value) {
158 $this->validateKey($key, __FUNCTION__);
160 case 'source_local_path':
161 $this->metadata['source_local_path'] = $value;
168 $this->metadata['frames'][0][$key] = $value;
177 protected function doRemoveMetadata($key) {
178 $this->validateKey($key, __FUNCTION__);
180 case 'source_local_path':
181 if (isset($this->metadata['source_local_path'])) {
182 unset($this->metadata['source_local_path']);
196 protected function getMetadataToCache() {
197 $metadata = $this->metadata;
198 // Avoid caching the source_local_path.
199 unset($metadata['source_local_path']);
204 * Calls the identify executable on the specified file.
207 * The array with identify metadata, if the file was parsed correctly.
210 protected function identify() {
211 $arguments = new ImagemagickExecArguments($this->execManager);
214 $arguments->setSource($this->getLocalTempPath());
216 // Prepare the -format argument according to the graphics package in use.
217 switch ($this->execManager->getPackage()) {
220 '-format ' . $arguments->escape("format:%[magick]|width:%[width]|height:%[height]|colorspace:%[colorspace]|profiles:%[profiles]|exif_orientation:%[EXIF:Orientation]\\n"),
221 ImagemagickExecArguments::PRE_SOURCE
225 case 'graphicsmagick':
227 '-format ' . $arguments->escape("format:%m|width:%w|height:%h|exif_orientation:%[EXIF:Orientation]\\n"),
228 ImagemagickExecArguments::PRE_SOURCE
234 // Allow modules to alter source file and the command line parameters.
235 $command = 'identify';
236 $this->moduleHandler->alter('imagemagick_pre_parse_file', $arguments);
237 $this->moduleHandler->alter('imagemagick_arguments', $arguments, $command);
239 // Execute the 'identify' command.
241 $ret = $this->execManager->execute($command, $arguments, $output);
246 // Remove any CR character (GraphicsMagick on Windows produces such).
247 $output = str_replace("\r", '', $output);
249 // Builds the frames info.
251 $frames_tmp = explode("\n", $output);
252 // Remove empty items at the end of the array.
253 while (empty($frames_tmp[count($frames_tmp) - 1])) {
254 array_pop($frames_tmp);
256 foreach ($frames_tmp as $i => $frame) {
257 $info = explode('|', $frame);
258 foreach ($info as $item) {
259 list($key, $value) = explode(':', $item);
260 if (trim($key) === 'profiles') {
261 $profiles_tmp = empty($value) ? [] : explode(',', $value);
262 $frames[$i][trim($key)] = $profiles_tmp;
265 $frames[$i][trim($key)] = trim($value);
269 $data['frames'] = $frames;
270 // Adds the local file path that was resolved via
271 // hook_imagemagick_pre_parse_file implementations.
272 $data['source_local_path'] = $arguments->getSourceLocalPath();
275 return ($ret === TRUE) ? $data : NULL;