vendor/pimcore/pimcore/models/Asset/Thumbnail/ImageThumbnailTrait.php line 260

Open in your IDE?
  1. <?php
  2. /**
  3. * Pimcore
  4. *
  5. * This source file is available under two different licenses:
  6. * - GNU General Public License version 3 (GPLv3)
  7. * - Pimcore Commercial License (PCL)
  8. * Full copyright and license information is available in
  9. * LICENSE.md which is distributed with this source code.
  10. *
  11. * @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12. * @license http://www.pimcore.org/license GPLv3 and PCL
  13. */
  14. namespace Pimcore\Model\Asset\Thumbnail;
  15. use Pimcore\Helper\TemporaryFileHelperTrait;
  16. use Pimcore\Model\Asset;
  17. use Pimcore\Model\Asset\Image;
  18. use Pimcore\Tool;
  19. use Pimcore\Tool\Storage;
  20. use Symfony\Component\Mime\MimeTypes;
  21. trait ImageThumbnailTrait
  22. {
  23. use TemporaryFileHelperTrait;
  24. /**
  25. * @internal
  26. *
  27. * @var Asset|null
  28. */
  29. protected $asset;
  30. /**
  31. * @internal
  32. *
  33. * @var Image\Thumbnail\Config|null
  34. */
  35. protected $config;
  36. /**
  37. * @internal
  38. *
  39. * @var array
  40. */
  41. protected array $pathReference = [];
  42. /**
  43. * @internal
  44. *
  45. * @var int|null
  46. */
  47. protected $width;
  48. /**
  49. * @internal
  50. *
  51. * @var int|null
  52. */
  53. protected $height;
  54. /**
  55. * @internal
  56. *
  57. * @var int|null
  58. */
  59. protected $realWidth;
  60. /**
  61. * @internal
  62. *
  63. * @var int|null
  64. */
  65. protected $realHeight;
  66. /**
  67. * @internal
  68. *
  69. * @var string
  70. */
  71. protected $mimetype;
  72. /**
  73. * @internal
  74. *
  75. * @var bool
  76. */
  77. protected $deferred = true;
  78. private static array $supportedFormats = [];
  79. /**
  80. * @return null|resource
  81. */
  82. public function getStream()
  83. {
  84. $pathReference = $this->getPathReference();
  85. try {
  86. return Storage::get($pathReference['type'])->readStream($pathReference['src']);
  87. } catch (\Exception $e) {
  88. return null;
  89. }
  90. }
  91. public function getPathReference(bool $deferredAllowed = false): array
  92. {
  93. if (!$deferredAllowed && (($this->pathReference['type'] ?? '') === 'deferred')) {
  94. $this->pathReference = [];
  95. }
  96. if (empty($this->pathReference)) {
  97. $this->generate($deferredAllowed);
  98. }
  99. return $this->pathReference;
  100. }
  101. /**
  102. * @internal
  103. */
  104. public function reset()
  105. {
  106. $this->pathReference = [];
  107. $this->width = null;
  108. $this->height = null;
  109. $this->realHeight = null;
  110. $this->realWidth = null;
  111. }
  112. /**
  113. * @return int
  114. */
  115. public function getWidth()
  116. {
  117. if (!$this->width) {
  118. $this->getDimensions();
  119. }
  120. return $this->width;
  121. }
  122. /**
  123. * @return int
  124. */
  125. public function getHeight()
  126. {
  127. if (!$this->height) {
  128. $this->getDimensions();
  129. }
  130. return $this->height;
  131. }
  132. /**
  133. * @return int
  134. */
  135. public function getRealWidth()
  136. {
  137. if (!$this->realWidth) {
  138. $this->getDimensions();
  139. }
  140. return $this->realWidth;
  141. }
  142. /**
  143. * @return int
  144. */
  145. public function getRealHeight()
  146. {
  147. if (!$this->realHeight) {
  148. $this->getDimensions();
  149. }
  150. return $this->realHeight;
  151. }
  152. /**
  153. * @return array
  154. */
  155. public function getDimensions()
  156. {
  157. if (!$this->width || !$this->height) {
  158. $config = $this->getConfig();
  159. $asset = $this->getAsset();
  160. $dimensions = [];
  161. // first we try to calculate the final dimensions based on the thumbnail configuration
  162. if ($config && $asset instanceof Image) {
  163. $dimensions = $config->getEstimatedDimensions($asset);
  164. }
  165. if (empty($dimensions)) {
  166. // unable to calculate dimensions -> use fallback
  167. // generate the thumbnail and get dimensions from the thumbnail file
  168. $pathReference = $this->getPathReference();
  169. if (in_array($pathReference['type'], ['thumbnail', 'asset'])) {
  170. try {
  171. $info = @getimagesize($this->getLocalFile());
  172. if ($info) {
  173. $dimensions = [
  174. 'width' => $info[0],
  175. 'height' => $info[1],
  176. ];
  177. }
  178. } catch (\Exception $e) {
  179. // noting to do
  180. }
  181. }
  182. }
  183. $this->width = isset($dimensions['width']) ? $dimensions['width'] : null;
  184. $this->height = isset($dimensions['height']) ? $dimensions['height'] : null;
  185. // the following is only relevant if using high-res option (retina, ...)
  186. $this->realHeight = $this->height;
  187. $this->realWidth = $this->width;
  188. if ($config && $config->getHighResolution() && $config->getHighResolution() > 1) {
  189. $this->realWidth = (int)floor($this->width * $config->getHighResolution());
  190. $this->realHeight = (int)floor($this->height * $config->getHighResolution());
  191. }
  192. }
  193. return [
  194. 'width' => $this->width,
  195. 'height' => $this->height,
  196. ];
  197. }
  198. /**
  199. * @return Asset
  200. */
  201. public function getAsset()
  202. {
  203. return $this->asset;
  204. }
  205. /**
  206. * @return Image\Thumbnail\Config|null
  207. */
  208. public function getConfig()
  209. {
  210. return $this->config;
  211. }
  212. /**
  213. * @return string
  214. */
  215. public function getMimeType()
  216. {
  217. if (!$this->mimetype) {
  218. $pathReference = $this->getPathReference(true);
  219. if ($pathReference['type'] === 'data-uri') {
  220. $this->mimetype = substr($pathReference['src'], 5, strpos($pathReference['src'], ';') - 5);
  221. } else {
  222. $fileExt = $this->getFileExtension();
  223. $mimeTypes = MimeTypes::getDefault()->getMimeTypes($fileExt);
  224. if (!empty($mimeTypes)) {
  225. $this->mimetype = $mimeTypes[0];
  226. } else {
  227. // unknown
  228. $this->mimetype = 'application/octet-stream';
  229. }
  230. }
  231. }
  232. return $this->mimetype;
  233. }
  234. /**
  235. * @return string
  236. */
  237. public function getFileExtension()
  238. {
  239. return \Pimcore\File::getFileExtension($this->getPath(true));
  240. }
  241. /**
  242. * @internal
  243. *
  244. * @param array $pathReference
  245. *
  246. * @return string|null
  247. */
  248. protected function convertToWebPath(array $pathReference): ?string
  249. {
  250. $type = $pathReference['type'] ?? null;
  251. $path = $pathReference['src'] ?? null;
  252. if (Tool::isFrontend()) {
  253. if ($type === 'data-uri') {
  254. return $path;
  255. } elseif ($type === 'deferred') {
  256. $prefix = \Pimcore::getContainer()->getParameter('pimcore.config')['assets']['frontend_prefixes']['thumbnail_deferred'];
  257. $path = $prefix . urlencode_ignore_slash($path);
  258. } elseif ($type === 'thumbnail') {
  259. $prefix = \Pimcore::getContainer()->getParameter('pimcore.config')['assets']['frontend_prefixes']['thumbnail'];
  260. $path = $prefix . urlencode_ignore_slash($path);
  261. } else {
  262. $path = urlencode_ignore_slash($path);
  263. }
  264. }
  265. return $path;
  266. }
  267. /**
  268. * @internal
  269. *
  270. * @return string
  271. *
  272. * @throws \Exception
  273. */
  274. public function getLocalFile()
  275. {
  276. return self::getLocalFileFromStream($this->getStream());
  277. }
  278. public static function supportsFormat(string $format): bool
  279. {
  280. if (!isset(self::$supportedFormats[$format])) {
  281. self::$supportedFormats[$format] = \Pimcore\Image::getInstance()->supportsFormat($format);
  282. }
  283. return self::$supportedFormats[$format];
  284. }
  285. }