Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/treetrek.git
<?php
require_once __DIR__ . '/FileRenderer.php';
require_once __DIR__ . '/Highlighter.php';
require_once __DIR__ . '/../UrlBuilder.php';

class HtmlFileRenderer implements FileRenderer {
  private string $repoSafeName;
  private string $currentPath;
  private string $currentRef;

  public function __construct( string $repoSafeName, string $currentPath = '', string $currentRef = 'HEAD' ) {
    $this->repoSafeName = $repoSafeName;
    $this->currentPath = trim( $currentPath, '/' );
    $this->currentRef = $currentRef;
  }

  public function renderListEntry(
    string $name,
    string $sha,
    string $mode,
    string $iconClass,
    int $timestamp,
    int $size
  ): void {
    $fullPath = ($this->currentPath === '' ? '' : $this->currentPath . '/') . $name;

    $isDir = ($mode === '40000' || $mode === '040000');
    $action = $isDir ? 'tree' : 'blob';

    $url = (new UrlBuilder())
      ->withRepo( $this->repoSafeName )
      ->withAction( $action )
      ->withHash( $this->currentRef )
      ->withName( $fullPath )
      ->build();

    echo '<tr>';
    echo '<td class="file-icon-cell"><i class="fas ' . $iconClass . '"></i></td>';
    echo '<td class="file-name-cell"><a href="' . $url . '">' . htmlspecialchars( $name ) . '</a></td>';
    echo '<td class="file-mode-cell">' . $this->formatMode( $mode ) . '</td>';
    echo '<td class="file-size-cell">' . ($size > 0 ? $this->formatSize( $size ) : '') . '</td>';
    echo '</tr>';
  }

  public function renderMedia( File $file, string $url, string $mediaType ): bool {
    if( $file->isImage() ) {
      echo '<div class="blob-content blob-content-image"><img src="' . $url . '"></div>';
      return true;
    } elseif( $file->isVideo() ) {
      echo '<div class="blob-content blob-content-video"><video controls><source src="' . $url . '" type="' . $mediaType . '"></video></div>';
      return true;
    } elseif( $file->isAudio() ) {
      echo '<div class="blob-content blob-content-audio"><audio controls><source src="' . $url . '" type="' . $mediaType . '"></audio></div>';
      return true;
    }
    return false;
  }

  public function renderSize( int $bytes ): void {
    echo $this->formatSize( $bytes );
  }

  public function highlight( string $filename, string $content, string $mediaType ): string {
    return (new Highlighter($filename, $content, $mediaType))->render();
  }

  public function renderTime( int $timestamp ): void {
    $tokens = [
      31536000 => 'year', 2592000 => 'month', 604800 => 'week',
      86400 => 'day', 3600 => 'hour', 60 => 'minute', 1 => 'second'
    ];
    $diff = $timestamp ? time() - $timestamp : null;
    $result = 'never';

    if( $diff && $diff >= 5 ) {
      foreach( $tokens as $unit => $text ) {
        if( $diff < $unit ) continue;
        $num = floor( $diff / $unit );
        $result = $num . ' ' . $text . ($num > 1 ? 's' : '') . ' ago';
        break;
      }
    } elseif( $diff ) {
      $result = 'just now';
    }

    echo $result;
  }

  private function formatSize( int $bytes ): string {
    $units = [ 'B', 'KB', 'MB', 'GB', 'TB' ];
    $i = 0;

    while( $bytes >= 1024 && $i < count( $units ) - 1 ) {
      $bytes /= 1024; $i++;
    }

    return ($bytes === 0 ? 0 : round( $bytes )) . ' ' . $units[$i];
  }

  private function formatMode( string $mode ): string {
    switch( $mode ) {
      case '100644': return 'w';
      case '100755': return 'x';
      case '040000': return 'd';
      case '120000': return 'l';
      case '160000': return 'm';
      default: return '?';
    }
  }
}