| | private $hash; |
| | |
| | - public function __construct($allRepos, $currentRepo, $git, $hash) { |
| | - parent::__construct($allRepos); |
| | + public function __construct( $allRepos, $currentRepo, $git, $hash ) { |
| | + parent::__construct( $allRepos ); |
| | + |
| | $this->currentRepo = $currentRepo; |
| | - $this->git = $git; |
| | - $this->hash = $hash; |
| | - $this->title = $currentRepo['name']; |
| | + $this->git = $git; |
| | + $this->hash = $hash; |
| | + $this->title = $currentRepo['name']; |
| | } |
| | |
| | public function render() { |
| | - $this->renderLayout(function() { |
| | + $this->renderLayout( function() { |
| | $main = $this->git->getMainBranch(); |
| | - if (!$main) { |
| | + |
| | + if( !$main ) { |
| | echo '<div class="empty-state"><h3>No branches</h3></div>'; |
| | + |
| | return; |
| | } |
| | |
| | - $target = $this->hash ?: $main['hash']; |
| | + $target = $this->hash ?: $main['hash']; |
| | $entries = []; |
| | |
| | - $this->git->walk($target, function($file) use (&$entries) { |
| | + $this->git->walk( $target, function( $file ) use ( &$entries ) { |
| | $entries[] = $file; |
| | - }); |
| | + } ); |
| | |
| | - if (!empty($entries)) { |
| | - $this->renderTree($main, $target, $entries); |
| | + if( !empty( $entries ) ) { |
| | + $this->renderTree( $main, $target, $entries ); |
| | } else { |
| | - $this->renderBlob($target); |
| | + $this->renderBlob( $target ); |
| | } |
| | - }, $this->currentRepo); |
| | + }, $this->currentRepo ); |
| | } |
| | |
| | - private function renderTree($main, $targetHash, $entries) { |
| | - $this->renderBreadcrumbs($targetHash, 'Tree'); |
| | - echo '<h2>' . htmlspecialchars($this->currentRepo['name']) . |
| | - ' <span class="branch-badge">' . |
| | - htmlspecialchars($main['name']) . '</span></h2>'; |
| | + private function renderTree( $main, $targetHash, $entries ) { |
| | + $path = $_GET['name'] ?? ''; |
| | |
| | - usort($entries, function($a, $b) { |
| | - return $a->compare($b); |
| | - }); |
| | + $this->renderBreadcrumbs( $targetHash, 'Tree' ); |
| | + |
| | + echo '<h2>' . htmlspecialchars( $this->currentRepo['name'] ) . |
| | + ' <span class="branch-badge">' . |
| | + htmlspecialchars( $main['name'] ) . '</span></h2>'; |
| | + |
| | + usort( $entries, function( $a, $b ) { |
| | + return $a->compare( $b ); |
| | + } ); |
| | |
| | echo '<div class="file-list">'; |
| | - $renderer = new HtmlFileRenderer($this->currentRepo['safe_name']); |
| | + $renderer = new HtmlFileRenderer( $this->currentRepo['safe_name'], $path ); |
| | |
| | - foreach ($entries as $file) { |
| | - $file->render($renderer); |
| | + foreach( $entries as $file ) { |
| | + $file->render( $renderer ); |
| | } |
| | |
| | echo '</div>'; |
| | } |
| | |
| | - private function renderBlob($targetHash) { |
| | - $repoParam = '&repo=' . urlencode($this->currentRepo['safe_name']); |
| | - $size = $this->git->getObjectSize($targetHash); |
| | + private function renderBlob( $targetHash ) { |
| | + $repoParam = '&repo=' . urlencode( $this->currentRepo['safe_name'] ); |
| | + $size = $this->git->getObjectSize( $targetHash ); |
| | + $buffer = ''; |
| | |
| | - $buffer = ''; |
| | - $this->git->stream($targetHash, function($d) use (&$buffer) { |
| | - if (strlen($buffer) < 12) $buffer .= $d; |
| | - }); |
| | + $this->git->stream( $targetHash, function( $d ) use ( &$buffer ) { |
| | + if( strlen( $buffer ) < 12 ) $buffer .= $d; |
| | + } ); |
| | |
| | - $filename = $_GET['name'] ?? ''; |
| | - $category = MediaTypeSniffer::isCategory($buffer, $filename); |
| | - $mediaType = MediaTypeSniffer::isMediaType($buffer, $filename); |
| | + $filename = $_GET['name'] ?? ''; |
| | + $category = MediaTypeSniffer::isCategory( $buffer, $filename ); |
| | + $mediaType = MediaTypeSniffer::isMediaType( $buffer, $filename ); |
| | |
| | - $this->renderBreadcrumbs($targetHash, 'File'); |
| | + $this->renderBreadcrumbs( $targetHash, 'File' ); |
| | |
| | - if ($size === 0) { |
| | - $this->renderDownloadState($targetHash, "This file is empty."); |
| | + if( $size === 0 ) { |
| | + $this->renderDownloadState( $targetHash, "This file is empty." ); |
| | + |
| | return; |
| | } |
| | |
| | $rawUrl = '?action=raw&hash=' . $targetHash . $repoParam . |
| | - '&name=' . urlencode($filename); |
| | + '&name=' . urlencode( $filename ); |
| | |
| | - if ($category === MediaTypeSniffer::CAT_IMAGE) { |
| | + if( $category === MediaTypeSniffer::CAT_IMAGE ) { |
| | echo '<div class="blob-content" style="text-align:center; ' . |
| | - 'padding: 20px; background: #f6f8fa;">'; |
| | - echo '<img src="' . $rawUrl . '" style="max-width: 100%; ' . |
| | - 'border: 1px solid #dfe2e5;">'; |
| | + 'padding: 20px; background: #f6f8fa;">'; |
| | + echo '<img src="' . $rawUrl . '" style="max-width: 100%; ' . |
| | + 'border: 1px solid #dfe2e5;">'; |
| | echo '</div>'; |
| | - } elseif ($category === MediaTypeSniffer::CAT_VIDEO) { |
| | + } elseif( $category === MediaTypeSniffer::CAT_VIDEO ) { |
| | echo '<div class="blob-content" style="text-align:center; ' . |
| | - 'padding: 20px; background: #000;">'; |
| | - echo '<video controls style="max-width: 100%; max-height: 80vh;">'; |
| | - echo '<source src="' . $rawUrl . '" type="' . $mediaType . '">'; |
| | - echo '</video>'; |
| | + 'padding: 20px; background: #000;">'; |
| | + echo '<video controls style="max-width: 100%; max-height: 80vh;">'; |
| | + echo '<source src="' . $rawUrl . '" type="' . $mediaType . '">'; |
| | + echo '</video>'; |
| | echo '</div>'; |
| | - } elseif ($category === MediaTypeSniffer::CAT_AUDIO) { |
| | + } elseif( $category === MediaTypeSniffer::CAT_AUDIO ) { |
| | echo '<div class="blob-content" style="text-align:center; ' . |
| | - 'padding: 40px; background: #f6f8fa;">'; |
| | - echo '<audio controls style="width: 100%; max-width: 600px;">'; |
| | - echo '<source src="' . $rawUrl . '" type="' . $mediaType . '">'; |
| | - echo '</audio>'; |
| | + 'padding: 40px; background: #f6f8fa;">'; |
| | + echo '<audio controls style="width: 100%; max-width: 600px;">'; |
| | + echo '<source src="' . $rawUrl . '" type="' . $mediaType . '">'; |
| | + echo '</audio>'; |
| | echo '</div>'; |
| | - } elseif ($category === MediaTypeSniffer::CAT_TEXT) { |
| | - if ($size > 524288) { |
| | - $this->renderDownloadState($targetHash, "File is too large " . |
| | - "to display (" . $this->formatSize($size) . ")."); |
| | + } elseif( $category === MediaTypeSniffer::CAT_TEXT ) { |
| | + if( $size > 524288 ) { |
| | + $this->renderDownloadState( $targetHash, "File is too large " . |
| | + "to display (" . $this->formatSize( $size ) . ")." ); |
| | } else { |
| | $content = ''; |
| | - $this->git->stream($targetHash, function($d) use (&$content) { |
| | + $this->git->stream( $targetHash, function( $d ) use ( &$content ) { |
| | $content .= $d; |
| | - }); |
| | + } ); |
| | echo '<div class="blob-content"><pre class="blob-code">' . |
| | - htmlspecialchars($content) . '</pre></div>'; |
| | + htmlspecialchars( $content ) . '</pre></div>'; |
| | } |
| | } else { |
| | - $this->renderDownloadState($targetHash, "This is a binary file."); |
| | + $this->renderDownloadState( $targetHash, "This is a binary file." ); |
| | } |
| | } |
| | |
| | - private function renderDownloadState($hash, $reason) { |
| | + private function renderDownloadState( $hash, $reason ) { |
| | $url = '?action=raw&hash=' . $hash . '&repo=' . |
| | - urlencode($this->currentRepo['safe_name']); |
| | + urlencode( $this->currentRepo['safe_name'] ); |
| | + |
| | echo '<div class="empty-state" style="text-align: center; ' . |
| | - 'padding: 40px; border: 1px solid #e1e4e8; border-radius: 6px; ' . |
| | - 'margin-top: 10px;">'; |
| | - echo '<p style="margin-bottom: 20px; color: #586069;">' . |
| | - htmlspecialchars($reason) . '</p>'; |
| | - echo '<a href="' . $url . '" style="display: inline-block; ' . |
| | - 'padding: 6px 16px; background: #0366d6; color: white; ' . |
| | - 'text-decoration: none; border-radius: 6px; ' . |
| | - 'font-weight: 600;">Download Raw File</a>'; |
| | + 'padding: 40px; border: 1px solid #e1e4e8; border-radius: 6px; ' . |
| | + 'margin-top: 10px;">'; |
| | + echo '<p style="margin-bottom: 20px; color: #586069;">' . |
| | + htmlspecialchars( $reason ) . '</p>'; |
| | + echo '<a href="' . $url . '" style="display: inline-block; ' . |
| | + 'padding: 6px 16px; background: #0366d6; color: white; ' . |
| | + 'text-decoration: none; border-radius: 6px; ' . |
| | + 'font-weight: 600;">Download Raw File</a>'; |
| | echo '</div>'; |
| | } |
| | |
| | - private function formatSize($size) { |
| | - if ($size <= 0) return '0 B'; |
| | + private function formatSize( $size ) { |
| | + if( $size <= 0 ) return '0 B'; |
| | + |
| | $units = ['B', 'KB', 'MB', 'GB']; |
| | - $i = (int)floor(log($size, 1024)); |
| | - return round($size / pow(1024, $i), 1) . ' ' . $units[$i]; |
| | + $i = (int)floor( log( $size, 1024 ) ); |
| | + |
| | + return round( $size / pow( 1024, $i ), 1 ) . ' ' . $units[$i]; |
| | } |
| | |
| | - private function renderBreadcrumbs($hash, $type) { |
| | + private function renderBreadcrumbs( $hash, $type ) { |
| | echo '<div class="breadcrumb">'; |
| | - echo '<a href="?">Repositories</a><span>/</span>'; |
| | + echo '<a href="?">Repositories</a><span>/</span>'; |
| | |
| | - $repoUrl = '?repo=' . urlencode($this->currentRepo['safe_name']); |
| | - echo '<a href="' . $repoUrl . '">' . htmlspecialchars($this->currentRepo['name']) . '</a>'; |
| | + $repoUrl = '?repo=' . urlencode( $this->currentRepo['safe_name'] ); |
| | + echo '<a href="' . $repoUrl . '">' . |
| | + htmlspecialchars( $this->currentRepo['name'] ) . '</a>'; |
| | |
| | $path = $_GET['name'] ?? ''; |
| | - if ($path) { |
| | - $parts = explode('/', trim($path, '/')); |
| | - $accumulatedPath = ''; |
| | |
| | - foreach ($parts as $index => $part) { |
| | + if( $path ) { |
| | + $parts = explode( '/', trim( $path, '/' ) ); |
| | + $acc = ''; |
| | + |
| | + foreach( $parts as $idx => $part ) { |
| | echo '<span>/</span>'; |
| | - $accumulatedPath .= ($index === 0 ? '' : '/') . $part; |
| | + $acc .= ( $idx === 0 ? '' : '/' ) . $part; |
| | |
| | - // If it's the last part (the file itself), just show text; otherwise, link to the path |
| | - if ($index === count($parts) - 1) { |
| | - echo '<span>' . htmlspecialchars($part) . '</span>'; |
| | + if( $idx === count( $parts ) - 1 ) { |
| | + echo '<span>' . htmlspecialchars( $part ) . '</span>'; |
| | } else { |
| | - // Note: This assumes your Git->walk() or Router can handle path-based hashes. |
| | - // For now, we link to the name parameter which is used in your existing logic. |
| | - echo '<a href="' . $repoUrl . '&name=' . urlencode($accumulatedPath) . '">' . |
| | - htmlspecialchars($part) . '</a>'; |
| | + echo '<a href="' . $repoUrl . '&name=' . urlencode( $acc ) . '">' . |
| | + htmlspecialchars( $part ) . '</a>'; |
| | } |
| | } |
| | + } elseif( $this->hash ) { |
| | + echo '<span>/</span><span>' . $type . ' ' . |
| | + substr( $hash, 0, 7 ) . '</span>'; |
| | } |
| | |
| | - if ($this->hash && !$path) { |
| | - echo '<span>/</span><span>' . $type . ' ' . substr($hash, 0, 7) . '</span>'; |
| | - } |
| | echo '</div>'; |
| | } |