Update Kirby and dependencies

This commit is contained in:
Paul Nicoué 2022-08-31 15:02:43 +02:00
parent 503b339974
commit 399fa20902
439 changed files with 66915 additions and 64442 deletions

View file

@ -18,100 +18,100 @@ use Kirby\Cms\FileModifications;
*/
class Asset
{
use IsFile;
use FileModifications;
use IsFile;
use FileModifications;
/**
* Relative file path
*
* @var string
*/
protected $path;
/**
* Relative file path
*
* @var string
*/
protected $path;
/**
* Creates a new Asset object for the given path.
*
* @param string $path
*/
public function __construct(string $path)
{
$this->setProperties([
'path' => dirname($path),
'root' => $this->kirby()->root('index') . '/' . $path,
'url' => $this->kirby()->url('index') . '/' . $path
]);
}
/**
* Creates a new Asset object for the given path.
*
* @param string $path
*/
public function __construct(string $path)
{
$this->setProperties([
'path' => dirname($path),
'root' => $this->kirby()->root('index') . '/' . $path,
'url' => $this->kirby()->url('base') . '/' . $path
]);
}
/**
* Returns a unique id for the asset
*
* @return string
*/
public function id(): string
{
return $this->root();
}
/**
* Returns a unique id for the asset
*
* @return string
*/
public function id(): string
{
return $this->root();
}
/**
* Create a unique media hash
*
* @return string
*/
public function mediaHash(): string
{
return crc32($this->filename()) . '-' . $this->modified();
}
/**
* Create a unique media hash
*
* @return string
*/
public function mediaHash(): string
{
return crc32($this->filename()) . '-' . $this->modified();
}
/**
* Returns the relative path starting at the media folder
*
* @return string
*/
public function mediaPath(): string
{
return 'assets/' . $this->path() . '/' . $this->mediaHash() . '/' . $this->filename();
}
/**
* Returns the relative path starting at the media folder
*
* @return string
*/
public function mediaPath(): string
{
return 'assets/' . $this->path() . '/' . $this->mediaHash() . '/' . $this->filename();
}
/**
* Returns the absolute path to the file in the public media folder
*
* @return string
*/
public function mediaRoot(): string
{
return $this->kirby()->root('media') . '/' . $this->mediaPath();
}
/**
* Returns the absolute path to the file in the public media folder
*
* @return string
*/
public function mediaRoot(): string
{
return $this->kirby()->root('media') . '/' . $this->mediaPath();
}
/**
* Returns the absolute Url to the file in the public media folder
*
* @return string
*/
public function mediaUrl(): string
{
return $this->kirby()->url('media') . '/' . $this->mediaPath();
}
/**
* Returns the absolute Url to the file in the public media folder
*
* @return string
*/
public function mediaUrl(): string
{
return $this->kirby()->url('media') . '/' . $this->mediaPath();
}
/**
* Returns the path of the file from the web root,
* excluding the filename
*
* @return string
*/
public function path(): string
{
return $this->path;
}
/**
* Returns the path of the file from the web root,
* excluding the filename
*
* @return string
*/
public function path(): string
{
return $this->path;
}
/**
* Setter for the path
*
* @param string $path
* @return $this
*/
protected function setPath(string $path)
{
$this->path = $path === '.' ? '' : $path;
return $this;
}
/**
* Setter for the path
*
* @param string $path
* @return $this
*/
protected function setPath(string $path)
{
$this->path = $path === '.' ? '' : $path;
return $this;
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -28,280 +28,280 @@ use Kirby\Toolkit\Str;
*/
class Filename
{
/**
* List of all applicable attributes
*
* @var array
*/
protected $attributes;
/**
* List of all applicable attributes
*
* @var array
*/
protected $attributes;
/**
* The sanitized file extension
*
* @var string
*/
protected $extension;
/**
* The sanitized file extension
*
* @var string
*/
protected $extension;
/**
* The source original filename
*
* @var string
*/
protected $filename;
/**
* The source original filename
*
* @var string
*/
protected $filename;
/**
* The sanitized file name
*
* @var string
*/
protected $name;
/**
* The sanitized file name
*
* @var string
*/
protected $name;
/**
* The template for the final name
*
* @var string
*/
protected $template;
/**
* The template for the final name
*
* @var string
*/
protected $template;
/**
* Creates a new Filename object
*
* @param string $filename
* @param string $template
* @param array $attributes
*/
public function __construct(string $filename, string $template, array $attributes = [])
{
$this->filename = $filename;
$this->template = $template;
$this->attributes = $attributes;
$this->extension = $this->sanitizeExtension(
$attributes['format'] ??
pathinfo($filename, PATHINFO_EXTENSION)
);
$this->name = $this->sanitizeName(pathinfo($filename, PATHINFO_FILENAME));
}
/**
* Creates a new Filename object
*
* @param string $filename
* @param string $template
* @param array $attributes
*/
public function __construct(string $filename, string $template, array $attributes = [])
{
$this->filename = $filename;
$this->template = $template;
$this->attributes = $attributes;
$this->extension = $this->sanitizeExtension(
$attributes['format'] ??
pathinfo($filename, PATHINFO_EXTENSION)
);
$this->name = $this->sanitizeName(pathinfo($filename, PATHINFO_FILENAME));
}
/**
* Converts the entire object to a string
*
* @return string
*/
public function __toString(): string
{
return $this->toString();
}
/**
* Converts the entire object to a string
*
* @return string
*/
public function __toString(): string
{
return $this->toString();
}
/**
* Converts all processed attributes
* to an array. The array keys are already
* the shortened versions for the filename
*
* @return array
*/
public function attributesToArray(): array
{
$array = [
'dimensions' => implode('x', $this->dimensions()),
'crop' => $this->crop(),
'blur' => $this->blur(),
'bw' => $this->grayscale(),
'q' => $this->quality(),
];
/**
* Converts all processed attributes
* to an array. The array keys are already
* the shortened versions for the filename
*
* @return array
*/
public function attributesToArray(): array
{
$array = [
'dimensions' => implode('x', $this->dimensions()),
'crop' => $this->crop(),
'blur' => $this->blur(),
'bw' => $this->grayscale(),
'q' => $this->quality(),
];
$array = array_filter(
$array,
fn ($item) => $item !== null && $item !== false && $item !== ''
);
$array = array_filter(
$array,
fn ($item) => $item !== null && $item !== false && $item !== ''
);
return $array;
}
return $array;
}
/**
* Converts all processed attributes
* to a string, that can be used in the
* new filename
*
* @param string|null $prefix The prefix will be used in the filename creation
* @return string
*/
public function attributesToString(string $prefix = null): string
{
$array = $this->attributesToArray();
$result = [];
/**
* Converts all processed attributes
* to a string, that can be used in the
* new filename
*
* @param string|null $prefix The prefix will be used in the filename creation
* @return string
*/
public function attributesToString(string $prefix = null): string
{
$array = $this->attributesToArray();
$result = [];
foreach ($array as $key => $value) {
if ($value === true) {
$value = '';
}
foreach ($array as $key => $value) {
if ($value === true) {
$value = '';
}
switch ($key) {
case 'dimensions':
$result[] = $value;
break;
case 'crop':
$result[] = ($value === 'center') ? 'crop' : $key . '-' . $value;
break;
default:
$result[] = $key . $value;
}
}
switch ($key) {
case 'dimensions':
$result[] = $value;
break;
case 'crop':
$result[] = ($value === 'center') ? 'crop' : $key . '-' . $value;
break;
default:
$result[] = $key . $value;
}
}
$result = array_filter($result);
$attributes = implode('-', $result);
$result = array_filter($result);
$attributes = implode('-', $result);
if (empty($attributes) === true) {
return '';
}
if (empty($attributes) === true) {
return '';
}
return $prefix . $attributes;
}
return $prefix . $attributes;
}
/**
* Normalizes the blur option value
*
* @return false|int
*/
public function blur()
{
$value = $this->attributes['blur'] ?? false;
/**
* Normalizes the blur option value
*
* @return false|int
*/
public function blur()
{
$value = $this->attributes['blur'] ?? false;
if ($value === false) {
return false;
}
if ($value === false) {
return false;
}
return (int)$value;
}
return (int)$value;
}
/**
* Normalizes the crop option value
*
* @return false|string
*/
public function crop()
{
// get the crop value
$crop = $this->attributes['crop'] ?? false;
/**
* Normalizes the crop option value
*
* @return false|string
*/
public function crop()
{
// get the crop value
$crop = $this->attributes['crop'] ?? false;
if ($crop === false) {
return false;
}
if ($crop === false) {
return false;
}
return Str::slug($crop);
}
return Str::slug($crop);
}
/**
* Returns a normalized array
* with width and height values
* if available
*
* @return array
*/
public function dimensions()
{
if (empty($this->attributes['width']) === true && empty($this->attributes['height']) === true) {
return [];
}
/**
* Returns a normalized array
* with width and height values
* if available
*
* @return array
*/
public function dimensions()
{
if (empty($this->attributes['width']) === true && empty($this->attributes['height']) === true) {
return [];
}
return [
'width' => $this->attributes['width'] ?? null,
'height' => $this->attributes['height'] ?? null
];
}
return [
'width' => $this->attributes['width'] ?? null,
'height' => $this->attributes['height'] ?? null
];
}
/**
* Returns the sanitized extension
*
* @return string
*/
public function extension(): string
{
return $this->extension;
}
/**
* Returns the sanitized extension
*
* @return string
*/
public function extension(): string
{
return $this->extension;
}
/**
* Normalizes the grayscale option value
* and also the available ways to write
* the option. You can use `grayscale`,
* `greyscale` or simply `bw`. The function
* will always return `grayscale`
*
* @return bool
*/
public function grayscale(): bool
{
// normalize options
$value = $this->attributes['grayscale'] ?? $this->attributes['greyscale'] ?? $this->attributes['bw'] ?? false;
/**
* Normalizes the grayscale option value
* and also the available ways to write
* the option. You can use `grayscale`,
* `greyscale` or simply `bw`. The function
* will always return `grayscale`
*
* @return bool
*/
public function grayscale(): bool
{
// normalize options
$value = $this->attributes['grayscale'] ?? $this->attributes['greyscale'] ?? $this->attributes['bw'] ?? false;
// turn anything into boolean
return filter_var($value, FILTER_VALIDATE_BOOLEAN);
}
// turn anything into boolean
return filter_var($value, FILTER_VALIDATE_BOOLEAN);
}
/**
* Returns the filename without extension
*
* @return string
*/
public function name(): string
{
return $this->name;
}
/**
* Returns the filename without extension
*
* @return string
*/
public function name(): string
{
return $this->name;
}
/**
* Normalizes the quality option value
*
* @return false|int
*/
public function quality()
{
$value = $this->attributes['quality'] ?? false;
/**
* Normalizes the quality option value
*
* @return false|int
*/
public function quality()
{
$value = $this->attributes['quality'] ?? false;
if ($value === false || $value === true) {
return false;
}
if ($value === false || $value === true) {
return false;
}
return (int)$value;
}
return (int)$value;
}
/**
* Sanitizes the file extension.
* The extension will be converted
* to lowercase and `jpeg` will be
* replaced with `jpg`
*
* @param string $extension
* @return string
*/
protected function sanitizeExtension(string $extension): string
{
$extension = strtolower($extension);
$extension = str_replace('jpeg', 'jpg', $extension);
return $extension;
}
/**
* Sanitizes the file extension.
* The extension will be converted
* to lowercase and `jpeg` will be
* replaced with `jpg`
*
* @param string $extension
* @return string
*/
protected function sanitizeExtension(string $extension): string
{
$extension = strtolower($extension);
$extension = str_replace('jpeg', 'jpg', $extension);
return $extension;
}
/**
* Sanitizes the name with Kirby's
* Str::slug function
*
* @param string $name
* @return string
*/
protected function sanitizeName(string $name): string
{
return Str::slug($name);
}
/**
* Sanitizes the name with Kirby's
* Str::slug function
*
* @param string $name
* @return string
*/
protected function sanitizeName(string $name): string
{
return Str::slug($name);
}
/**
* Returns the converted filename as string
*
* @return string
*/
public function toString(): string
{
return Str::template($this->template, [
'name' => $this->name(),
'attributes' => $this->attributesToString('-'),
'extension' => $this->extension()
], ['fallback' => '']);
}
/**
* Returns the converted filename as string
*
* @return string
*/
public function toString(): string
{
return Str::template($this->template, [
'name' => $this->name(),
'attributes' => $this->attributesToString('-'),
'extension' => $this->extension()
], ['fallback' => '']);
}
}

View file

@ -22,175 +22,175 @@ use Kirby\Toolkit\Properties;
*/
trait IsFile
{
use Properties;
use Properties;
/**
* File asset object
*
* @var \Kirby\Filesystem\File
*/
protected $asset;
/**
* File asset object
*
* @var \Kirby\Filesystem\File
*/
protected $asset;
/**
* Absolute file path
*
* @var string|null
*/
protected $root;
/**
* Absolute file path
*
* @var string|null
*/
protected $root;
/**
* Absolute file URL
*
* @var string|null
*/
protected $url;
/**
* Absolute file URL
*
* @var string|null
*/
protected $url;
/**
* Constructor sets all file properties
*
* @param array $props
*/
public function __construct(array $props)
{
$this->setProperties($props);
}
/**
* Constructor sets all file properties
*
* @param array $props
*/
public function __construct(array $props)
{
$this->setProperties($props);
}
/**
* Magic caller for asset methods
*
* @param string $method
* @param array $arguments
* @return mixed
* @throws \Kirby\Exception\BadMethodCallException
*/
public function __call(string $method, array $arguments = [])
{
// public property access
if (isset($this->$method) === true) {
return $this->$method;
}
/**
* Magic caller for asset methods
*
* @param string $method
* @param array $arguments
* @return mixed
* @throws \Kirby\Exception\BadMethodCallException
*/
public function __call(string $method, array $arguments = [])
{
// public property access
if (isset($this->$method) === true) {
return $this->$method;
}
// asset method proxy
if (method_exists($this->asset(), $method)) {
return $this->asset()->$method(...$arguments);
}
// asset method proxy
if (method_exists($this->asset(), $method)) {
return $this->asset()->$method(...$arguments);
}
throw new BadMethodCallException('The method: "' . $method . '" does not exist');
}
throw new BadMethodCallException('The method: "' . $method . '" does not exist');
}
/**
* Converts the asset to a string
*
* @return string
*/
public function __toString(): string
{
return (string)$this->asset();
}
/**
* Converts the asset to a string
*
* @return string
*/
public function __toString(): string
{
return (string)$this->asset();
}
/**
* Returns the file asset object
*
* @param array|string|null $props
* @return \Kirby\Filesystem\File
*/
public function asset($props = null)
{
if ($this->asset !== null) {
return $this->asset;
}
/**
* Returns the file asset object
*
* @param array|string|null $props
* @return \Kirby\Filesystem\File
*/
public function asset($props = null)
{
if ($this->asset !== null) {
return $this->asset;
}
$props = $props ?? [
'root' => $this->root(),
'url' => $this->url()
];
$props = $props ?? [
'root' => $this->root(),
'url' => $this->url()
];
switch ($this->type()) {
case 'image':
return $this->asset = new Image($props);
default:
return $this->asset = new File($props);
}
}
switch ($this->type()) {
case 'image':
return $this->asset = new Image($props);
default:
return $this->asset = new File($props);
}
}
/**
* Checks if the file exists on disk
*
* @return bool
*/
public function exists(): bool
{
// Important to include this in the trait
// to avoid infinite loops when trying
// to proxy the method from the asset object
return file_exists($this->root()) === true;
}
/**
* Checks if the file exists on disk
*
* @return bool
*/
public function exists(): bool
{
// Important to include this in the trait
// to avoid infinite loops when trying
// to proxy the method from the asset object
return file_exists($this->root()) === true;
}
/**
* Returns the app instance
*
* @return \Kirby\Cms\App
*/
public function kirby()
{
return App::instance();
}
/**
* Returns the app instance
*
* @return \Kirby\Cms\App
*/
public function kirby()
{
return App::instance();
}
/**
* Returns the given file path
*
* @return string|null
*/
public function root(): ?string
{
return $this->root;
}
/**
* Returns the given file path
*
* @return string|null
*/
public function root(): ?string
{
return $this->root;
}
/**
* Setter for the root
*
* @param string|null $root
* @return $this
*/
protected function setRoot(?string $root = null)
{
$this->root = $root;
return $this;
}
/**
* Setter for the root
*
* @param string|null $root
* @return $this
*/
protected function setRoot(?string $root = null)
{
$this->root = $root;
return $this;
}
/**
* Setter for the file url
*
* @param string|null $url
* @return $this
*/
protected function setUrl(?string $url = null)
{
$this->url = $url;
return $this;
}
/**
* Setter for the file url
*
* @param string|null $url
* @return $this
*/
protected function setUrl(?string $url = null)
{
$this->url = $url;
return $this;
}
/**
* Returns the file type
*
* @return string|null
*/
public function type(): ?string
{
// Important to include this in the trait
// to avoid infinite loops when trying
// to proxy the method from the asset object
return F::type($this->root() ?? $this->url());
}
/**
* Returns the file type
*
* @return string|null
*/
public function type(): ?string
{
// Important to include this in the trait
// to avoid infinite loops when trying
// to proxy the method from the asset object
return F::type($this->root() ?? $this->url());
}
/**
* Returns the absolute url for the file
*
* @return string|null
*/
public function url(): ?string
{
return $this->url;
}
/**
* Returns the absolute url for the file
*
* @return string|null
*/
public function url(): ?string
{
return $this->url;
}
}

View file

@ -19,325 +19,333 @@ use SimpleXMLElement;
*/
class Mime
{
/**
* Extension to MIME type map
*
* @var array
*/
public static $types = [
'ai' => 'application/postscript',
'aif' => 'audio/x-aiff',
'aifc' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff',
'avi' => 'video/x-msvideo',
'avif' => 'image/avif',
'bmp' => 'image/bmp',
'css' => 'text/css',
'csv' => ['text/csv', 'text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream'],
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'dvi' => 'application/x-dvi',
'eml' => 'message/rfc822',
'eps' => 'application/postscript',
'exe' => ['application/octet-stream', 'application/x-msdownload'],
'gif' => 'image/gif',
'gtar' => 'application/x-gtar',
'gz' => 'application/x-gzip',
'htm' => 'text/html',
'html' => 'text/html',
'ico' => 'image/x-icon',
'ics' => 'text/calendar',
'js' => ['application/javascript', 'application/x-javascript'],
'json' => ['application/json', 'text/json'],
'j2k' => ['image/jp2'],
'jp2' => ['image/jp2'],
'jpg' => ['image/jpeg', 'image/pjpeg'],
'jpeg' => ['image/jpeg', 'image/pjpeg'],
'jpe' => ['image/jpeg', 'image/pjpeg'],
'log' => ['text/plain', 'text/x-log'],
'm4a' => 'audio/mp4',
'm4v' => 'video/mp4',
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mif' => 'application/vnd.mif',
'mov' => 'video/quicktime',
'movie' => 'video/x-sgi-movie',
'mp2' => 'audio/mpeg',
'mp3' => ['audio/mpeg', 'audio/mpg', 'audio/mpeg3', 'audio/mp3'],
'mp4' => 'video/mp4',
'mpe' => 'video/mpeg',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpga' => 'audio/mpeg',
'odc' => 'application/vnd.oasis.opendocument.chart',
'odp' => 'application/vnd.oasis.opendocument.presentation',
'odt' => 'application/vnd.oasis.opendocument.text',
'pdf' => ['application/pdf', 'application/x-download'],
'php' => ['text/php', 'text/x-php', 'application/x-httpd-php', 'application/php', 'application/x-php', 'application/x-httpd-php-source'],
'php3' => ['text/php', 'text/x-php', 'application/x-httpd-php', 'application/php', 'application/x-php', 'application/x-httpd-php-source'],
'phps' => ['text/php', 'text/x-php', 'application/x-httpd-php', 'application/php', 'application/x-php', 'application/x-httpd-php-source'],
'phtml' => ['text/php', 'text/x-php', 'application/x-httpd-php', 'application/php', 'application/x-php', 'application/x-httpd-php-source'],
'png' => 'image/png',
'ppt' => ['application/powerpoint', 'application/vnd.ms-powerpoint'],
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
'ps' => 'application/postscript',
'psd' => 'application/x-photoshop',
'qt' => 'video/quicktime',
'rss' => 'application/rss+xml',
'rtf' => 'text/rtf',
'rtx' => 'text/richtext',
'shtml' => 'text/html',
'svg' => 'image/svg+xml',
'swf' => 'application/x-shockwave-flash',
'tar' => 'application/x-tar',
'text' => 'text/plain',
'txt' => 'text/plain',
'tgz' => ['application/x-tar', 'application/x-gzip-compressed'],
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'wav' => 'audio/x-wav',
'wbxml' => 'application/wbxml',
'webm' => 'video/webm',
'webp' => 'image/webp',
'word' => ['application/msword', 'application/octet-stream'],
'xhtml' => 'application/xhtml+xml',
'xht' => 'application/xhtml+xml',
'xml' => 'text/xml',
'xl' => 'application/excel',
'xls' => ['application/excel', 'application/vnd.ms-excel', 'application/msexcel'],
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'xsl' => 'text/xml',
'yaml' => ['application/yaml', 'text/yaml'],
'yml' => ['application/yaml', 'text/yaml'],
'zip' => ['application/x-zip', 'application/zip', 'application/x-zip-compressed'],
];
/**
* Extension to MIME type map
*
* @var array
*/
public static $types = [
'ai' => 'application/postscript',
'aif' => 'audio/x-aiff',
'aifc' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff',
'avi' => 'video/x-msvideo',
'avif' => 'image/avif',
'bmp' => 'image/bmp',
'css' => 'text/css',
'csv' => ['text/csv', 'text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream'],
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'dvi' => 'application/x-dvi',
'eml' => 'message/rfc822',
'eps' => 'application/postscript',
'exe' => ['application/octet-stream', 'application/x-msdownload'],
'gif' => 'image/gif',
'gtar' => 'application/x-gtar',
'gz' => 'application/x-gzip',
'htm' => 'text/html',
'html' => 'text/html',
'ico' => 'image/x-icon',
'ics' => 'text/calendar',
'js' => ['application/javascript', 'application/x-javascript'],
'json' => ['application/json', 'text/json'],
'j2k' => ['image/jp2'],
'jp2' => ['image/jp2'],
'jpg' => ['image/jpeg', 'image/pjpeg'],
'jpeg' => ['image/jpeg', 'image/pjpeg'],
'jpe' => ['image/jpeg', 'image/pjpeg'],
'log' => ['text/plain', 'text/x-log'],
'm4a' => 'audio/mp4',
'm4v' => 'video/mp4',
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mif' => 'application/vnd.mif',
'mjs' => 'text/javascript',
'mov' => 'video/quicktime',
'movie' => 'video/x-sgi-movie',
'mp2' => 'audio/mpeg',
'mp3' => ['audio/mpeg', 'audio/mpg', 'audio/mpeg3', 'audio/mp3'],
'mp4' => 'video/mp4',
'mpe' => 'video/mpeg',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpga' => 'audio/mpeg',
'odc' => 'application/vnd.oasis.opendocument.chart',
'odp' => 'application/vnd.oasis.opendocument.presentation',
'odt' => 'application/vnd.oasis.opendocument.text',
'pdf' => ['application/pdf', 'application/x-download'],
'php' => ['text/php', 'text/x-php', 'application/x-httpd-php', 'application/php', 'application/x-php', 'application/x-httpd-php-source'],
'php3' => ['text/php', 'text/x-php', 'application/x-httpd-php', 'application/php', 'application/x-php', 'application/x-httpd-php-source'],
'phps' => ['text/php', 'text/x-php', 'application/x-httpd-php', 'application/php', 'application/x-php', 'application/x-httpd-php-source'],
'phtml' => ['text/php', 'text/x-php', 'application/x-httpd-php', 'application/php', 'application/x-php', 'application/x-httpd-php-source'],
'png' => 'image/png',
'ppt' => ['application/powerpoint', 'application/vnd.ms-powerpoint'],
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
'ps' => 'application/postscript',
'psd' => 'application/x-photoshop',
'qt' => 'video/quicktime',
'rss' => 'application/rss+xml',
'rtf' => 'text/rtf',
'rtx' => 'text/richtext',
'shtml' => 'text/html',
'svg' => 'image/svg+xml',
'swf' => 'application/x-shockwave-flash',
'tar' => 'application/x-tar',
'text' => 'text/plain',
'txt' => 'text/plain',
'tgz' => ['application/x-tar', 'application/x-gzip-compressed'],
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'wav' => 'audio/x-wav',
'wbxml' => 'application/wbxml',
'webm' => 'video/webm',
'webp' => 'image/webp',
'word' => ['application/msword', 'application/octet-stream'],
'xhtml' => 'application/xhtml+xml',
'xht' => 'application/xhtml+xml',
'xml' => 'text/xml',
'xl' => 'application/excel',
'xls' => ['application/excel', 'application/vnd.ms-excel', 'application/msexcel'],
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
'xsl' => 'text/xml',
'yaml' => ['application/yaml', 'text/yaml'],
'yml' => ['application/yaml', 'text/yaml'],
'zip' => ['application/x-zip', 'application/zip', 'application/x-zip-compressed'],
];
/**
* Fixes an invalid MIME type guess for the given file
*
* @param string $file
* @param string $mime
* @param string $extension
* @return string|null
*/
public static function fix(string $file, string $mime = null, string $extension = null)
{
// fixing map
$map = [
'text/html' => [
'svg' => ['Kirby\Filesystem\Mime', 'fromSvg'],
],
'text/plain' => [
'css' => 'text/css',
'json' => 'application/json',
'svg' => ['Kirby\Filesystem\Mime', 'fromSvg'],
],
'text/x-asm' => [
'css' => 'text/css'
],
'image/svg' => [
'svg' => 'image/svg+xml'
]
];
/**
* Fixes an invalid MIME type guess for the given file
*
* @param string $file
* @param string $mime
* @param string $extension
* @return string|null
*/
public static function fix(string $file, string $mime = null, string $extension = null)
{
// fixing map
$map = [
'text/html' => [
'svg' => ['Kirby\Filesystem\Mime', 'fromSvg'],
],
'text/plain' => [
'css' => 'text/css',
'json' => 'application/json',
'mjs' => 'text/javascript',
'svg' => ['Kirby\Filesystem\Mime', 'fromSvg'],
],
'text/x-asm' => [
'css' => 'text/css'
],
'text/x-java' => [
'mjs' => 'text/javascript',
],
'image/svg' => [
'svg' => 'image/svg+xml'
],
'application/octet-stream' => [
'mjs' => 'text/javascript'
]
];
if ($mode = ($map[$mime][$extension] ?? null)) {
if (is_callable($mode) === true) {
return $mode($file, $mime, $extension);
}
if ($mode = ($map[$mime][$extension] ?? null)) {
if (is_callable($mode) === true) {
return $mode($file, $mime, $extension);
}
if (is_string($mode) === true) {
return $mode;
}
}
if (is_string($mode) === true) {
return $mode;
}
}
return $mime;
}
return $mime;
}
/**
* Guesses a MIME type by extension
*
* @param string $extension
* @return string|null
*/
public static function fromExtension(string $extension): ?string
{
$mime = static::$types[$extension] ?? null;
return is_array($mime) === true ? array_shift($mime) : $mime;
}
/**
* Guesses a MIME type by extension
*
* @param string $extension
* @return string|null
*/
public static function fromExtension(string $extension): ?string
{
$mime = static::$types[$extension] ?? null;
return is_array($mime) === true ? array_shift($mime) : $mime;
}
/**
* Returns the MIME type of a file
*
* @param string $file
* @return string|false
*/
public static function fromFileInfo(string $file)
{
if (function_exists('finfo_file') === true && file_exists($file) === true) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file);
finfo_close($finfo);
return $mime;
}
/**
* Returns the MIME type of a file
*
* @param string $file
* @return string|false
*/
public static function fromFileInfo(string $file)
{
if (function_exists('finfo_file') === true && file_exists($file) === true) {
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $file);
finfo_close($finfo);
return $mime;
}
return false;
}
return false;
}
/**
* Returns the MIME type of a file
*
* @param string $file
* @return string|false
*/
public static function fromMimeContentType(string $file)
{
if (function_exists('mime_content_type') === true && file_exists($file) === true) {
return mime_content_type($file);
}
/**
* Returns the MIME type of a file
*
* @param string $file
* @return string|false
*/
public static function fromMimeContentType(string $file)
{
if (function_exists('mime_content_type') === true && file_exists($file) === true) {
return mime_content_type($file);
}
return false;
}
return false;
}
/**
* Tries to detect a valid SVG and returns the MIME type accordingly
*
* @param string $file
* @return string|false
*/
public static function fromSvg(string $file)
{
if (file_exists($file) === true) {
libxml_use_internal_errors(true);
/**
* Tries to detect a valid SVG and returns the MIME type accordingly
*
* @param string $file
* @return string|false
*/
public static function fromSvg(string $file)
{
if (file_exists($file) === true) {
libxml_use_internal_errors(true);
$svg = new SimpleXMLElement(file_get_contents($file));
$svg = new SimpleXMLElement(file_get_contents($file));
if ($svg !== false && $svg->getName() === 'svg') {
return 'image/svg+xml';
}
}
if ($svg !== false && $svg->getName() === 'svg') {
return 'image/svg+xml';
}
}
return false;
}
return false;
}
/**
* Tests if a given MIME type is matched by an `Accept` header
* pattern; returns true if the MIME type is contained at all
*
* @param string $mime
* @param string $pattern
* @return bool
*/
public static function isAccepted(string $mime, string $pattern): bool
{
$accepted = Str::accepted($pattern);
/**
* Tests if a given MIME type is matched by an `Accept` header
* pattern; returns true if the MIME type is contained at all
*
* @param string $mime
* @param string $pattern
* @return bool
*/
public static function isAccepted(string $mime, string $pattern): bool
{
$accepted = Str::accepted($pattern);
foreach ($accepted as $m) {
if (static::matches($mime, $m['value']) === true) {
return true;
}
}
foreach ($accepted as $m) {
if (static::matches($mime, $m['value']) === true) {
return true;
}
}
return false;
}
return false;
}
/**
* Tests if a MIME wildcard pattern from an `Accept` header
* matches a given type
* @since 3.3.0
*
* @param string $test
* @param string $wildcard
* @return bool
*/
public static function matches(string $test, string $wildcard): bool
{
return fnmatch($wildcard, $test, FNM_PATHNAME) === true;
}
/**
* Tests if a MIME wildcard pattern from an `Accept` header
* matches a given type
* @since 3.3.0
*
* @param string $test
* @param string $wildcard
* @return bool
*/
public static function matches(string $test, string $wildcard): bool
{
return fnmatch($wildcard, $test, FNM_PATHNAME) === true;
}
/**
* Returns the extension for a given MIME type
*
* @param string|null $mime
* @return string|false
*/
public static function toExtension(string $mime = null)
{
foreach (static::$types as $key => $value) {
if (is_array($value) === true && in_array($mime, $value) === true) {
return $key;
}
/**
* Returns the extension for a given MIME type
*
* @param string|null $mime
* @return string|false
*/
public static function toExtension(string $mime = null)
{
foreach (static::$types as $key => $value) {
if (is_array($value) === true && in_array($mime, $value) === true) {
return $key;
}
if ($value === $mime) {
return $key;
}
}
if ($value === $mime) {
return $key;
}
}
return false;
}
return false;
}
/**
* Returns all available extensions for a given MIME type
*
* @param string|null $mime
* @return array
*/
public static function toExtensions(string $mime = null): array
{
$extensions = [];
/**
* Returns all available extensions for a given MIME type
*
* @param string|null $mime
* @return array
*/
public static function toExtensions(string $mime = null): array
{
$extensions = [];
foreach (static::$types as $key => $value) {
if (is_array($value) === true && in_array($mime, $value) === true) {
$extensions[] = $key;
continue;
}
foreach (static::$types as $key => $value) {
if (is_array($value) === true && in_array($mime, $value) === true) {
$extensions[] = $key;
continue;
}
if ($value === $mime) {
$extensions[] = $key;
}
}
if ($value === $mime) {
$extensions[] = $key;
}
}
return $extensions;
}
return $extensions;
}
/**
* Returns the MIME type of a file
*
* @param string $file
* @param string $extension
* @return string|false
*/
public static function type(string $file, string $extension = null)
{
// use the standard finfo extension
$mime = static::fromFileInfo($file);
/**
* Returns the MIME type of a file
*
* @param string $file
* @param string $extension
* @return string|false
*/
public static function type(string $file, string $extension = null)
{
// use the standard finfo extension
$mime = static::fromFileInfo($file);
// use the mime_content_type function
if ($mime === false) {
$mime = static::fromMimeContentType($file);
}
// use the mime_content_type function
if ($mime === false) {
$mime = static::fromMimeContentType($file);
}
// get the extension or extract it from the filename
$extension ??= F::extension($file);
// get the extension or extract it from the filename
$extension ??= F::extension($file);
// try to guess the mime type at least
if ($mime === false) {
$mime = static::fromExtension($extension);
}
// try to guess the mime type at least
if ($mime === false) {
$mime = static::fromExtension($extension);
}
// fix broken mime detection
return static::fix($file, $mime, $extension);
}
// fix broken mime detection
return static::fix($file, $mime, $extension);
}
/**
* Returns all detectable MIME types
*
* @return array
*/
public static function types(): array
{
return static::$types;
}
/**
* Returns all detectable MIME types
*
* @return array
*/
public static function types(): array
{
return static::$types;
}
}