index/src/MediaType.php
flash 5150f0cb56 Allow including Index through Composer.
index.php automatically detects if the Composer autoloader exists and doesn't initialise its own autoloader.
Also including phpunit and phpstan through it instead of including the phars, probably makes more sense to do it the other way but they're Big.
2023-07-21 18:04:29 +00:00

163 lines
4.6 KiB
PHP

<?php
// MediaType.php
// Created: 2022-02-10
// Updated: 2023-07-21
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 {
if(empty($mediaTypeStr))
throw new InvalidArgumentException('Invalid media type supplied.');
$parts = explode(';', $mediaTypeStr);
$mediaTypeStr = array_shift($parts);
$mediaTypeParts = explode('/', $mediaTypeStr, 2);
$category = $mediaTypeParts[0];
$kindSplit = explode('+', $mediaTypeParts[1] ?? '', 2);
$kind = $kindSplit[0];
$suffix = $kindSplit[1] ?? '';
$params = [];
foreach($parts as $part) {
$paramSplit = explode('=', trim($part), 2);
$params[trim($paramSplit[0])] = trim($paramSplit[1] ?? '', " \n\r\t\v\0\"");
}
return new MediaType($category, $kind, $suffix, $params);
}
public static function fromPath(string $path): MediaType {
return self::parse(mime_content_type($path));
}
}