/**
  * Reach the given step.
  *
  * @param ModelInterface $model
  * @param Step           $step
  * @param ModelState     $currentModelState
  * @return ModelState
  */
 protected function reachStep(ModelInterface $model, Step $step, ModelState $currentModelState = null)
 {
     try {
         $this->checkCredentials($step);
     } catch (AccessDeniedException $e) {
         return $this->storage->newModelStateError($model, $this->process->getName(), $step->getName(), array($e), $currentModelState);
     }
     $errors = $this->executeValidations($model, $step->getValidations());
     if (0 === count($errors)) {
         $modelState = $this->storage->newModelStateSuccess($model, $this->process->getName(), $step->getName(), $currentModelState);
         // update model status
         if ($step->hasModelStatus()) {
             list($method, $constant) = $step->getModelStatus();
             $model->{$method}(constant($constant));
         }
         $eventName = sprintf('%s.%s.reached', $this->process->getName(), $step->getName());
         $this->dispatcher->dispatch($eventName, new StepEvent($step, $model, $modelState));
     } else {
         $modelState = $this->storage->newModelStateError($model, $this->process->getName(), $step->getName(), $errors, $currentModelState);
         $eventName = sprintf('%s.%s.validation_fail', $this->process->getName(), $step->getName());
         $this->dispatcher->dispatch($eventName, new StepEvent($step, $model, $modelState));
         if ($step->getOnInvalid()) {
             $step = $this->getProcessStep($step->getOnInvalid());
             $modelState = $this->reachStep($model, $step);
         }
     }
     return $modelState;
 }