2022-09-13 13:13:11 +00:00
|
|
|
<?php
|
|
|
|
// MediaType.php
|
|
|
|
// Created: 2022-02-10
|
2023-07-22 14:25:58 +00:00
|
|
|
// Updated: 2023-07-22
|
2022-09-13 13:13:11 +00:00
|
|
|
|
|
|
|
namespace Index;
|
|
|
|
|
|
|
|
use InvalidArgumentException;
|
|
|
|
use Stringable;
|
|
|
|
|
|
|
|
class MediaType implements Stringable, IComparable, IEquatable {
|
|
|
|
private string $category = '';
|
|
|
|
private string $kind = '';
|
|
|
|
private string $suffix = '';
|
|
|
|
private array $params = [];
|
|
|
|
|
|
|
|
public function __construct(string $category, string $kind, string $suffix, array $params) {
|
|
|
|
$this->category = $category;
|
|
|
|
$this->kind = $kind;
|
|
|
|
$this->suffix = $suffix;
|
|
|
|
$this->params = $params;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCategory(): string {
|
|
|
|
return $this->category;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getKind(): string {
|
|
|
|
return $this->kind;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getSuffix(): string {
|
|
|
|
return $this->suffix;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getParams(): array {
|
|
|
|
return $this->params;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function hasParam(string $name): bool {
|
|
|
|
return isset($this->params[$name]);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getParam(string $name, int $filter = FILTER_DEFAULT, $options = null) {
|
|
|
|
if(!isset($this->params[$name]))
|
|
|
|
return null;
|
|
|
|
return filter_var($this->params[$name], $filter, $options);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCharset(): string {
|
|
|
|
return $this->getParam('charset', FILTER_DEFAULT, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH) ?? 'utf-8';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getQuality(): float {
|
|
|
|
return max(min(round($this->getParam('q', FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION) ?? 1, 2), 1), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function compareCategory(string $category): int {
|
|
|
|
return ($this->category === '*' || $category === '*')
|
|
|
|
? 0 : strcmp($this->category, $category);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function matchCategory(string $category): bool {
|
|
|
|
return $this->category === '*' || $category === '*' || $this->category === $category;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function compareKind(string $kind): int {
|
|
|
|
return ($this->kind === '*' || $kind === '*')
|
|
|
|
? 0 : strcmp($this->kind, $kind);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function matchKind(string $kind): bool {
|
|
|
|
return $this->kind === '*' || $kind === '*' || $this->kind === $kind;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function compareSuffix(string $suffix): int {
|
|
|
|
return strcmp($this->suffix, $suffix);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function matchSuffix(string $suffix): bool {
|
|
|
|
return $this->suffix === $suffix;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function compare(mixed $other): int {
|
|
|
|
if(!($other instanceof MediaType)) {
|
|
|
|
try {
|
|
|
|
$other = self::parse((string)$other);
|
|
|
|
} catch(InvalidArgumentException $ex) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(($match = self::compareCategory($other->category)) !== 0)
|
|
|
|
return $match;
|
|
|
|
if(($match = self::compareKind($other->kind)) !== 0)
|
|
|
|
return $match;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function equals(mixed $other): bool {
|
|
|
|
if(!($other instanceof MediaType)) {
|
|
|
|
try {
|
|
|
|
$other = self::parse((string)$other);
|
|
|
|
} catch(InvalidArgumentException $ex) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!$this->matchCategory($other->category))
|
|
|
|
return false;
|
|
|
|
if(!$this->matchKind($other->kind))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __toString(): string {
|
|
|
|
$string = $this->category . '/' . $this->kind;
|
|
|
|
|
|
|
|
if(!empty($this->suffix))
|
|
|
|
$string .= '+' . $this->suffix;
|
|
|
|
|
|
|
|
if(!empty($this->params))
|
|
|
|
foreach($this->params as $key => $value) {
|
|
|
|
$string .= ';';
|
|
|
|
if(is_string($key))
|
|
|
|
$string .= $key . '=';
|
|
|
|
$string .= $value;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $string;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function parse(string $mediaTypeStr): MediaType {
|
2023-07-21 18:04:29 +00:00
|
|
|
$parts = explode(';', $mediaTypeStr);
|
2023-02-01 20:24:42 +00:00
|
|
|
$mediaTypeStr = array_shift($parts);
|
|
|
|
$mediaTypeParts = explode('/', $mediaTypeStr, 2);
|
2022-09-13 13:13:11 +00:00
|
|
|
|
2023-02-01 20:24:42 +00:00
|
|
|
$category = $mediaTypeParts[0];
|
|
|
|
|
|
|
|
$kindSplit = explode('+', $mediaTypeParts[1] ?? '', 2);
|
2022-09-13 13:13:11 +00:00
|
|
|
$kind = $kindSplit[0];
|
|
|
|
$suffix = $kindSplit[1] ?? '';
|
|
|
|
|
|
|
|
$params = [];
|
|
|
|
|
2023-02-01 20:24:42 +00:00
|
|
|
foreach($parts as $part) {
|
|
|
|
$paramSplit = explode('=', trim($part), 2);
|
|
|
|
$params[trim($paramSplit[0])] = trim($paramSplit[1] ?? '', " \n\r\t\v\0\"");
|
2022-09-13 13:13:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return new MediaType($category, $kind, $suffix, $params);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static function fromPath(string $path): MediaType {
|
|
|
|
return self::parse(mime_content_type($path));
|
|
|
|
}
|
|
|
|
}
|