Added readFile() and readStream() methods to MediaCollectionInterface and MediaFileInterface, removed getImageFileObject()

This commit is contained in:
Matias Griese
2022-02-17 16:04:15 +02:00
parent 420daa7432
commit b4df948c5f
9 changed files with 108 additions and 85 deletions

View File

@@ -109,12 +109,6 @@ interface MediaCollectionInterface extends \Grav\Framework\Media\Interfaces\Medi
*/
public function createFromArray(array $items = [], Blueprint $blueprint = null): ?MediaObjectInterface;
/**
* @param MediaObjectInterface $mediaObject
* @return ImageFile
*/
public function getImageFileObject(MediaObjectInterface $mediaObject): ImageFile;
/**
* @param string $filepath
* @return string

View File

@@ -50,4 +50,16 @@ interface MediaFileInterface extends MediaObjectInterface
* @return mixed
*/
public function relativePath($reset = true);
/**
* @return string
* @throws \RuntimeException
*/
public function readFile(): string;
/**
* @return resource
* @throws \RuntimeException
*/
public function readStream();
}

View File

@@ -12,7 +12,6 @@ namespace Grav\Common\Media\Traits;
use Grav\Common\Config\Config;
use Grav\Common\Grav;
use Grav\Common\Media\Interfaces\ImageMediaInterface;
use Grav\Common\Media\Interfaces\MediaCollectionInterface;
use Grav\Common\Page\Medium\ImageFile;
use Grav\Common\Page\Medium\ImageMedium;
use Grav\Common\Page\Medium\MediumFactory;
@@ -351,14 +350,7 @@ trait ImageMediaTrait
// Make sure we free previous image.
unset($this->image);
/** @var MediaCollectionInterface $media */
$media = $this->get('media');
if ($media && method_exists($media, 'getImageFileObject')) {
$this->image = $media->getImageFileObject($this);
} else {
$this->image = ImageFile::open($this->get('filepath'));
}
$this->image = ImageFile::fromData($this->readFile());
$this->image
->setCacheDir($cacheDir)
->setActualCacheDir($cacheDir)

View File

