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 { $parts = explode(';', $mediaTypeStr); if(empty($parts)) throw new InvalidArgumentException('Invalid media type supplied.'); $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)); } }