| | echo '<div class="commit-list">'; |
| | |
| | - $start = $this->hash ?: $main['hash']; |
| | - $count = 0; |
| | - $nextHash = ''; |
| | - $prevHash = ''; |
| | - |
| | - if( $start !== $main['hash'] ) { |
| | - $prevHash = $this->getPreviousHash( $main['hash'], $start ); |
| | - } |
| | + $start = $this->hash !== '' ? $this->hash : $main['hash']; |
| | + $count = 0; |
| | |
| | $this->git->history( |
| | $start, |
| | self::PER_PAGE, |
| | - function( $commit ) use ( &$count, &$nextHash ) { |
| | - $msg = htmlspecialchars( explode( "\n", $commit->message )[0] ); |
| | - |
| | - $url = (new UrlBuilder()) |
| | - ->withRepo( $this->currentRepo['safe_name'] ) |
| | - ->withAction( 'commit' ) |
| | - ->withHash( $commit->sha ) |
| | - ->build(); |
| | - |
| | - echo '<div class="commit-row">'; |
| | - echo '<a href="' . $url . '" class="sha">' . |
| | - substr( $commit->sha, 0, 7 ) . '</a>'; |
| | - echo '<span class="message">' . $msg . '</span>'; |
| | - echo '<span class="meta">' . |
| | - htmlspecialchars( $commit->author ) . |
| | - ' • ' . date( 'Y-m-d', $commit->date ) . '</span>'; |
| | - echo '</div>'; |
| | - |
| | + function( $commit ) use ( &$count ) { |
| | + $this->renderCommitRow( $commit ); |
| | $count++; |
| | - $nextHash = $commit->parentSha; |
| | } |
| | ); |
| | |
| | echo '</div>'; |
| | |
| | - $this->renderPagination( $prevHash, $nextHash, $count ); |
| | + $this->renderPagination( $main['hash'], $count ); |
| | } |
| | }, $this->currentRepo ); |
| | } |
| | |
| | - private function renderPagination( |
| | - string $prevHash, |
| | - string $nextHash, |
| | - int $count |
| | - ) { |
| | - $hasPrev = $prevHash !== ''; |
| | - $hasNext = $count === self::PER_PAGE && $nextHash !== ''; |
| | + private function renderCommitRow( object $commit ) { |
| | + $msg = htmlspecialchars( explode( "\n", $commit->message )[0] ); |
| | + $url = $this->buildCommitUrl( $commit->sha ); |
| | + |
| | + echo '<div class="commit-row">'; |
| | + echo '<a href="' . $url . '" class="sha">' . |
| | + substr( $commit->sha, 0, 7 ) . '</a>'; |
| | + echo '<span class="message">' . $msg . '</span>'; |
| | + echo '<span class="meta">' . htmlspecialchars( $commit->author ) . |
| | + ' • ' . date( 'Y-m-d', $commit->date ) . '</span>'; |
| | + echo '</div>'; |
| | + } |
| | + |
| | + private function renderPagination( string $mainHash, int $count ) { |
| | + $nav = $this->buildPaginationData( $mainHash, $count ); |
| | + $pages = $nav['pages']; |
| | + $current = $nav['current']; |
| | + $hasNext = $nav['hasNext']; |
| | + $hasPrev = $current > 1; |
| | |
| | if( $hasPrev || $hasNext ) { |
| | echo '<div class="pagination">'; |
| | |
| | if( $hasPrev ) { |
| | - $url = (new UrlBuilder()) |
| | - ->withRepo( $this->currentRepo['safe_name'] ) |
| | - ->withAction( 'commits' ) |
| | - ->withHash( $prevHash ) |
| | - ->build(); |
| | - |
| | - echo '<a href="' . $url . '">← Back</a>'; |
| | + $prevSha = $pages[$current - 2]; |
| | + $prevUrl = $this->buildPageUrl( $prevSha ); |
| | |
| | - if( $hasNext ) { |
| | - echo ' • '; |
| | - } |
| | + echo '<a href="' . $prevUrl . '" class="page-link">← Back</a>'; |
| | } |
| | + |
| | + $this->renderPageNumbers( $pages, $current ); |
| | |
| | if( $hasNext ) { |
| | - $url = (new UrlBuilder()) |
| | - ->withRepo( $this->currentRepo['safe_name'] ) |
| | - ->withAction( 'commits' ) |
| | - ->withHash( $nextHash ) |
| | - ->build(); |
| | + $nextSha = $pages[$current]; |
| | + $nextUrl = $this->buildPageUrl( $nextSha ); |
| | |
| | - echo '<a href="' . $url . '">Next →</a>'; |
| | + echo '<a href="' . $nextUrl . '" class="page-link">Next →</a>'; |
| | } |
| | |
| | echo '</div>'; |
| | } |
| | } |
| | |
| | - private function getPreviousHash( string $head, string $target ): string { |
| | - $prevHash = ''; |
| | - $window = []; |
| | + private function renderPageNumbers( array $pages, int $current ) { |
| | + $total = count( $pages ); |
| | + $actual = 1; |
| | + $start = 1; |
| | + $end = $total; |
| | |
| | - if( $target !== '' && $target !== $head ) { |
| | - $this->git->history( |
| | - $head, |
| | - PHP_INT_MAX, |
| | - function( $commit ) use ( $target, &$window, &$prevHash ) { |
| | - $result = true; |
| | + if( $total > 10 ) { |
| | + if( $current >= 5 ) { |
| | + $start = $current; |
| | + $end = $current + 10; |
| | + } else { |
| | + $start = 1; |
| | + $end = 10; |
| | + } |
| | + } |
| | |
| | - if( $commit->sha === $target ) { |
| | - if( !empty( $window ) ) { |
| | - $prevHash = $window[0]; |
| | - } |
| | + if( $end > $total ) { |
| | + $end = $total; |
| | + } |
| | |
| | - $result = false; |
| | - } |
| | + while( $actual <= $total ) { |
| | + if( $actual >= $start && $actual <= $end ) { |
| | + if( $actual === $current ) { |
| | + echo '<span class="page-badge">(' . $actual . ')</span>'; |
| | + } else { |
| | + $sha = $pages[$actual - 1]; |
| | + $url = $this->buildPageUrl( $sha ); |
| | |
| | - if( $result ) { |
| | - $window[] = $commit->sha; |
| | + echo '<a href="' . $url . '" class="page-link">' . $actual . '</a>'; |
| | + } |
| | + } |
| | |
| | - if( count( $window ) > self::PER_PAGE ) { |
| | - array_shift( $window ); |
| | - } |
| | - } |
| | + $actual++; |
| | + } |
| | + } |
| | |
| | - return $result; |
| | + private function buildPaginationData( string $mainHash, int $count ): array { |
| | + $target = $this->hash !== '' ? $this->hash : $mainHash; |
| | + $pageHashes = []; |
| | + $commits = 0; |
| | + $currentPage = 1; |
| | + $found = false; |
| | + $result = []; |
| | + |
| | + $this->git->history( |
| | + $mainHash, |
| | + PHP_INT_MAX, |
| | + function( $commit ) use ( |
| | + $target, |
| | + &$pageHashes, |
| | + &$commits, |
| | + &$currentPage, |
| | + &$found |
| | + ) { |
| | + $continue = true; |
| | + |
| | + if( $commits % self::PER_PAGE === 0 ) { |
| | + $pageHashes[] = $commit->sha; |
| | } |
| | - ); |
| | - } |
| | |
| | - return $prevHash; |
| | + if( $commit->sha === $target ) { |
| | + $currentPage = count( $pageHashes ); |
| | + $found = true; |
| | + } |
| | + |
| | + if( $found && count( $pageHashes ) > $currentPage + 10 ) { |
| | + $continue = false; |
| | + } |
| | + |
| | + if( $continue ) { |
| | + $commits++; |
| | + } |
| | + |
| | + return $continue; |
| | + } |
| | + ); |
| | + |
| | + $result['pages'] = $pageHashes; |
| | + $result['current'] = $currentPage; |
| | + $result['hasNext'] = $count === self::PER_PAGE && |
| | + isset( $pageHashes[$currentPage] ); |
| | + |
| | + return $result; |
| | + } |
| | + |
| | + private function buildCommitUrl( string $targetHash ): string { |
| | + $builder = new UrlBuilder(); |
| | + $result = ''; |
| | + |
| | + $builder->withRepo( $this->currentRepo['safe_name'] ); |
| | + $builder->withAction( 'commit' ); |
| | + $builder->withHash( $targetHash ); |
| | + |
| | + $result = $builder->build(); |
| | + |
| | + return $result; |
| | + } |
| | + |
| | + private function buildPageUrl( string $targetHash ): string { |
| | + $builder = new UrlBuilder(); |
| | + $result = ''; |
| | + |
| | + $builder->withRepo( $this->currentRepo['safe_name'] ); |
| | + $builder->withAction( 'commits' ); |
| | + $builder->withHash( $targetHash ); |
| | + |
| | + $result = $builder->build(); |
| | + |
| | + return $result; |
| | } |
| | } |