/**
  * Forwards the request to another action and / or controller.
  *
  * Request is directly transferred to the other action / controller
  *
  * @param string $actionName Name of the action to forward to
  * @param string $controllerName Unqualified object name of the controller to forward to. If not specified, the current controller is used.
  * @param string $packageKey Key of the package containing the controller to forward to. May also contain the sub package, concatenated with backslash (Vendor.Foo\Bar\Baz). If not specified, the current package is assumed.
  * @param array $arguments Arguments to pass to the target action
  * @return void
  * @throws \TYPO3\Flow\Mvc\Exception\ForwardException
  * @see redirect()
  * @api
  */
 protected function forward($actionName, $controllerName = null, $packageKey = null, array $arguments = array())
 {
     $nextRequest = clone $this->request;
     $nextRequest->setControllerActionName($actionName);
     if ($controllerName !== null) {
         $nextRequest->setControllerName($controllerName);
     }
     if ($packageKey !== null && strpos($packageKey, '\\') !== false) {
         list($packageKey, $subpackageKey) = explode('\\', $packageKey, 2);
     } else {
         $subpackageKey = null;
     }
     if ($packageKey !== null) {
         $nextRequest->setControllerPackageKey($packageKey);
     }
     if ($subpackageKey !== null) {
         $nextRequest->setControllerSubpackageKey($subpackageKey);
     }
     $regularArguments = array();
     foreach ($arguments as $argumentName => $argumentValue) {
         if (substr($argumentName, 0, 2) === '__') {
             $nextRequest->setArgument($argumentName, $argumentValue);
         } else {
             $regularArguments[$argumentName] = $argumentValue;
         }
     }
     $nextRequest->setArguments($this->persistenceManager->convertObjectsToIdentityArrays($regularArguments));
     $this->arguments->removeAll();
     $forwardException = new \TYPO3\Flow\Mvc\Exception\ForwardException();
     $forwardException->setNextRequest($nextRequest);
     throw $forwardException;
 }
 /**
  * Iterate through the configured modules, find the matching module and set
  * the route path accordingly
  *
  * @param array $value (contains action, controller and package of the module controller)
  * @return boolean
  */
 protected function resolveValue($value)
 {
     if (is_array($value)) {
         $this->value = isset($value['@action']) && $value['@action'] !== 'index' ? $value['@action'] : '';
         if ($this->value !== '' && isset($value['@format'])) {
             $this->value .= '.' . $value['@format'];
         }
         $exceedingArguments = array();
         foreach ($value as $argumentKey => $argumentValue) {
             if (substr($argumentKey, 0, 1) !== '@' && substr($argumentKey, 0, 2) !== '__') {
                 $exceedingArguments[$argumentKey] = $argumentValue;
             }
         }
         if ($exceedingArguments !== array()) {
             $exceedingArguments = Arrays::removeEmptyElementsRecursively($exceedingArguments);
             $exceedingArguments = $this->persistenceManager->convertObjectsToIdentityArrays($exceedingArguments);
             $queryString = http_build_query(array($this->name => $exceedingArguments), null, '&');
             if ($queryString !== '') {
                 $this->value .= '?' . $queryString;
             }
         }
     }
     return true;
 }
 /**
  * Checks whether $routeValues can be resolved to a corresponding uri.
  * If all Route Parts can resolve one or more of the $routeValues, TRUE is
  * returned and $this->matchingURI contains the generated URI (excluding
  * protocol and host).
  *
  * @param array $routeValues An array containing key/value pairs to be resolved to uri segments
  * @return boolean TRUE if this Route corresponds to the given $routeValues, otherwise FALSE
  * @throws InvalidRoutePartValueException
  * @see getMatchingUri()
  */
 public function resolves(array $routeValues)
 {
     $this->resolvedUriPath = null;
     if ($this->uriPattern === null) {
         return false;
     }
     if (!$this->isParsed) {
         $this->parse();
     }
     $resolvedUriPath = '';
     $remainingDefaults = $this->defaults;
     $requireOptionalRouteParts = false;
     $matchingOptionalUriPortion = '';
     /** @var $routePart RoutePartInterface */
     foreach ($this->routeParts as $routePart) {
         if (!$routePart->resolve($routeValues)) {
             if (!$routePart->hasDefaultValue()) {
                 return false;
             }
         }
         if ($routePart->getName() !== null) {
             $remainingDefaults = Arrays::unsetValueByPath($remainingDefaults, $routePart->getName());
         }
         $routePartValue = null;
         if ($routePart->hasValue()) {
             $routePartValue = $routePart->getValue();
             if (!is_string($routePartValue)) {
                 throw new InvalidRoutePartValueException('RoutePart::getValue() must return a string after calling RoutePart::resolve(), got ' . (is_object($routePartValue) ? get_class($routePartValue) : gettype($routePartValue)) . ' for RoutePart "' . get_class($routePart) . '" in Route "' . $this->getName() . '".');
             }
         }
         $routePartDefaultValue = $routePart->getDefaultValue();
         if ($routePartDefaultValue !== null && !is_string($routePartDefaultValue)) {
             throw new InvalidRoutePartValueException('RoutePart::getDefaultValue() must return a string, got ' . (is_object($routePartDefaultValue) ? get_class($routePartDefaultValue) : gettype($routePartDefaultValue)) . ' for RoutePart "' . get_class($routePart) . '" in Route "' . $this->getName() . '".');
         }
         if (!$routePart->isOptional()) {
             $resolvedUriPath .= $routePart->hasValue() ? $routePartValue : $routePartDefaultValue;
             $requireOptionalRouteParts = false;
             continue;
         }
         if ($routePart->hasValue() && strtolower($routePartValue) !== strtolower($routePartDefaultValue)) {
             $matchingOptionalUriPortion .= $routePartValue;
             $requireOptionalRouteParts = true;
         } else {
             $matchingOptionalUriPortion .= $routePartDefaultValue;
         }
         if ($requireOptionalRouteParts) {
             $resolvedUriPath .= $matchingOptionalUriPortion;
             $matchingOptionalUriPortion = '';
         }
     }
     if ($this->compareAndRemoveMatchingDefaultValues($remainingDefaults, $routeValues) !== true) {
         return false;
     }
     if (isset($routeValues['@format']) && $routeValues['@format'] === '') {
         unset($routeValues['@format']);
     }
     // add query string
     if (count($routeValues) > 0) {
         $routeValues = Arrays::removeEmptyElementsRecursively($routeValues);
         $routeValues = $this->persistenceManager->convertObjectsToIdentityArrays($routeValues);
         if (!$this->appendExceedingArguments) {
             $internalArguments = $this->extractInternalArguments($routeValues);
             if ($routeValues !== array()) {
                 return false;
             }
             $routeValues = $internalArguments;
         }
         $queryString = http_build_query($routeValues, null, '&');
         if ($queryString !== '') {
             $resolvedUriPath .= strpos($resolvedUriPath, '?') !== false ? '&' . $queryString : '?' . $queryString;
         }
     }
     $this->resolvedUriPath = $resolvedUriPath;
     return true;
 }