first version

This commit is contained in:
Bastian Allgeier
2019-01-13 23:17:34 +01:00
commit 01277f79f2
595 changed files with 82913 additions and 0 deletions

305
kirby/src/Image/Image.php Executable file
View 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();
}
}