@@ -56,8 +56,8 @@ abstract class AbstractMedia implements ExportInterface, MediaCollectionInterfac
protected $path;
/** @var string|null */
protected $url;
/** @var array */
protected $index = [];
/** @var array|null */
protected $index;
/** @var MediaObjectInterface[] */
protected $items = [];
/** @var array|null */
@@ -242,6 +242,16 @@ abstract class AbstractMedia implements ExportInterface, MediaCollectionInterfac
*/
abstract public function createFromFile($filename, array $params = []): ?MediaObjectInterface;
/**
* Create a new ImageMedium by scaling another ImageMedium object.
*
* @param MediaObjectInterface $medium
* @param int $from
* @param int $to
* @return MediaObjectInterface
*/
abstract public function scaledFromMedium(MediaObjectInterface $medium, int $from, int $to = 1): MediaObjectInterface;
/**
* Create Medium from array of parameters
*
@@ -251,12 +261,6 @@ abstract class AbstractMedia implements ExportInterface, MediaCollectionInterfac
*/
abstract public function createFromArray(array $items = [], Blueprint $blueprint = null): ?MediaObjectInterface;
/**
* @param MediaObjectInterface $mediaObject
* @return ImageFile
*/
abstract public function getImageFileObject(MediaObjectInterface $mediaObject): ImageFile;
/**
* @return array
*/
@@ -264,8 +268,7 @@ abstract class AbstractMedia implements ExportInterface, MediaCollectionInterfac
{
return [
'version' => static::VERSION,
'index' => $this->index,
'items' => $this->items,
'index' => $this->index ?? [],
'path' => $this->path,
'url' => $this->url,
'media_order' => $this->media_order,
@@ -291,10 +294,8 @@ abstract class AbstractMedia implements ExportInterface, MediaCollectionInterfac
$this->media_order = $data['media_order'];
$this->standard_exif = $data['standard_exif'];
$this->indexTimeout = $data['indexTimeout'];
$items = $data['items'];
foreach ($items as $name => $item) {
$this->add($name, $item);
}
$this->init();
}
/**
@@ -509,18 +510,20 @@ abstract class AbstractMedia implements ExportInterface, MediaCollectionInterfac
$config = $this->getConfig();
// Get file media listing. Use cached version if possible to avoid I/O.
$now = time();
[$files, $timestamp] = $this->loadIndex();
$timeout = $this->indexTimeout;
if (!$timestamp || ($timeout && $timestamp < $now - $timeout)) {
$media_types = $config->get('media.types');
$files = $this->prepareFileInfo($this->loadFileInfo(), $media_types, $files);
if (null === $this->index) {
$now = time();
[$files, $timestamp] = $this->loadIndex();
$timeout = $this->indexTimeout;
if (!$timestamp || ($timeout && $timestamp < $now - $timeout)) {
$media_types = $config->get('media.types');
$files = $this->prepareFileInfo($this->loadFileInfo(), $media_types, $files);
$this->saveIndex($files, $now);
$this->saveIndex($files, $now);
}
$this->index = $files;
}
$this->index = $files;
// Group images by base name.
$media = [];
foreach ($files as $filename => $info) {
@@ -542,8 +545,8 @@ abstract class AbstractMedia implements ExportInterface, MediaCollectionInterfac
}
}
// Prepare the alternatives in case there is no base medium.
foreach ($media as $name => $types) {
// Prepare the alternatives in case there is no base medium.
if (!empty($types['alternative'])) {
/**
* @var string|int $ratio
@@ -568,7 +571,7 @@ abstract class AbstractMedia implements ExportInterface, MediaCollectionInterfac
$max = max(array_keys($types['alternative']));
$medium = $types['alternative'][$max]['file'];
$file_path = $medium->path();
$medium = MediumFactory::scaledFromMedium($medium, $max, 1)['file'];
$medium = $this->scaledFromMedium($medium, $max);
} else {
$medium = $this->createFromFile($types['base']['file']);
if ($medium) {
@@ -577,10 +580,6 @@ abstract class AbstractMedia implements ExportInterface, MediaCollectionInterfac
}
}
if (empty($medium)) {
continue;
}
if ($file_path) {
$meta_path = $file_path . '.meta.yaml';
if (file_exists($meta_path)) {
@@ -620,11 +619,9 @@ abstract class AbstractMedia implements ExportInterface, MediaCollectionInterfac
$max = max(array_keys($alternatives));
for ($i=$max; $i > 1; $i--) {
if (isset($alternatives[$i])) {
continue;
if (!isset($alternatives[$i])) {
$types['alternative'][$i] = $this->scaledFromMedium($alternatives[$max]['file'], $max, $i);
}
$types['alternative'][$i] = MediumFactory::scaledFromMedium($alternatives[$max]['file'], $max, $i);
}
foreach ($types['alternative'] as $altMedium) {

View File

@@ -175,11 +175,16 @@ class ImageFile extends Image
*/
public function fixOrientation()
{
$info = $this->source->getInfos();
if (!\is_string($info) || !file_exists($info)) {
return $this;
}
if (!extension_loaded('exif')) {
throw new RuntimeException('You need to EXIF PHP Extension to use this function');
}
if (!in_array(exif_imagetype($this->source->getInfos()), [IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM], true)) {
if (!in_array(exif_imagetype($info), [IMAGETYPE_JPEG, IMAGETYPE_TIFF_II, IMAGETYPE_TIFF_MM], true)) {
return $this;
}
@@ -188,7 +193,7 @@ class ImageFile extends Image
$locator = Grav::instance()['locator'];
$filepath = $this->source->getInfos();
if ($locator->isStream($filepath)) {
$filepath = $locator->findResource($this->source->getInfos(), true, true);
$filepath = $locator->findResource($info, true, true);
}
// Make sure file exists

View File

@@ -17,7 +17,6 @@ use Grav\Common\Media\Interfaces\MediaLinkInterface;
use Grav\Common\Media\Traits\ImageLoadingTrait;
use Grav\Common\Media\Traits\ImageMediaTrait;
use Grav\Common\Utils;
use Gregwar\Image\Image;
use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
use function array_key_exists;
use function func_get_args;
@@ -54,13 +53,10 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
$this->def('debug', $config->get('system.images.debug'));
$path = $this->get('filepath');
if (!$path || !file_exists($path) || !filesize($path)) {
return;
}
$this->set('thumbnails.media', $path);
if (!($this->offsetExists('width') && $this->offsetExists('height') && $this->offsetExists('mime'))) {
$exists = $path && file_exists($path) && filesize($path);
if ($exists && !($this->offsetExists('width') && $this->offsetExists('height') && $this->offsetExists('mime'))) {
$image_info = getimagesize($path);
if ($image_info) {
$this->def('width', $image_info[0]);
@@ -223,7 +219,7 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
}
$srcset = [];
foreach ($this->alternatives as $ratio => $medium) {
foreach ($this->alternatives as $medium) {
$srcset[] = $medium->url($reset) . ' ' . $medium->get('width') . 'w';
}
$srcset[] = str_replace(' ', '%20', $this->url($reset)) . ' ' . $this->get('width') . 'w';
@@ -315,7 +311,7 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
*/
public function autoSizes($enabled = 'true')
{
$this->auto_sizes = $enabled === 'true' ?: false;
$this->auto_sizes = $enabled === 'true';
return $this;
}
@@ -326,7 +322,7 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
*/
public function aspectRatio($enabled = 'true')
{
$this->aspect_ratio = $enabled === 'true' ?: false;
$this->aspect_ratio = $enabled === 'true';
return $this;
}
@@ -429,7 +425,7 @@ class ImageMedium extends Medium implements ImageMediaInterface, ImageManipulate
public function addFrame(int $border = 10, string $color = '0x000000')
{
if($border > 0 && preg_match('/^0x[a-f0-9]{6}$/i', $color)) { // $border must be an integer and bigger than 0; $color must be formatted as an HEX value (0x??????).
$image = ImageFile::open($this->path());
$image = ImageFile::fromData($this->readFile());
}
else {
return $this;

View File

@@ -40,7 +40,7 @@ class Link implements RenderableInterface, MediaLinkInterface
{
$this->attributes = $attributes;
$source = $medium->reset()->thumbnail('auto')->display('thumbnail');
$source = $medium->reset()->thumbnail()->display('thumbnail');
if (!$source instanceof MediaObjectInterface) {
throw new RuntimeException('Media has no thumbnail set');
}

View File

@@ -109,14 +109,18 @@ abstract class LocalMedia extends AbstractMedia
}
/**
* @param MediaObjectInterface $mediaObject
* @return ImageFile
* Create a new ImageMedium by scaling another ImageMedium object.
*
* @param MediaObjectInterface $medium
* @param int $from
* @param int $to
* @return MediaObjectInterface
*/
public function getImageFileObject(MediaObjectInterface $mediaObject): ImageFile
public function scaledFromMedium(MediaObjectInterface $medium, int $from, int $to = 1): MediaObjectInterface
{
$filepath = $mediaObject->get('filepath');
$result = MediumFactory::scaledFromMedium($medium, $from, $to);
return ImageFile::open($filepath);
return is_array($result) ? $result['file'] : $result;
}
/**

View File

@@ -13,10 +13,13 @@ use Grav\Common\File\CompiledYamlFile;
use Grav\Common\Grav;
use Grav\Common\Data\Data;
use Grav\Common\Data\Blueprint;
use Grav\Common\Media\Interfaces\MediaCollectionInterface;
use Grav\Common\Media\Interfaces\MediaFileInterface;
use Grav\Common\Media\Interfaces\MediaLinkInterface;
use Grav\Common\Media\Interfaces\MediaObjectInterface;
use Grav\Common\Media\Traits\MediaFileTrait;
use Grav\Common\Media\Traits\MediaObjectTrait;
use RuntimeException;
/**
* Class Medium
@@ -45,29 +48,23 @@ class Medium extends Data implements RenderableInterface, MediaFileInterface
*/
public function __construct($items = [], Blueprint $blueprint = null)
{
$items += ['mime' => 'application/octet-stream'];
$size = $items['size'] ?? null;
$modified = $items['modified'] ?? null;
if (null === $size || null === $modified) {
$path = $items['filepath'];
if ($path && file_exists($path)) {
$items['size'] = $size ?? filesize($path);
$items['modified'] = $modified ?? filemtime($path);
}
}
parent::__construct($items, $blueprint);
if (Grav::instance()['config']->get('system.media.enable_media_timestamp', true)) {
$this->timestamp = Grav::instance()['cache']->getKey();
}
$this->def('mime', 'application/octet-stream');
$sizeMissing = !$this->offsetExists('size');
$modifiedMissing = !$this->offsetExists('modified');
if ($sizeMissing || $modifiedMissing) {
$path = $this->get('filepath');
if ($path && file_exists($path)) {
if ($sizeMissing) {
$this->set('size', filesize($path));
}
if ($modifiedMissing) {
$this->set('modified', filemtime($path));
}
}
}
$this->reset();
}
@@ -80,6 +77,24 @@ class Medium extends Data implements RenderableInterface, MediaFileInterface
// Allows future compatibility as parent::__clone() works.
}
/**
* @return string
* @throws RuntimeException
*/
public function readFile(): string
{
return $this->getMedia()->readFile($this->filepath);
}
/**
* @return resource
* @throws RuntimeException
*/
public function readStream()
{
return $this->getMedia()->readStream($this->filepath);
}
/**
* Add meta file for the medium.
*
@@ -116,11 +131,11 @@ class Medium extends Data implements RenderableInterface, MediaFileInterface
/**
* @param string $thumb
* @return Medium|null
* @return MediaObjectInterface|null
*/
protected function createThumbnail($thumb)
{
return MediumFactory::fromFile($thumb, ['type' => 'thumbnail']);
return $this->getMedia()->createFromFile($thumb, ['type' => 'thumbnail']);
}
/**
@@ -132,6 +147,14 @@ class Medium extends Data implements RenderableInterface, MediaFileInterface
return new Link($attributes, $this);
}
/**
* @return MediaCollectionInterface
*/
protected function getMedia(): MediaCollectionInterface
{
return $this->get('media', GlobalMedia::getInstance());
}
/**
* @return Grav
*/