/**
  * 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($model, $step);
     } catch (AccessDeniedException $e) {
         $violations = new ViolationList();
         $violations->add(new Violation($e->getMessage()));
         $modelState = $this->storage->newModelStateError($model, $this->process->getName(), $step->getName(), $violations, $currentModelState);
         $eventName = sprintf('%s.%s.bad_credentials', $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;
     }
     $event = new ValidateStepEvent($step, $model, new ViolationList());
     $eventName = sprintf('%s.%s.validate', $this->process->getName(), $step->getName());
     $this->dispatcher->dispatch($eventName, $event);
     if (0 === count($event->getViolationList())) {
         $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(), $event->getViolationList(), $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;
 }