Skip to content

Commit 205e78b

Browse files
committed
Fix keeping data from group child steps
The `Step::keep()` methods now also work when applied to child steps within a group step.
1 parent 8d1f87b commit 205e78b

File tree

3 files changed

+74
-14
lines changed

3 files changed

+74
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77
## [Unreleased]
88
### Fixed
99
* When providing an empty base selector to an `Html` step (`Html::each('')`, `Html::first('')`, `Html::last('')`), it won't fail with an error, but instead log a warning, that it most likely doesn't make sense.
10+
* The `Step::keep()` methods now also work when applied to child steps within a group step.
1011

1112
## [3.4.2] - 2025-03-08
1213
### Fixed

src/Steps/Group.php

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ final class Group extends BaseStep
2828
*/
2929
public function invokeStep(Input $input): Generator
3030
{
31-
$combinedOutput = [];
31+
$combinedOutput = $combinedKeptData = [];
3232

3333
if ($this->uniqueInput && !$this->inputOrOutputIsUnique($input)) {
3434
return;
@@ -46,16 +46,23 @@ public function invokeStep(Input $input): Generator
4646
}
4747

4848
if ($this->includeOutput($step)) {
49-
$combinedOutput = $this->addOutputToCombinedOutputs(
49+
$combinedOutput = $this->addToCombinedOutputData(
5050
$output->get(),
5151
$combinedOutput,
5252
$nthOutput,
5353
);
5454
}
55+
56+
// Also transfer data, kept in group child steps, to the kept data of the final group output.
57+
if ($output->keep !== $inputForStepInvocation->keep) {
58+
$keep = $this->getNewlyKeptData($output, $inputForStepInvocation);
59+
60+
$combinedKeptData = $this->addToCombinedOutputData($keep, $combinedKeptData, $nthOutput);
61+
}
5562
}
5663
}
5764

58-
yield from $this->prepareCombinedOutputs($combinedOutput, $input);
65+
yield from $this->prepareCombinedOutputs($combinedOutput, $combinedKeptData, $input);
5966
}
6067
}
6168

@@ -134,31 +141,39 @@ protected function includeOutput(StepInterface $step): bool
134141
* @param mixed[] $combined
135142
* @return mixed[]
136143
*/
137-
private function addOutputToCombinedOutputs(
138-
mixed $output,
139-
array $combined,
140-
int $nthOutput,
141-
): array {
142-
if (is_array($output)) {
143-
foreach ($output as $key => $value) {
144-
$combined[$nthOutput][$key][] = $value;
144+
private function addToCombinedOutputData(mixed $add, array $combined, int $nthElement): array
145+
{
146+
if (is_array($add)) {
147+
foreach ($add as $key => $value) {
148+
$combined[$nthElement][$key][] = $value;
145149
}
146150
} else {
147-
$combined[$nthOutput][][] = $output;
151+
$combined[$nthElement][][] = $add;
148152
}
149153

150154
return $combined;
151155
}
152156

157+
/**
158+
* @return mixed[]
159+
*/
160+
private function getNewlyKeptData(Output $output, Input $input): array
161+
{
162+
return array_filter($output->keep, function ($key) use ($input) {
163+
return !array_key_exists($key, $input->keep);
164+
}, ARRAY_FILTER_USE_KEY);
165+
}
166+
153167
/**
154168
* @param mixed[] $combinedOutputs
169+
* @param mixed[] $combinedKeptData
155170
* @param Input $input
156171
* @return Generator<Output>
157172
* @throws Exception
158173
*/
159-
private function prepareCombinedOutputs(array $combinedOutputs, Input $input): Generator
174+
private function prepareCombinedOutputs(array $combinedOutputs, array $combinedKeptData, Input $input): Generator
160175
{
161-
foreach ($combinedOutputs as $combinedOutput) {
176+
foreach ($combinedOutputs as $key => $combinedOutput) {
162177
if ($this->maxOutputsExceeded()) {
163178
break;
164179
}
@@ -170,6 +185,10 @@ private function prepareCombinedOutputs(array $combinedOutputs, Input $input): G
170185
if ($this->passesAllFilters($outputData)) {
171186
$output = $this->makeOutput($outputData, $input);
172187

188+
if (array_key_exists($key, $combinedKeptData)) {
189+
$output->keep($this->normalizeCombinedOutputs($combinedKeptData[$key]));
190+
}
191+
173192
if ($this->uniqueOutput !== false && !$this->inputOrOutputIsUnique($output)) {
174193
continue;
175194
}

tests/Steps/GroupTest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,46 @@ function () {
529529
]);
530530
});
531531

532+
it('keeps data, when keep() is called on child steps', function () {
533+
$step1 = helper_getValueReturningStep(['foo' => 'fooValue', 'bar' => 'barValue']);
534+
535+
$step2 = helper_getValueReturningStep(['baz' => 'bazValue', 'quz' => 'quzValue']);
536+
537+
$group = (new Group())
538+
->addStep($step1->keep('foo'))
539+
->addStep($step2->keep(['baz', 'quz']));
540+
541+
$output = helper_invokeStepWithInput($group);
542+
543+
expect($output)->toHaveCount(1)
544+
->and($output[0]->keep)->toBe([
545+
'foo' => 'fooValue',
546+
'baz' => 'bazValue',
547+
'quz' => 'quzValue',
548+
]);
549+
});
550+
551+
it('keeps data, when keepAs() is called on child steps', function () {
552+
$step1 = helper_getValueReturningStep('fooValue');
553+
554+
$step2 = helper_getValueReturningStep(['bar' => 'barValue', 'baz' => 'bazValue']);
555+
556+
$group = (new Group())
557+
->addStep($step1->keepAs('foo'))
558+
->addStep($step2->keepAs('quz'));
559+
560+
$output = helper_invokeStepWithInput($group);
561+
562+
expect($output)->toHaveCount(1)
563+
->and($output[0]->keep)->toBe([
564+
'foo' => 'fooValue',
565+
'quz' => [
566+
'bar' => 'barValue',
567+
'baz' => 'bazValue',
568+
],
569+
]);
570+
});
571+
532572
test(
533573
'when steps yield multiple outputs it combines the first output from first step with first output from second ' .
534574
'step and so on.',

0 commit comments

Comments
 (0)