Skip to content

Commit 083cfbb

Browse files
authored
Merge pull request CoverGenius#5 from arg2009/main
refactor: update select minimal original diffs to detect changes to the same new key across original keys
2 parents fd658fc + b2188fd commit 083cfbb

17 files changed

+496
-42
lines changed

composer.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"Jet\\Tests\\": "tests/"
1616
},
1717
"files": [
18-
"src/Support/polyfills.php"
18+
"tests/Support/polyfills.php"
1919
]
2020
},
2121
"authors": [
@@ -30,6 +30,7 @@
3030
},
3131
"require-dev": {
3232
"phpunit/phpunit": "^9.6",
33-
"symfony/var-dumper": "^5.4"
33+
"symfony/var-dumper": "^5.4",
34+
"fakerphp/faker": "^1.20"
3435
}
3536
}

composer.lock

Lines changed: 68 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phpunit.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,8 @@
1111
<testsuite name="Feature">
1212
<directory suffix="Test.php">./tests/Feature</directory>
1313
</testsuite>
14+
<testsuite name="Unit">
15+
<directory suffix="Test.php">./tests/Unit</directory>
16+
</testsuite>
1417
</testsuites>
1518
</phpunit>

src/Actions/AddAdditionsToJsonDiffAction.php

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,17 @@ class AddAdditionsToJsonDiffAction
1515
*/
1616
private $getItemPathAction;
1717

