Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/treetrek.git
<?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 : '';
  }
}