MediumFactory.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. <?php
  2. /**
  3. * @package Grav\Common\Page
  4. *
  5. * @copyright Copyright (c) 2015 - 2022 Trilby Media, LLC. All rights reserved.
  6. * @license MIT License; see LICENSE file for details.
  7. */
  8. namespace Grav\Common\Page\Medium;
  9. use Grav\Common\Grav;
  10. use Grav\Common\Data\Blueprint;
  11. use Grav\Common\Media\Interfaces\ImageMediaInterface;
  12. use Grav\Common\Media\Interfaces\MediaObjectInterface;
  13. use Grav\Common\Utils;
  14. use Grav\Framework\Form\FormFlashFile;
  15. use Psr\Http\Message\UploadedFileInterface;
  16. use function dirname;
  17. use function is_array;
  18. /**
  19. * Class MediumFactory
  20. * @package Grav\Common\Page\Medium
  21. */
  22. class MediumFactory
  23. {
  24. /**
  25. * Create Medium from a file
  26. *
  27. * @param string $file
  28. * @param array $params
  29. * @return Medium|null
  30. */
  31. public static function fromFile($file, array $params = [])
  32. {
  33. if (!file_exists($file)) {
  34. return null;
  35. }
  36. $parts = Utils::pathinfo($file);
  37. $path = $parts['dirname'];
  38. $filename = $parts['basename'];
  39. $ext = $parts['extension'] ?? '';
  40. $basename = $parts['filename'];
  41. $config = Grav::instance()['config'];
  42. $media_params = $ext ? $config->get('media.types.' . strtolower($ext)) : null;
  43. if (!is_array($media_params)) {
  44. return null;
  45. }
  46. // Remove empty 'image' attribute
  47. if (isset($media_params['image']) && empty($media_params['image'])) {
  48. unset($media_params['image']);
  49. }
  50. $params += $media_params;
  51. // Add default settings for undefined variables.
  52. $params += (array)$config->get('media.types.defaults');
  53. $params += [
  54. 'type' => 'file',
  55. 'thumb' => 'media/thumb.png',
  56. 'mime' => 'application/octet-stream',
  57. 'filepath' => $file,
  58. 'filename' => $filename,
  59. 'basename' => $basename,
  60. 'extension' => $ext,
  61. 'path' => $path,
  62. 'modified' => filemtime($file),
  63. 'thumbnails' => []
  64. ];
  65. $locator = Grav::instance()['locator'];
  66. $file = $locator->findResource("image://{$params['thumb']}");
  67. if ($file) {
  68. $params['thumbnails']['default'] = $file;
  69. }
  70. return static::fromArray($params);
  71. }
  72. /**
  73. * Create Medium from an uploaded file
  74. *
  75. * @param UploadedFileInterface $uploadedFile
  76. * @param array $params
  77. * @return Medium|null
  78. */
  79. public static function fromUploadedFile(UploadedFileInterface $uploadedFile, array $params = [])
  80. {
  81. // For now support only FormFlashFiles, which exist over multiple requests. Also ignore errored and moved media.
  82. if (!$uploadedFile instanceof FormFlashFile || $uploadedFile->getError() !== \UPLOAD_ERR_OK || $uploadedFile->isMoved()) {
  83. return null;
  84. }
  85. $clientName = $uploadedFile->getClientFilename();
  86. if (!$clientName) {
  87. return null;
  88. }
  89. $parts = Utils::pathinfo($clientName);
  90. $filename = $parts['basename'];
  91. $ext = $parts['extension'] ?? '';
  92. $basename = $parts['filename'];
  93. $file = $uploadedFile->getTmpFile();
  94. $path = $file ? dirname($file) : '';
  95. $config = Grav::instance()['config'];
  96. $media_params = $ext ? $config->get('media.types.' . strtolower($ext)) : null;
  97. if (!is_array($media_params)) {
  98. return null;
  99. }
  100. $params += $media_params;
  101. // Add default settings for undefined variables.
  102. $params += (array)$config->get('media.types.defaults');
  103. $params += [
  104. 'type' => 'file',
  105. 'thumb' => 'media/thumb.png',
  106. 'mime' => 'application/octet-stream',
  107. 'filepath' => $file,
  108. 'filename' => $filename,
  109. 'basename' => $basename,
  110. 'extension' => $ext,
  111. 'path' => $path,
  112. 'modified' => $file ? filemtime($file) : 0,
  113. 'thumbnails' => []
  114. ];
  115. $locator = Grav::instance()['locator'];
  116. $file = $locator->findResource("image://{$params['thumb']}");
  117. if ($file) {
  118. $params['thumbnails']['default'] = $file;
  119. }
  120. return static::fromArray($params);
  121. }
  122. /**
  123. * Create Medium from array of parameters
  124. *
  125. * @param array $items
  126. * @param Blueprint|null $blueprint
  127. * @return Medium
  128. */
  129. public static function fromArray(array $items = [], Blueprint $blueprint = null)
  130. {
  131. $type = $items['type'] ?? null;
  132. switch ($type) {
  133. case 'image':
  134. return new ImageMedium($items, $blueprint);
  135. case 'thumbnail':
  136. return new ThumbnailImageMedium($items, $blueprint);
  137. case 'vector':
  138. return new VectorImageMedium($items, $blueprint);
  139. case 'animated':
  140. return new StaticImageMedium($items, $blueprint);
  141. case 'video':
  142. return new VideoMedium($items, $blueprint);
  143. case 'audio':
  144. return new AudioMedium($items, $blueprint);
  145. default:
  146. return new Medium($items, $blueprint);
  147. }
  148. }
  149. /**
  150. * Create a new ImageMedium by scaling another ImageMedium object.
  151. *
  152. * @param ImageMediaInterface|MediaObjectInterface $medium
  153. * @param int $from
  154. * @param int $to
  155. * @return ImageMediaInterface|MediaObjectInterface|array
  156. */
  157. public static function scaledFromMedium($medium, $from, $to)
  158. {
  159. if (!$medium instanceof ImageMedium) {
  160. return $medium;
  161. }
  162. if ($to > $from) {
  163. return $medium;
  164. }
  165. $ratio = $to / $from;
  166. $width = $medium->get('width') * $ratio;
  167. $height = $medium->get('height') * $ratio;
  168. $prev_basename = $medium->get('basename');
  169. $basename = str_replace('@' . $from . 'x', $to !== 1 ? '@' . $to . 'x' : '', $prev_basename);
  170. $debug = $medium->get('debug');
  171. $medium->set('debug', false);
  172. $medium->setImagePrettyName($basename);
  173. $file = $medium->resize($width, $height)->path();
  174. $medium->set('debug', $debug);
  175. $medium->setImagePrettyName($prev_basename);
  176. $size = filesize($file);
  177. $medium = self::fromFile($file);
  178. if ($medium) {
  179. $medium->set('basename', $basename);
  180. $medium->set('filename', $basename . '.' . $medium->extension);
  181. $medium->set('size', $size);
  182. }
  183. return ['file' => $medium, 'size' => $size];
  184. }
  185. }