<?php require_once 'MediaTypeSniffer.php'; require_once 'FileRenderer.php'; class File { private string $name; private string $sha; private string $mode; private int $timestamp; private int $size; private bool $isDir; public function __construct(string $name, string $sha, string $mode, int $timestamp = 0, int $size = 0) { $this->name = $name; $this->sha = $sha; $this->mode = $mode; $this->timestamp = $timestamp; $this->size = $size; $this->isDir = ($mode === '40000' || $mode === '040000'); } public function compare(File $other): int { if ($this->isDir !== $other->isDir) { return $this->isDir ? -1 : 1; } return strcasecmp($this->name, $other->name); } public function render(FileRenderer $renderer): void { $renderer->renderFileItem( $this->name, $this->sha, $this->mode, $this->getIconClass(), $this->timestamp, $this->isDir ? '' : $this->getFormattedSize() ); } private function getIconClass(): string { if ($this->isDir) return 'fa-folder'; return match (true) { $this->isType('application/pdf') => 'fa-file-pdf', $this->isCategory(MediaTypeSniffer::CAT_ARCHIVE) => 'fa-file-archive', $this->isCategory(MediaTypeSniffer::CAT_IMAGE) => 'fa-file-image', $this->isCategory(MediaTypeSniffer::CAT_AUDIO) => 'fa-file-audio', $this->isCategory(MediaTypeSniffer::CAT_VIDEO) => 'fa-file-video', $this->isCategory(MediaTypeSniffer::CAT_TEXT) => 'fa-file-code', default => 'fa-file', }; } private function getFormattedSize(): string { if ($this->size <= 0) return '0 B'; $units = ['B', 'KB', 'MB', 'GB']; $i = (int)floor(log($this->size, 1024)); return round($this->size / pow(1024, $i), 1) . ' ' . $units[$i]; } public function isType(string $type): bool { return str_contains(MediaTypeSniffer::isMediaType($this->getSniffBuffer(), $this->name), $type); } public function isCategory(string $category): bool { return MediaTypeSniffer::isCategory($this->getSniffBuffer(), $this->name) === $category; } public function isBinary(): bool { return MediaTypeSniffer::isBinary($this->getSniffBuffer(), $this->name); } private function getSniffBuffer(): string { if ($this->isDir || !file_exists($this->name)) return ''; $handle = @fopen($this->name, 'rb'); if (!$handle) return ''; $read = fread($handle, 12); fclose($handle); return ($read !== false) ? $read : ''; } }