/**
* @param StoryTeller $st
* @param Injectables $injectables
* @param array $phases
*/
public function playPhases($activity, StoryTeller $st, Injectables $injectables, $phases, $thingBeingPlayed)
{
// shorthand
$output = $st->getOutput();
// we are going to need something to help us load each of our
// phases
$phaseLoader = $injectables->phaseLoader;
// pre-load all of the phases, before we execute them
// this will trigger any PHP syntax errors now rather than
// when we're part-way through executing our code
$phasesToPlay = [];
foreach ($phases as $phaseName => $isActive) {
$phase = $phaseLoader->loadPhase($st, $phaseName);
$phasesToPlay[$phaseName] = ['phase' => $phase, 'isActive' => $isActive];
}
// the result of playing this group of phases
$groupResult = null;
if ($thingBeingPlayed) {
$groupResult = $thingBeingPlayed->getResult();
$groupResult->setActivity($activity);
}
// we need to wrap our code to catch old-style PHP errors
$legacyHandler = new Legacy_ErrorHandler();
// execute each phase, until either:
//
// 1. all listed phases have been executed, or
// 2. one of the phases says that the story has failed
foreach ($phasesToPlay as $phaseName => $phaseData) {
// shorthand
$phase = $phaseData['phase'];
$isActive = $phaseData['isActive'];
try {
// tell the world that we're running this phase
$output->startPhase($phase);
// play the phase
$phaseResult = $legacyHandler->run([$this, 'playPhase'], [$st, $injectables, $phase, $isActive, $thingBeingPlayed]);
// remember the result of this phase
//$phaseResults->addResult($phase, $phaseResult);
// now, what do we do?
$nextAction = $phaseResult->getNextAction();
switch ($nextAction) {
case self::NEXT_SKIP:
// why?
if ($phaseResult->getPhaseIsBlacklisted()) {
if ($groupResult) {
$groupResult->setPhaseGroupHasBeenBlacklisted($phaseResult);
}
$output->logPhaseSkipped($phaseName, self::MSG_PHASE_BLACKLISTED . ': ' . $phaseResult->getMessage());
} else {
if ($phaseResult->getPhaseCannotRun()) {
$output->logPhaseSkipped($phaseName, $phaseResult->getMessage());
} else {
if ($groupResult) {
$groupResult->setPhaseGroupIsIncomplete($phaseResult);
}
$output->logPhaseSkipped($phaseName, self::MSG_PHASE_INCOMPLETE);
}
}
// tell the output plugins that this phase is over
$output->endPhase($phase, $phaseResult);
return;
case self::NEXT_FAIL:
if ($groupResult) {
$groupResult->setPhaseGroupHasFailed($phaseResult);
}
$output->logPhaseError($phaseName, self::MSG_PHASE_FAILED . ': ' . $phaseResult->getMessage());
// tell the output plugins that this phase is over
$output->endPhase($phase, $phaseResult);
return;
case self::NEXT_CONTINUE:
if ($groupResult) {
// keep the result up to date, in case this
// is the last one
if ($phaseResult->getPhaseHasBeenSkipped()) {
$groupResult->setPhaseGroupHasBeenSkipped();
} else {
$groupResult->setPhaseGroupHasSucceeded();
}
}
// tell the output plugins that this phase is over
$output->endPhase($phase, $phaseResult);
}
} catch (Exception $e) {
// tell our output plugins what happened
$output->logPhaseError($phaseName, "uncaught exception: " . (string) $e->getMessage() . $e->getTraceAsString());
// we need to create a dummy phase result for this
$phaseResult = new Phase_Result($phaseName);
$phaseResult->setPlayingFailed($phaseResult::ERROR, self::MSG_PHASE_FAILED, $e);
// tell the world that this phase is over
$output->endPhase($phase, $phaseResult);
// this is a fatal exception
if ($groupResult) {
$groupResult->setPhaseGroupHasError($phaseResult);
}
// run no more phases
return;
}
}
// all done
// if ($groupResult) {
// $groupResult->setPhaseGroupHasSucceeded();
// }
}