GlobalMedia.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. <?php
  2. /**
  3. * @package Grav\Common\Page
  4. *
  5. * @copyright Copyright (c) 2015 - 2023 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\Media\Interfaces\MediaObjectInterface;
  11. use Grav\Common\Utils;
  12. use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
  13. use function dirname;
  14. /**
  15. * Class GlobalMedia
  16. * @package Grav\Common\Page\Medium
  17. */
  18. class GlobalMedia extends AbstractMedia
  19. {
  20. /** @var self */
  21. protected static $instance;
  22. public static function getInstance(): self
  23. {
  24. if (null === self::$instance) {
  25. self::$instance = new self();
  26. }
  27. return self::$instance;
  28. }
  29. /**
  30. * Return media path.
  31. *
  32. * @return string|null
  33. */
  34. public function getPath(): ?string
  35. {
  36. return null;
  37. }
  38. /**
  39. * @param string $offset
  40. * @return bool
  41. */
  42. #[\ReturnTypeWillChange]
  43. public function offsetExists($offset)
  44. {
  45. return parent::offsetExists($offset) ?: !empty($this->resolveStream($offset));
  46. }
  47. /**
  48. * @param string $offset
  49. * @return MediaObjectInterface|null
  50. */
  51. #[\ReturnTypeWillChange]
  52. public function offsetGet($offset)
  53. {
  54. return parent::offsetGet($offset) ?: $this->addMedium($offset);
  55. }
  56. /**
  57. * @param string $filename
  58. * @return string|null
  59. */
  60. protected function resolveStream($filename)
  61. {
  62. /** @var UniformResourceLocator $locator */
  63. $locator = Grav::instance()['locator'];
  64. if (!$locator->isStream($filename)) {
  65. return null;
  66. }
  67. return $locator->findResource($filename) ?: null;
  68. }
  69. /**
  70. * @param string $stream
  71. * @return MediaObjectInterface|null
  72. */
  73. protected function addMedium($stream)
  74. {
  75. $filename = $this->resolveStream($stream);
  76. if (!$filename) {
  77. return null;
  78. }
  79. $path = dirname($filename);
  80. [$basename, $ext,, $extra] = $this->getFileParts(Utils::basename($filename));
  81. $medium = MediumFactory::fromFile($filename);
  82. if (null === $medium) {
  83. return null;
  84. }
  85. $medium->set('size', filesize($filename));
  86. $scale = (int) ($extra ?: 1);
  87. if ($scale !== 1) {
  88. $altMedium = $medium;
  89. // Create scaled down regular sized image.
  90. $medium = MediumFactory::scaledFromMedium($altMedium, $scale, 1)['file'];
  91. if (empty($medium)) {
  92. return null;
  93. }
  94. // Add original sized image as alternative.
  95. $medium->addAlternative($scale, $altMedium['file']);
  96. // Locate or generate smaller retina images.
  97. for ($i = $scale-1; $i > 1; $i--) {
  98. $altFilename = "{$path}/{$basename}@{$i}x.{$ext}";
  99. if (file_exists($altFilename)) {
  100. $scaled = MediumFactory::fromFile($altFilename);
  101. } else {
  102. $scaled = MediumFactory::scaledFromMedium($altMedium, $scale, $i)['file'];
  103. }
  104. if ($scaled) {
  105. $medium->addAlternative($i, $scaled);
  106. }
  107. }
  108. }
  109. $meta = "{$path}/{$basename}.{$ext}.yaml";
  110. if (file_exists($meta)) {
  111. $medium->addMetaFile($meta);
  112. }
  113. $meta = "{$path}/{$basename}.{$ext}.meta.yaml";
  114. if (file_exists($meta)) {
  115. $medium->addMetaFile($meta);
  116. }
  117. $thumb = "{$path}/{$basename}.thumb.{$ext}";
  118. if (file_exists($thumb)) {
  119. $medium->set('thumbnails.page', $thumb);
  120. }
  121. $this->add($stream, $medium);
  122. return $medium;
  123. }
  124. }