From cc5190a40594a09189abd174768aa187683fda41 Mon Sep 17 00:00:00 2001 From: Freek Van der Herten Date: Thu, 22 Feb 2024 13:43:37 +0100 Subject: [PATCH] wip --- src/DiffClass.php | 7 ---- src/DiffResult.php | 41 ++++++++++++++++++ src/DiffResultLine.php | 16 +++++++ src/Differ.php | 62 ++++++++++++++++++++++++++++ src/Enums/DiffResultLineType.php | 10 +++++ src/Exceptions/CannotDiff.php | 18 ++++++++ src/Normalisers/ObjectNormaliser.php | 8 ++++ src/Renderers/Renderer.php | 10 +++++ src/Renderers/SimpleRenderer.php | 44 ++++++++++++++++++++ src/TypeDiffers/ArrayDiffer.php | 44 ++++++++++++++++++++ src/TypeDiffers/ObjectDiffer.php | 18 ++++++++ src/TypeDiffers/ScalarDiffer.php | 19 +++++++++ src/TypeDiffers/TypeDiffer.php | 12 ++++++ tests/ArrayDiffTest.php | 17 ++++++++ tests/ExampleTest.php | 5 --- 15 files changed, 319 insertions(+), 12 deletions(-) delete mode 100755 src/DiffClass.php create mode 100644 src/DiffResult.php create mode 100644 src/DiffResultLine.php create mode 100755 src/Differ.php create mode 100644 src/Enums/DiffResultLineType.php create mode 100644 src/Exceptions/CannotDiff.php create mode 100644 src/Normalisers/ObjectNormaliser.php create mode 100644 src/Renderers/Renderer.php create mode 100644 src/Renderers/SimpleRenderer.php create mode 100644 src/TypeDiffers/ArrayDiffer.php create mode 100644 src/TypeDiffers/ObjectDiffer.php create mode 100644 src/TypeDiffers/ScalarDiffer.php create mode 100644 src/TypeDiffers/TypeDiffer.php create mode 100644 tests/ArrayDiffTest.php delete mode 100644 tests/ExampleTest.php diff --git a/src/DiffClass.php b/src/DiffClass.php deleted file mode 100755 index c3fcda2..0000000 --- a/src/DiffClass.php +++ /dev/null @@ -1,7 +0,0 @@ - */ + protected array $lines = []; + + public function __construct( + protected mixed $first, + protected mixed $second) + { + + } + + public function add( + DiffResultLineType $type, + string $key, + mixed $value, + mixed $oldValue = null + ): self { + $this->lines[] = new DiffResultLine($type, $key, $value, $oldValue); + + return $this; + } + + /** @return array<\Spatie\Diff\DiffResultLine> */ + public function getLines(): array + { + return $this->lines; + } + + public function render(Renderer $renderer): string + { + return $renderer->render($this); + } +} diff --git a/src/DiffResultLine.php b/src/DiffResultLine.php new file mode 100644 index 0000000..f56b719 --- /dev/null +++ b/src/DiffResultLine.php @@ -0,0 +1,16 @@ + */ + protected array $differs = [ + ScalarDiffer::class, + ObjectDiffer::class, + Arraydiffer::class, + ]; + + public function diff(mixed $first, mixed $second): DiffResult + { + $this->ensureSameTypes($first, $second); + + $typeDiffer = $this->determineTypeDiffer($first, $second); + + if (! $typeDiffer) { + throw CannotDiff::noDifferFound($first, $second); + } + + return $typeDiffer->diff($first, $second); + } + + protected function determineTypeDiffer(mixed $first, mixed $second): ?TypeDiffer + { + foreach($this->differs as $differClass) { + $differClass = new $differClass; + + if ($differClass->candiff($first, $second)) { + return $differClass; + } + } + + return null; + } + + protected function ensureSameTypes(mixed $first, mixed $second): void + { + if (is_scalar($first) && is_scalar($second)) { + return; + } + + if (is_array($first) && is_array($second)) { + return; + } + + if (is_object($first) && is_object($second)) { + return; + } + + throw CannotDiff::differentTypes($first, $second); + } +} diff --git a/src/Enums/DiffResultLineType.php b/src/Enums/DiffResultLineType.php new file mode 100644 index 0000000..04a8ed5 --- /dev/null +++ b/src/Enums/DiffResultLineType.php @@ -0,0 +1,10 @@ +getSymbol($line->type)} {$line->key} => {$this->toString($line->value)}"; + + if ($line->oldValue !== null) { + $string .= " (from {$this->toString($line->oldValue)})"; + } + + return $string; + }, $diffResult->getLines()); + + return implode(PHP_EOL, $stringLines); + } + + protected function getSymbol(DiffResultLineType $lineType): string + { + return match ($lineType) { + DiffResultLineType::Added => '+', + DiffResultLineType::Removed => '-', + DiffResultLineType::Changed => 'U', + }; + } + + protected function toString(mixed $anything): string + { + return match (true) { + is_string($anything) => $anything, + is_array($anything) => json_encode($anything), + is_object($anything) => json_encode($anything), + default => (string) $anything, + }; + } +} diff --git a/src/TypeDiffers/ArrayDiffer.php b/src/TypeDiffers/ArrayDiffer.php new file mode 100644 index 0000000..b25bf7b --- /dev/null +++ b/src/TypeDiffers/ArrayDiffer.php @@ -0,0 +1,44 @@ + $value) { + $diffResult->add(DiffResultLineType::Added, $key, $value); + } + + foreach(array_diff_key($first, $second) as $key => $value) { + $diffResult->add(DiffResultLineType::Removed, $key, $value); + } + + foreach ($first as $key => $value) { + if (array_key_exists($key, $second)) { + if ($second[$key] !== $value) { + $diffResult->add(DiffResultLineType::Changed, $key, $second[$key], $value); + } + } + } + + return $diffResult; + + } +} diff --git a/src/TypeDiffers/ObjectDiffer.php b/src/TypeDiffers/ObjectDiffer.php new file mode 100644 index 0000000..55da3a8 --- /dev/null +++ b/src/TypeDiffers/ObjectDiffer.php @@ -0,0 +1,18 @@ +diff( + ['a' => 1, 'b' => 2, 'd' => 4], + ['a' => 1, 'c' => 3, 'd' => 5] + ); + + $renderedResult = $result->render(new SimpleRenderer()); + + dd($renderedResult); +}); diff --git a/tests/ExampleTest.php b/tests/ExampleTest.php deleted file mode 100644 index 5d36321..0000000 --- a/tests/ExampleTest.php +++ /dev/null @@ -1,5 +0,0 @@ -toBeTrue(); -});