Dave Jarvis' Repositories

git clone https://repo.autonoma.ca/repo/treetrek.git

Uses closures to render pages

Author Dave Jarvis <email>
Date 2026-03-02 12:51:10 GMT-0800
Commit 864da81e1391b1e52e8d6054dabf4292bd98d59f
Parent 2f3caa1
pages/DiffPage.php
require_once __DIR__ . '/../model/UrlBuilder.php';
+class DiffStats {
+ private $added = 0;
+ private $deleted = 0;
+ private $empty = true;
+
+ public function track( array $change ): array {
+ $this->empty = false;
+
+ foreach( $change['hunks'] as $hunkLine ) {
+ if( $hunkLine['t'] === '+' ) {
+ $this->added++;
+ } elseif( $hunkLine['t'] === '-' ) {
+ $this->deleted++;
+ }
+ }
+
+ return $change;
+ }
+
+ public function isEmpty(): bool {
+ return $this->empty;
+ }
+
+ public function __toString(): string {
+ $diffNet = $this->added - $this->deleted;
+ $addPl = $this->added !== 1 ? 's' : '';
+ $delPl = $this->deleted !== 1 ? 's' : '';
+ $msg = $this->added . ' line' . $addPl . ' added, ' .
+ $this->deleted . ' line' . $delPl . ' removed';
+
+ if( $diffNet !== 0 ) {
+ $dir = $diffNet > 0 ? 'increase' : 'decrease';
+ $msg .= ', ' . \abs( $diffNet ) . "-line $dir";
+ }
+
+ return $msg;
+ }
+}
+
class DiffPage extends BasePage {
private $currentRepo;
}
- $commitsUrl = (new UrlBuilder())->withRepo( $this->currentRepo['safe_name'] )->withAction( 'commits' )->build();
+ $commitsUrl = (new UrlBuilder())
+ ->withRepo( $this->currentRepo['safe_name'] )
+ ->withAction( 'commits' )
+ ->build();
$trail = [
[
$tpl->assign( 'parent_url', $parentUrl );
$tpl->assign( 'parent_sha', $parentSha );
-
- $added = 0;
- $deleted = 0;
- $hasChanges = false;
- foreach( $diffEngine->compare( $this->hash ) as $change ) {
- $hasChanges = true;
+ $stats = new DiffStats();
- foreach( $change['hunks'] as $hunkLine ) {
- if( $hunkLine['t'] === '+' ) {
- $added++;
- } elseif( $hunkLine['t'] === '-' ) {
- $deleted++;
- }
- }
- }
+ $tpl->assign( 'stats', $stats );
+ $tpl->assign( 'changes', $this->generateChanges( $diffEngine, $stats ) );
- $diffNet = $added - $deleted;
- $deltaMsg = $added . ' line' . ($added !== 1 ? 's' : '') . ' added, ' .
- $deleted . ' line' . ($deleted !== 1 ? 's' : '') . ' removed';
+ $tpl->render( 'diff.tpl' );
+ }
- if( $diffNet !== 0 ) {
- $direction = $diffNet > 0 ? 'increase' : 'decrease';
- $deltaMsg .= ', ' . \abs( $diffNet ) . "-line $direction";
+ private function generateChanges(
+ GitDiff $diffEngine,
+ DiffStats $stats
+ ): Generator {
+ foreach( $diffEngine->compare( $this->hash ) as $change ) {
+ yield $stats->track( $change );
}
-
- $tpl->assign( 'delta_msg', $deltaMsg );
- $tpl->assign( 'empty_changes', !$hasChanges );
-
- $tpl->assign( 'changes', $diffEngine->compare( $this->hash ) );
-
- echo $tpl->render( 'diff.tpl' );
}
}
pages/Template.php
}
- public function render( string $file ): string {
- $res = $this->evaluate( $file );
+ public function render( string $file ): void {
+ $this->evaluate( $file, true );
if( $this->layout !== '' ) {
$layout = $this->layout;
$this->layout = '';
- $this->assign( 'content', $this->blocks['content'] ?? '' );
- $res = $this->evaluate( $layout );
+ $this->evaluate( $layout, false );
}
-
- return $res;
}
- private function evaluate( string $file ): string {
+ private function evaluate( string $file, bool $discard ): void {
$php = $this->compile( \file_get_contents( __DIR__ . '/' . $file ) );
$tmp = \tempnam( \sys_get_temp_dir(), 'tpl_' );
\file_put_contents( $tmp, $php );
- \ob_start();
+ if( $discard ) {
+ \ob_start();
+ }
+
\extract( $this->vars );
require $tmp;
- $res = \ob_get_clean();
- \unlink( $tmp );
+ if( $discard ) {
+ \ob_end_clean();
+ }
- return $res;
+ \unlink( $tmp );
}
$replace = [
'<?php $this->layout = "$1"; ?>',
- '<?php \ob_start(); ?>',
- '<?php $this->blocks["$1"] = \ob_get_clean(); ?>',
- '<?php echo $this->blocks["$1"] ?? ""; ?>',
+ '<?php $this->blocks["$1"] = function() { \extract( $this->vars ); ?>',
+ '<?php }; ?>',
+ '<?php if( isset( $this->blocks["$1"] ) ) { $this->blocks["$1"](); } ?>',
'<?php if( $1 ) { ?>',
'<?php } elseif( $1 ) { ?>',
'<?php foreach( $1 ) { ?>',
'<?php echo \$$1 ?? ""; ?>',
- '<?php echo \htmlspecialchars( (string)( \$$1 ?? "" ) ); ?>',
+ '<?php echo \htmlspecialchars( (string)(\$$1 ?? "") ); ?>',
'<?php } else { ?>',
'<?php } ?>',
pages/diff.tpl
</div>
+ <div class="diff-container" style="order:3">
+ {foreach $changes as $change}
+ <div class="diff-file">
+ <div class="diff-header">
+ <span class="diff-status {if $change.type === 'A'}status-add{elseif $change.type === 'D'}status-del{elseif $change.type === 'M'}status-mod{/if}">
+ <i class="fa {if $change.type === 'A'}fa-plus-circle{elseif $change.type === 'D'}fa-minus-circle{elseif $change.type === 'M'}fa-pencil-alt{else}fa-file{/if}"></i>
+ </span>
+ <span class="diff-path">{$change.path}</span>
+ </div>
+
+ {if $change.is_binary}
+ <div class="diff-binary">Binary files differ</div>
+ {else}
+ <div class="diff-content">
+ <table>
+ <tbody>
+ {foreach $change.hunks as $line}
+ {if $line.t === 'gap'}
+ <tr class="diff-gap">
+ <td colspan="3"><img src="/images/diff-gap.svg" class="diff-gap-icon" /></td>
+ </tr>
+ {else}
+ {strip}
+ <tr class="{if $line.t === '+'}diff-add{elseif $line.t === '-'}diff-del{else}diff-ctx{/if}">
+ <td class="diff-num" data-num="{$line.no}"></td>
+ <td class="diff-num" data-num="{$line.nn}"></td>
+ <td class="diff-code">
+ <span class="diff-marker">{if $line.t === '+'}+{elseif $line.t === '-'}-{else} {/if}</span>{$line.l}
+ </td>
+ </tr>
+ {/strip}
+ {/if}
+ {/foreach}
+ </tbody>
+ </table>
+ </div>
+ {/if}
+ </div>
+ {/foreach}
+
+ {if $stats->isEmpty()}
+ <div class="empty-state">
+ <p>No changes detected.</p>
+ </div>
+ {/if}
+ </div>
+
<div class="diff-delta" style="order:2">
<table class="commit-info-table">
<tbody>
<tr>
<th class="commit-info-label">Delta</th>
- <td class="commit-info-value">{$delta_msg}</td>
+ <td class="commit-info-value">{$stats}</td>
</tr>
</tbody>
</table>
- </div>
-
- <div class="diff-container" style="order:3">
- {if $empty_changes}
- <div class="empty-state">
- <p>No changes detected.</p>
- </div>
- {else}
- {foreach $changes as $change}
- <div class="diff-file">
- <div class="diff-header">
- <span class="diff-status {if $change.type === 'A'}status-add{elseif $change.type === 'D'}status-del{elseif $change.type === 'M'}status-mod{/if}">
- <i class="fa {if $change.type === 'A'}fa-plus-circle{elseif $change.type === 'D'}fa-minus-circle{elseif $change.type === 'M'}fa-pencil-alt{else}fa-file{/if}"></i>
- </span>
- <span class="diff-path">{$change.path}</span>
- </div>
-
- {if $change.is_binary}
- <div class="diff-binary">Binary files differ</div>
- {else}
- <div class="diff-content">
- <table>
- <tbody>
- {foreach $change.hunks as $line}
- {if $line.t === 'gap'}
- <tr class="diff-gap">
- <td colspan="3"><img src="/images/diff-gap.svg" class="diff-gap-icon" /></td>
- </tr>
- {else}
- {strip}
- <tr class="{if $line.t === '+'}diff-add{elseif $line.t === '-'}diff-del{else}diff-ctx{/if}">
- <td class="diff-num" data-num="{$line.no}"></td>
- <td class="diff-num" data-num="{$line.nn}"></td>
- <td class="diff-code">
- <span class="diff-marker">{if $line.t === '+'}+{elseif $line.t === '-'}-{else} {/if}</span>{$line.l}
- </td>
- </tr>
- {/strip}
- {/if}
- {/foreach}
- </tbody>
- </table>
- </div>
- {/if}
- </div>
- {/foreach}
- {/if}
</div>
</div>
Delta 118 lines added, 91 lines removed, 27-line increase