Skip to content

Commit ff127d2

Browse files
committed
Fix bug where some original indexes do not have a mapping to new indexes.
1 parent 24e6e39 commit ff127d2

File tree

2 files changed

+106
-10
lines changed

2 files changed

+106
-10
lines changed

src/Actions/SelectJsonDiffsForOriginalKeysWithMinimalChangesAction.php

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@ public function execute(Collection $diffs): Collection
1919
$originalToNewIndexMapping = collect();
2020

2121
do {
22-
$addedMapping = false;
22+
$modifiedMapping = false;
2323

24-
$diffs->each(function (Collection $diffMappings) use (&$originalToNewIndexMapping, &$keysProcessedInNewArray, &$addedMapping): void {
25-
$diffMappings->each(function (DiffMapping $diffMapping) use (&$originalToNewIndexMapping, &$keysProcessedInNewArray, &$addedMapping): void {
26-
// If we find a diff mapping with lesser changes than an existing mapping, replace it
24+
$diffs->each(function (Collection $diffMappings) use (&$originalToNewIndexMapping, &$keysProcessedInNewArray, &$modifiedMapping): void {
25+
$diffMappings->each(function (DiffMapping $diffMapping) use (&$originalToNewIndexMapping, &$keysProcessedInNewArray, &$modifiedMapping): void {
26+
/*
27+
* If this diff mapping's new index has already been mapped, and it has fewer changes
28+
* skip this diff mapping.
29+
*/
2730
if (
2831
$keysProcessedInNewArray->has($diffMapping->getNewIndex())
2932
&& $diffMapping
@@ -37,8 +40,10 @@ public function execute(Collection $diffs): Collection
3740
return;
3841
}
3942

40-
// If we have an existing diff mapping to the original index with lesser changes than the current
41-
// diff mapping, skip replacing the mapping with the current index
43+
/*
44+
* If this diff mapping's original index has already been mapped, and it has fewer changes
45+
* skip this diff mapping.
46+
*/
4247
if (
4348
$originalToNewIndexMapping->has($diffMapping->getOriginalIndex())
4449
&& $diffMapping
@@ -52,25 +57,38 @@ public function execute(Collection $diffs): Collection
5257
return;
5358
}
5459

60+
// Changes will happen so we need to keep looping
61+
$modifiedMapping = true;
62+
5563
// Add the mapping
5664
$keysProcessedInNewArray
5765
->offsetSet(
5866
$diffMapping->getNewIndex(),
5967
$diffMapping
6068
);
6169

62-
// Add an original index to new index mapping to track if an original index has been mapped to a new
63-
// index already
70+
/*
71+
* Add an original index to new index mapping to track if an original index has been mapped to a new
72+
* index already
73+
*/
6474
$originalToNewIndexMapping
6575
->offsetSet(
6676
$diffMapping->getOriginalIndex(),
6777
$diffMapping->getNewIndex()
6878
);
6979

70-
$addedMapping = true;
80+
// Unmap any other original indexes that may have been mapped to this diff mapping's new index
81+
$originalToNewIndexMapping
82+
->filter(function ($newIndex, $originalIndex) use ($diffMapping) {
83+
return $originalIndex !== $diffMapping->getOriginalIndex() && $newIndex === $diffMapping->getNewIndex();
84+
})
85+
->keys()
86+
->each(function ($originalIndex) use (&$originalToNewIndexMapping): void {
87+
$originalToNewIndexMapping->offsetUnset($originalIndex);
88+
});
7189
});
7290
});
73-
} while ($addedMapping);
91+
} while ($modifiedMapping);
7492

7593
// For each original index, return the found diff mapping
7694
return $keysProcessedInNewArray->mapWithKeys(function (DiffMapping $diffMapping) {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Jet\Tests\Unit\Actions;
6+
7+
use Carbon\Carbon;
8+
use Illuminate\Container\Container;
9+
use Jet\JsonDiff\Actions\CalculateAllDifferencesRespectiveToOriginalAction;
10+
use Jet\JsonDiff\Actions\SelectJsonDiffsForOriginalKeysWithMinimalChangesAction;
11+
use Jet\JsonDiff\Actions\SortDifferencesByNumberOfChangesAction;
12+
use Jet\Tests\TestCase;
13+
14+
class SelectJsonDiffsForOriginalKeysWithMinimalChangesTest extends TestCase
15+
{
16+
/**
17+
* Test the action will create a mapping for each original array element to an element in the new array if the
18+
* new array has greater or equal number of array elements to the original array.
19+
*
20+
* Note:
21+
* The new array element mapped to the original array element will always have the least amount of changes in
22+
* respect to the original element.
23+
*/
24+
public function test_each_original_keys_have_a_mapping_to_a_new_key_if_new_array_has_greater_or_equal_elements_to_the_original_array(): void
25+
{
26+
$originalArray = [
27+
[
28+
'label' => 'post1',
29+
'description' => null,
30+
'meta' => [
31+
'created_at' => Carbon::now(),
32+
],
33+
],
34+
[
35+
'label' => 'post2',
36+
'description' => 'description for test post 2',
37+
'meta' => null,
38+
],
39+
];
40+
41+
$newArray = [
42+
[
43+
'label' => 'post1',
44+
'description' => 'description for test post 1',
45+
'meta' => [
46+
'created_at' => Carbon::now(),
47+
'comment_count' => 25,
48+
],
49+
],
50+
[
51+
'label' => 'post2',
52+
'description' => 'description for test post 2',
53+
'meta' => null,
54+
],
55+
[
56+
'label' => 'post3',
57+
'description' => 'description for test post 3',
58+
'meta' => null,
59+
],
60+
];
61+
62+
$diffMappings = $this->container(CalculateAllDifferencesRespectiveToOriginalAction::class)->execute($originalArray, $newArray, '');
63+
$diffMappings = $this->container(SortDifferencesByNumberOfChangesAction::class)->execute($diffMappings);
64+
$diffMappings = $this->container(SelectJsonDiffsForOriginalKeysWithMinimalChangesAction::class)->execute($diffMappings);
65+
66+
// Assert that both original array elements have a mapping to the new array elements
67+
$this->assertSame(2, $diffMappings->count());
68+
}
69+
70+
private function container($abstract = null, array $parameters = [])
71+
{
72+
if (null === $abstract) {
73+
return Container::getInstance();
74+
}
75+
76+
return Container::getInstance()->make($abstract, $parameters);
77+
}
78+
}

0 commit comments

Comments
 (0)