/** * @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(); // } }