Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
freekmurze committed Feb 22, 2024
1 parent 23bb235 commit cc5190a
Show file tree
Hide file tree
Showing 15 changed files with 319 additions and 12 deletions.
7 changes: 0 additions & 7 deletions src/DiffClass.php

This file was deleted.

41 changes: 41 additions & 0 deletions src/DiffResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Spatie\Diff;

use Spatie\Diff\Enums\DiffResultLineType;
use Spatie\Diff\Renderers\Renderer;

class DiffResult
{
/** @var array<\Spatie\Diff\DiffResultLine> */
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);
}
}
16 changes: 16 additions & 0 deletions src/DiffResultLine.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace Spatie\Diff;

use Spatie\Diff\Enums\DiffResultLineType;

class DiffResultLine
{
public function __construct(
public DiffResultLineType $type,
public string $key,
public mixed $value,
public mixed $oldValue = null,
) {
}
}
62 changes: 62 additions & 0 deletions src/Differ.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Spatie\Diff;

use Spatie\Diff\Exceptions\CannotDiff;
use Spatie\Diff\TypeDiffers\ArrayDiffer;
use Spatie\Diff\TypeDiffers\ObjectDiffer;
use Spatie\Diff\TypeDiffers\ScalarDiffer;
use Spatie\Diff\TypeDiffers\TypeDiffer;

class Differ
{
/** @var array<\Spatie\Diff\TypeDiffers\TypeDiffer> */
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);
}
}
10 changes: 10 additions & 0 deletions src/Enums/DiffResultLineType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Spatie\Diff\Enums;

enum DiffResultLineType
{
case Added;
case Changed;
case Removed;
}
18 changes: 18 additions & 0 deletions src/Exceptions/CannotDiff.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Spatie\Diff\Exceptions;

use Exception;

class CannotDiff extends Exception
{
public static function noDifferFound(mixed $first, mixed $second): self
{
return new self("We could not find a differ for the given type of the passed arguments");
}

public static function differentTypes(mixed $first, mixed $second): self
{
return new self("The given arguments are of different types");
}
}
8 changes: 8 additions & 0 deletions src/Normalisers/ObjectNormaliser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Spatie\Diff\Normalisers;

class ObjectNormaliser
{

}
10 changes: 10 additions & 0 deletions src/Renderers/Renderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Spatie\Diff\Renderers;

use Spatie\Diff\DiffResult;

interface Renderer
{
public function render(DiffResult $diffResult): string;
}
44 changes: 44 additions & 0 deletions src/Renderers/SimpleRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Spatie\Diff\Renderers;

use Spatie\Diff\DiffResult;
use Spatie\Diff\DiffResultLine;
use Spatie\Diff\Enums\DiffResultLineType;

class SimpleRenderer implements Renderer
{
public function render(DiffResult $diffResult): string
{
$stringLines = array_map(function (DiffResultLine $line) {
$string = "{$this->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,
};
}
}
44 changes: 44 additions & 0 deletions src/TypeDiffers/ArrayDiffer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Spatie\Diff\TypeDiffers;

use Spatie\Diff\DiffResult;
use Spatie\Diff\Enums\DiffResultLineType;

class ArrayDiffer implements TypeDiffer
{
public function canDiff(mixed $first, mixed $second): bool
{
return is_array($first) && is_array($second);
}

/**
* @param array $first
* @param array $second
*
* @return \Spatie\Diff\DiffResult
*/
public function diff($first, $second): DiffResult
{
$diffResult = new DiffResult($first, $second);

foreach(array_diff_key($second, $first) as $key => $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;

}
}
18 changes: 18 additions & 0 deletions src/TypeDiffers/ObjectDiffer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace Spatie\Diff\TypeDiffers;

use Spatie\Diff\DiffResult;

class ObjectDiffer implements TypeDiffer
{
public function canDiff(mixed $first, mixed $second): bool
{
return is_object($first) && is_object($second);
}

public function diff($first, $second): DiffResult
{
// TODO: Implement diff() method.
}
}
19 changes: 19 additions & 0 deletions src/TypeDiffers/ScalarDiffer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Spatie\Diff\TypeDiffers;

use Spatie\Diff\DiffResult;

class ScalarDiffer implements TypeDiffer
{

public function canDiff(mixed $first, mixed $second): bool
{
return is_scalar($first) && is_scalar($second);
}

public function diff($first, $second): DiffResult
{
// TODO: Implement diff() method.
}
}
12 changes: 12 additions & 0 deletions src/TypeDiffers/TypeDiffer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace Spatie\Diff\TypeDiffers;

use Spatie\Diff\DiffResult;

interface TypeDiffer
{
public function canDiff(mixed $first, mixed $second): bool;

public function diff(mixed $first, mixed $second): DiffResult;
}
17 changes: 17 additions & 0 deletions tests/ArrayDiffTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

use Spatie\Diff\Differ;
use Spatie\Diff\Renderers\SimpleRenderer;

it('can diff two arrays', function () {
$differ = new Differ();

$result = $differ->diff(
['a' => 1, 'b' => 2, 'd' => 4],
['a' => 1, 'c' => 3, 'd' => 5]
);

$renderedResult = $result->render(new SimpleRenderer());

dd($renderedResult);
});
5 changes: 0 additions & 5 deletions tests/ExampleTest.php

This file was deleted.

0 comments on commit cc5190a

Please sign in to comment.