Prevent infinite loop when a subject from the trigger is missing

Given the trigger provides two subjects but only one subject was given via parameter and no
transformer was able to generate the second from the first, this method runs into an
infinite loop. This commit prevents this infinite loop.

[MAILPOET-4935]
This commit is contained in:
David Remer
2023-03-20 12:14:48 +02:00
committed by Aschepikov
parent b5a846327a
commit 68f09b6bd1

View File

@@ -96,12 +96,17 @@ class SubjectTransformerHandler {
*/ */
public function provideAllSubjects(Trigger $trigger, Subject ...$subjects): array { public function provideAllSubjects(Trigger $trigger, Subject ...$subjects): array {
$allSubjectsKeys = $this->subjectKeysForTrigger($trigger); $allSubjectsKeys = $this->subjectKeysForTrigger($trigger);
$allSubjectKeyTargets = array_diff($allSubjectsKeys, array_map( $allSubjectKeyTargets = array_filter(
array_diff($allSubjectsKeys, array_map(
function(Subject $subject): string { function(Subject $subject): string {
return $subject->getKey(); return $subject->getKey();
}, },
$subjects $subjects
)); )),
function(string $target) use ($subjects): bool {
return $this->canSubjectsTransformTo($target, ...$subjects);
}
);
$allSubjects = []; $allSubjects = [];
foreach ($subjects as $existingSubject) { foreach ($subjects as $existingSubject) {
@@ -118,9 +123,17 @@ class SubjectTransformerHandler {
} }
} }
} }
while (count($allSubjects) < count($allSubjectsKeys)) {
$allSubjects = $this->provideAllSubjects($trigger, ...array_values($allSubjects)); $allSubjectsTransformed = true;
do {
foreach ($allSubjectKeyTargets as $key) {
if (!isset($allSubjects[$key])) {
$allSubjectsTransformed = false;
break;
} }
}
$allSubjects = $allSubjectsTransformed ? $allSubjects : $this->provideAllSubjects($trigger, ...array_values($allSubjects));
} while (!$allSubjectsTransformed);
return array_values($allSubjects); return array_values($allSubjects);
} }
@@ -164,4 +177,25 @@ class SubjectTransformerHandler {
return $transformerChain; return $transformerChain;
} }
private function canSubjectsTransformTo(string $target, Subject ...$subjects): bool {
if (
in_array($target, array_map(
function(Subject $subject): string {
return $subject->getKey();
},
$subjects
))
) {
return true;
}
foreach ($subjects as $subject) {
$possibleTransformations = $this->getPossibleTransformations($subject->getKey());
if (in_array($target, $possibleTransformations)) {
return true;
}
}
return false;
}
} }