first version
This commit is contained in:
305
kirby/src/Image/Image.php
Executable file
305
kirby/src/Image/Image.php
Executable file
@@ -0,0 +1,305 @@
|
||||
<?php
|
||||
|
||||
namespace Kirby\Image;
|
||||
|
||||
use Exception;
|
||||
use Kirby\Http\Response;
|
||||
use Kirby\Toolkit\File;
|
||||
use Kirby\Toolkit\Html;
|
||||
use Kirby\Toolkit\Mime;
|
||||
use Kirby\Toolkit\Str;
|
||||
use Kirby\Toolkit\V;
|
||||
|
||||
/**
|
||||
* A representation of an image/media file
|
||||
* with dimensions, optional exif data and
|
||||
* a connection to our darkroom classes to resize/crop
|
||||
* images.
|
||||
*
|
||||
* @package Kirby Image
|
||||
* @author Bastian Allgeier <bastian@getkirby.com>
|
||||
* @link http://getkirby.com
|
||||
* @copyright Bastian Allgeier
|
||||
* @license MIT
|
||||
*/
|
||||
class Image extends File
|
||||
{
|
||||
|
||||
/**
|
||||
* optional url where the file is reachable
|
||||
* @var string
|
||||
*/
|
||||
protected $url;
|
||||
|
||||
/**
|
||||
* @var Exif|null
|
||||
*/
|
||||
protected $exif;
|
||||
|
||||
/**
|
||||
* @var Dimensions|null
|
||||
*/
|
||||
protected $dimensions;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $root
|
||||
* @param string|null $url
|
||||
*/
|
||||
public function __construct(string $root = null, string $url = null)
|
||||
{
|
||||
parent::__construct($root);
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improved var_dump() output
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __debuginfo(): array
|
||||
{
|
||||
return array_merge($this->toArray(), [
|
||||
'dimensions' => $this->dimensions(),
|
||||
'exif' => $this->exif(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a full link to this file
|
||||
* Perfect for debugging in connection with echo
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the file if possible
|
||||
*
|
||||
* @return Dimensions
|
||||
*/
|
||||
public function dimensions(): Dimensions
|
||||
{
|
||||
if ($this->dimensions !== null) {
|
||||
return $this->dimensions;
|
||||
}
|
||||
|
||||
if (in_array($this->mime(), ['image/jpeg', 'image/png', 'image/gif'])) {
|
||||
return $this->dimensions = Dimensions::forImage($this->root);
|
||||
}
|
||||
|
||||
if ($this->extension() === 'svg') {
|
||||
return $this->dimensions = Dimensions::forSvg($this->root);
|
||||
}
|
||||
|
||||
return $this->dimensions = new Dimensions(0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Automatically sends all needed headers for the file to be downloaded
|
||||
* and echos the file's content
|
||||
*
|
||||
* @param string|null $filename Optional filename for the download
|
||||
* @return string
|
||||
*/
|
||||
public function download($filename = null): string
|
||||
{
|
||||
return Response::download($this->root, $filename ?? $this->filename());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exif object for this file (if image)
|
||||
*
|
||||
* @return Exif
|
||||
*/
|
||||
public function exif(): Exif
|
||||
{
|
||||
if ($this->exif !== null) {
|
||||
return $this->exif;
|
||||
}
|
||||
$this->exif = new Exif($this);
|
||||
return $this->exif;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an appropriate header for the asset
|
||||
*
|
||||
* @param boolean $send
|
||||
* @return Response|string
|
||||
*/
|
||||
public function header(bool $send = true)
|
||||
{
|
||||
$response = new Response();
|
||||
$response->type($this->mime());
|
||||
return $send === true ? $response->send() : $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the height of the asset
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function height(): int
|
||||
{
|
||||
return $this->dimensions()->height();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $attr
|
||||
* @return string
|
||||
*/
|
||||
public function html(array $attr = []): string
|
||||
{
|
||||
return Html::img($this->url(), $attr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the PHP imagesize array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function imagesize(): array
|
||||
{
|
||||
return getimagesize($this->root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the dimensions of the asset are portrait
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isPortrait(): bool
|
||||
{
|
||||
return $this->dimensions()->portrait();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the dimensions of the asset are landscape
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isLandscape(): bool
|
||||
{
|
||||
return $this->dimensions()->landscape();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the dimensions of the asset are square
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isSquare(): bool
|
||||
{
|
||||
return $this->dimensions()->square();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a set of validations on the image object
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function match(array $rules): bool
|
||||
{
|
||||
if (($rules['mime'] ?? null) !== null) {
|
||||
if (Mime::isAccepted($this->mime(), $rules['mime']) !== true) {
|
||||
throw new Exception(sprintf('Invalid mime type: %s', $this->mime()));
|
||||
}
|
||||
}
|
||||
|
||||
$rules = array_change_key_case($rules);
|
||||
|
||||
$validations = [
|
||||
'maxsize' => ['size', 'max', 'The file is too large'],
|
||||
'minsize' => ['size', 'min', 'The file is too small'],
|
||||
'maxwidth' => ['width', 'max', 'The width of the image must not exceed %s pixels'],
|
||||
'minwidth' => ['width', 'min', 'The width of the image must be at least %s pixels'],
|
||||
'maxheight' => ['height', 'max', 'The height of the image must not exceed %s pixels'],
|
||||
'minheight' => ['height', 'min', 'The height of the image must be at least %s pixels'],
|
||||
'orientation' => ['orientation', 'same', 'The orientation of the image must be "%s"']
|
||||
];
|
||||
|
||||
foreach ($validations as $key => $arguments) {
|
||||
if (isset($rules[$key]) === true && $rules[$key] !== null) {
|
||||
$property = $arguments[0];
|
||||
$validator = $arguments[1];
|
||||
$message = $arguments[2];
|
||||
|
||||
if (V::$validator($this->$property(), $rules[$key]) === false) {
|
||||
throw new Exception(sprintf($message, $rules[$key]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ratio of the asset
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function ratio(): float
|
||||
{
|
||||
return $this->dimensions()->ratio();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the orientation as string
|
||||
* landscape | portrait | square
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function orientation(): string
|
||||
{
|
||||
return $this->dimensions()->orientation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the media object to a
|
||||
* plain PHP array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
return array_merge(parent::toArray(), [
|
||||
'dimensions' => $this->dimensions()->toArray(),
|
||||
'exif' => $this->exif()->toArray(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the entire file array into
|
||||
* a json string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function toJson(): string
|
||||
{
|
||||
return json_encode($this->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function url()
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width of the asset
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function width(): int
|
||||
{
|
||||
return $this->dimensions()->width();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user