18-
public function __construct(GetItemPathAction $getItemPathAction)
19-
{
18+
/**
19+
* @var GetUnmappedNewIndexesAction
20+
*/
21+
private $getUnmappedNewIndexesAction;
22+
23+
public function __construct(
24+
GetItemPathAction $getItemPathAction,
25+
GetUnmappedNewIndexesAction $getUnmappedNewIndexesAction
26+
) {
2027
$this->getItemPathAction = $getItemPathAction;
28+
$this->getUnmappedNewIndexesAction = $getUnmappedNewIndexesAction;
2129
}
2230

2331
/**
@@ -29,16 +37,9 @@ public function __construct(GetItemPathAction $getItemPathAction)
2937
*/
3038
public function execute(Collection $diffMappings, array $new, JsonDiff $jsonDiff, string $path): JsonDiff
3139
{
32-
collect(array_keys($new))
33-
->diff(
34-
$diffMappings
35-
->map(function (?DiffMapping $diffMapping) {
36-
return optional($diffMapping)->getNewIndex();
37-
})
38-
->filter(function (?int $index) {
39-
return $index !== null;
40-
})
41-
)
40+
$this
41+
->getUnmappedNewIndexesAction
42+
->execute($diffMappings, $new)
4243
->each(function (int $newKey) use ($path, $new, $jsonDiff) {
4344
$jsonDiff->addAddedKey($this->getItemPathAction->execute($path, $newKey), $newKey, $new[$newKey]);
4445
});

src/Actions/AddRemovalsToJsonDiffAction.php

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace Jet\JsonDiff\Actions;
66

77
use Illuminate\Support\Collection;
8-
use Jet\JsonDiff\DiffMapping;
98
use Jet\JsonDiff\JsonDiff;
109

1110
class AddRemovalsToJsonDiffAction
@@ -15,20 +14,24 @@ class AddRemovalsToJsonDiffAction
1514
*/
1615
private $getItemPathAction;
1716

18-
public function __construct(GetItemPathAction $getItemPathAction)
19-
{
17+
/**
18+
* @var GetUnmappedOriginalIndexesAction
19+
*/
20+
private $getUnmappedOriginalIndexesAction;
21+
22+
public function __construct(
23+
GetItemPathAction $getItemPathAction,
24+
GetUnmappedOriginalIndexesAction $getUnmappedOriginalIndexesAction
25+
) {
2026
$this->getItemPathAction = $getItemPathAction;
27+
$this->getUnmappedOriginalIndexesAction = $getUnmappedOriginalIndexesAction;
2128
}
2229

2330
public function execute(Collection $diffMappings, array $original, JsonDiff $jsonDiff, string $path): JsonDiff
2431
{
25-
$diffMappings
26-
->filter(function (?DiffMapping $diffMapping) {
27-
return $diffMapping === null;
28-
})
29-
->map(function (?DiffMapping $diffMapping, int $originalIndex) {
30-
return $originalIndex;
31-
})
32+
$this
33+
->getUnmappedOriginalIndexesAction
34+
->execute($diffMappings, $original)
3235
->each(function (int $originalKey) use ($original, $path, $jsonDiff) {
3336
$jsonDiff->addRemovedKey($this->getItemPathAction->execute($path, $originalKey), $originalKey, $original[$originalKey]);
3437
});

src/Actions/CalculateAllDifferencesRespectiveToOriginalAction.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public function __construct(GetTraversingPathAction $getTraversingPathAction)
2323
/**
2424
* Calculate the differences between the original keys and all of the new keys
2525
* group by the original key.
26+
*
27+
* @return Collection<DiffMapping>
2628
*/
2729
public function execute(array $original, array $new, string $path): Collection
2830
{
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jet\JsonDiff\Actions;
6+
7+
use Illuminate\Support\Collection;
8+
use Jet\JsonDiff\DiffMapping;
9+
10+
class GetUnmappedNewIndexesAction
11+
{
12+
/**
13+
* @param Collection<DiffMapping> $diffMappings
14+
* @param array $new
15+
* @return Collection<int>
16+
*/
17+
public function execute(Collection $diffMappings, array $new): Collection
18+
{
19+
return collect(array_keys($new))
20+
->diff(
21+
$diffMappings
22+
->map(function (DiffMapping $diffMapping) {
23+
return $diffMapping->getNewIndex();
24+
})
25+
)
26+
->values();
27+
}
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jet\JsonDiff\Actions;
6+
7+
use Illuminate\Support\Collection;
8+
use Jet\JsonDiff\DiffMapping;
9+
10+
class GetUnmappedOriginalIndexesAction
11+
{
12+
/**
13+
* @param Collection<DiffMapping> $diffMappings
14+
* @param array $original
15+
* @return Collection<int>
16+
*/
17+
public function execute(Collection $diffMappings, array $original): Collection
18+
{
19+
return collect(array_keys($original))
20+
->diff(
21+
$diffMappings
22+
->map(function (DiffMapping $diffMapping) {
23+
return $diffMapping->getOriginalIndex();
24+
})
25+
)
26+
->values();
27+
}
28+
}

src/Actions/SelectMinimalOriginalDiffsAction.php

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,49 @@
99

1010
class SelectMinimalOriginalDiffsAction
1111
{
12+
/**
13+
* @param Collection<Collection<DiffMapping>> $diffs
14+
* @return Collection<DiffMapping>
15+
*/
1216
public function execute(Collection $diffs): Collection
1317
{
14-
$keysProcessedInNewArray = [];
15-
16-
return
17-
$diffs->mapWithKeys(function (Collection $diffMappings, int $key) use (&$keysProcessedInNewArray) {
18-
$returnMapping = [
19-
"{$key}" => $diffMappings->first(function (DiffMapping $diffMapping) use (&$keysProcessedInNewArray) {
20-
return ! in_array($diffMapping->getNewIndex(), $keysProcessedInNewArray);
21-
})
22-
];
23-
24-
// No mapping to a new key was found
25-
if ($returnMapping["{$key}"] !== null) {
26-
$keysProcessedInNewArray[] = $returnMapping["{$key}"]->getNewIndex();
27-
}
28-
29-
return $returnMapping;
18+
$keysProcessedInNewArray = collect();
19+
20+
do {
21+
$addedMapping = false;
22+
23+
$diffs->each(function (Collection $diffMappings) use (&$keysProcessedInNewArray, &$addedMapping) {
24+
$diffMappings->each(function (DiffMapping $diffMapping) use (&$keysProcessedInNewArray, &$addedMapping) {
25+
// If we find a diff mapping with less changes than an existing mapping, replace it
26+
if (
27+
$keysProcessedInNewArray->has($diffMapping->getNewIndex()) &&
28+
$diffMapping
29+
->getDiff()
30+
->getNumberOfChanges() >=
31+
$keysProcessedInNewArray
32+
->get($diffMapping->getNewIndex())
33+
->getDiff()
34+
->getNumberOfChanges()
35+
) {
36+
return;
37+
}
38+
39+
// Add the mapping
40+
$keysProcessedInNewArray
41+
->offsetSet(
42+
$diffMapping->getNewIndex(),
43+
$diffMapping
44+
);
45+
$addedMapping = true;
46+
});
3047
});
48+
} while ($addedMapping);
49+
50+
// For each original index, return the found diff mapping
51+
return $keysProcessedInNewArray->mapWithKeys(function (DiffMapping $diffMapping) {
52+
return [
53+
$diffMapping->getOriginalIndex() => $diffMapping,
54+
];
55+
});
3156
}
3257
}

src/JsonDiff.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ public function __construct(array $original, array $new, string $startingPath =
7474
$this->calculateMinimalDiffOfListArrayAction = $this->serviceContainer
7575
->make(CalculateMinimalDiffOfListArrayAction::class);
7676

77+
// Arrays are the same, no differences
78+
if (empty($original) && empty($new)) {
79+
return;
80+
}
81+
7782
if (array_is_list($original) && array_is_list($new)) {
7883
$this
7984
->mergeChanges(

0 commit comments

Comments
 (0)