| | |
| | class CommitsPage extends BasePage { |
| | + private const PER_PAGE = 100; |
| | + |
| | private $currentRepo; |
| | private $git; |
 |
| | echo '<div class="commit-list">'; |
| | |
| | - $start = $this->hash ?: $main['hash']; |
| | + $start = $this->hash ?: $main['hash']; |
| | + $count = 0; |
| | + $nextHash = ''; |
| | + $prevHash = ''; |
| | |
| | - $this->git->history( $start, 100, function( $commit ) { |
| | - $msg = htmlspecialchars( explode( "\n", $commit->message )[0] ); |
| | + if( $start !== $main['hash'] ) { |
| | + $prevHash = $this->getPreviousHash( $main['hash'], $start ); |
| | + } |
| | |
| | - $url = (new UrlBuilder()) |
| | - ->withRepo( $this->currentRepo['safe_name'] ) |
| | - ->withAction( 'commit' ) |
| | - ->withHash( $commit->sha ) |
| | - ->build(); |
| | + $this->git->history( |
| | + $start, |
| | + self::PER_PAGE, |
| | + function( $commit ) use ( &$count, &$nextHash ) { |
| | + $msg = htmlspecialchars( explode( "\n", $commit->message )[0] ); |
| | |
| | - 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>'; |
| | - } ); |
| | + $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>'; |
| | + |
| | + $count++; |
| | + $nextHash = $commit->parentSha; |
| | + } |
| | + ); |
| | |
| | echo '</div>'; |
| | + |
| | + $this->renderPagination( $prevHash, $nextHash, $count ); |
| | } |
| | }, $this->currentRepo ); |
| | + } |
| | + |
| | + private function renderPagination( |
| | + string $prevHash, |
| | + string $nextHash, |
| | + int $count |
| | + ) { |
| | + $hasPrev = $prevHash !== ''; |
| | + $hasNext = $count === self::PER_PAGE && $nextHash !== ''; |
| | + |
| | + 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>'; |
| | + |
| | + if( $hasNext ) { |
| | + echo ' • '; |
| | + } |
| | + } |
| | + |
| | + if( $hasNext ) { |
| | + $url = (new UrlBuilder()) |
| | + ->withRepo( $this->currentRepo['safe_name'] ) |
| | + ->withAction( 'commits' ) |
| | + ->withHash( $nextHash ) |
| | + ->build(); |
| | + |
| | + echo '<a href="' . $url . '">Next →</a>'; |
| | + } |
| | + |
| | + echo '</div>'; |
| | + } |
| | + } |
| | + |
| | + private function getPreviousHash( string $head, string $target ): string { |
| | + $prevHash = ''; |
| | + $window = []; |
| | + |
| | + if( $target !== '' && $target !== $head ) { |
| | + $this->git->history( |
| | + $head, |
| | + PHP_INT_MAX, |
| | + function( $commit ) use ( $target, &$window, &$prevHash ) { |
| | + $result = true; |
| | + |
| | + if( $commit->sha === $target ) { |
| | + if( !empty( $window ) ) { |
| | + $prevHash = $window[0]; |
| | + } |
| | + |
| | + $result = false; |
| | + } |
| | + |
| | + if( $result ) { |
| | + $window[] = $commit->sha; |
| | + |
| | + if( count( $window ) > self::PER_PAGE ) { |
| | + array_shift( $window ); |
| | + } |
| | + } |
| | + |
| | + return $result; |
| | + } |
| | + ); |
| | + } |
| | + |
| | + return $prevHash; |
| | } |
| | } |