diff --git a/README.md b/README.md index 1631040..183717c 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,10 @@ $ git clone ... $ phpstan-baseline-analyze *phpstan-baseline.neon --json > now.json +# To use baseline file modification time as the analysis date instead of "now" +# Best used together with `git restore-mtime *phpstan-baseline.neon` +$ phpstan-baseline-analyze *phpstan-baseline.neon --json --mtime > now.json + $ git checkout `git rev-list -n 1 --before="1 week ago" HEAD` $ phpstan-baseline-analyze '*phpstan-baseline.neon' --json > 1-week-ago.json @@ -92,6 +96,8 @@ $ phpstan-baseline-analyze '*phpstan-baseline.neon' --json > 2-weeks-ago.json $ php phpstan-baseline-graph '*.json' > result.html ``` +See [git-tools](https://github.com/MestreLion/git-tools) for details on `git restore-mtime` + ![PHPStan baseline analysis graph](https://github.com/staabm/phpstan-baseline-analysis/assets/120441/ea5abe25-21e8-43f2-9118-0967a75517c6) diff --git a/bin/phpstan-baseline-analyze.php b/bin/phpstan-baseline-analyze.php index f5c56a8..0fc8517 100644 --- a/bin/phpstan-baseline-analyze.php +++ b/bin/phpstan-baseline-analyze.php @@ -35,9 +35,14 @@ $format = ResultPrinter::FORMAT_TEXT; +$useFileMtime = false; if (in_array('--json', $argv)) { $format = ResultPrinter::FORMAT_JSON; } -$exitCode = $app->start($argv[1], $format); +if (in_array('--mtime', $argv)) { + $useFileMtime = true; +} + +$exitCode = $app->start($argv[1], $format, $useFileMtime); exit($exitCode); diff --git a/lib/AnalyzeApplication.php b/lib/AnalyzeApplication.php index deb39f9..b803c21 100644 --- a/lib/AnalyzeApplication.php +++ b/lib/AnalyzeApplication.php @@ -24,7 +24,7 @@ final class AnalyzeApplication * * @api */ - public function start(string $glob, string $format): int + public function start(string $glob, string $format, bool $useFileMtime = false): int { $printer = new ResultPrinter(); $baselines = BaselineFinder::forGlob($glob); @@ -36,6 +36,7 @@ public function start(string $glob, string $format): int $isLast = $i == $numBaselines - 1; $analyzer = new BaselineAnalyzer($baseline); + $analyzer->useFileMtime($useFileMtime); $result = $analyzer->analyze(); if ($format == ResultPrinter::FORMAT_JSON) { diff --git a/lib/BaselineAnalyzer.php b/lib/BaselineAnalyzer.php index 31a5bd7..4e9cce4 100644 --- a/lib/BaselineAnalyzer.php +++ b/lib/BaselineAnalyzer.php @@ -3,7 +3,7 @@ namespace staabm\PHPStanBaselineAnalysis; use Safe\DateTimeImmutable; -use function Safe\preg_match; +use function Safe\filemtime; final class BaselineAnalyzer { @@ -32,16 +32,26 @@ final class BaselineAnalyzer * @var Baseline */ private $baseline; + private bool $fileMtime; public function __construct(Baseline $baseline) { $this->baseline = $baseline; } + public function useFileMtime(bool $useFileMtime) + { + $this->fileMtime = $useFileMtime; + } + public function analyze(): AnalyzerResult { $result = new AnalyzerResult(); - $result->referenceDate = new DateTimeImmutable(); + if ($this->fileMtime) { + $result->referenceDate = DateTimeImmutable::createFromFormat("U", (string)filemtime($this->baseline->getFilePath())); + } else { + $result->referenceDate = new DateTimeImmutable(); + } /** * @var BaselineError $baselineError diff --git a/lib/GraphTemplate.php b/lib/GraphTemplate.php index e86bc76..7e8d6b7 100644 --- a/lib/GraphTemplate.php +++ b/lib/GraphTemplate.php @@ -103,6 +103,7 @@ public function render(Iterator $it):string { } foreach ($dataByDates as $baselinePath => $dataByDate) { + ksort($dataByDate); foreach ($dataByDate as $date => $data) { $dates[$baselinePath][] = 'new Date(' . $date . ' * 1000).toLocaleDateString("de-DE")'; $splines[$baselinePath][0]['data'][] = $data[0]; diff --git a/tests/AnalyzeApplicationTest.php b/tests/AnalyzeApplicationTest.php index 10e4700..44b8989 100644 --- a/tests/AnalyzeApplicationTest.php +++ b/tests/AnalyzeApplicationTest.php @@ -2,13 +2,17 @@ namespace staabm\PHPStanBaselineAnalysis\Tests; +use Safe\DateTimeImmutable; use staabm\PHPStanBaselineAnalysis\AnalyzeApplication; use staabm\PHPStanBaselineAnalysis\ResultPrinter; + +use function Safe\filemtime; use function Safe\json_encode; +use function Safe\ob_start; class AnalyzeApplicationTest extends BaseTestCase { - function testTextPrinting():void + function testTextPrintingWithCurrentTime():void { $app = new AnalyzeApplication(); @@ -33,6 +37,37 @@ function testTextPrinting():void Native-Return-Type-Coverage: 4 Unused-Symbols: 3 +PHP; + + $this->assertSame($expected, $rendered); + $this->assertSame(0, $exitCode); + } + + function testTextPrintingWithFileModificationTime():void + { + $app = new AnalyzeApplication(); + + ob_start(); + $exitCode = $app->start(__DIR__ . '/fixtures/all-in.neon', ResultPrinter::FORMAT_TEXT, true); + $rendered = ob_get_clean(); + + $rendered = str_replace(__DIR__, '', $rendered); + + $expectedDate = DateTimeImmutable::createFromFormat("U", (string) filemtime(__DIR__ . '/fixtures/all-in.neon'))->format(ResultPrinter::DATE_FORMAT); + $expected = <<assertSame($expected, $rendered);