/** * @dataProvider arrayMergeRecursiveOverruleData * @test */ public function arrayMergeRecursiveOverruleMergesSimpleArrays($inputArray1, $inputArray2, $dontAddNewKeys, $emptyValuesOverride, $expected) { $actual = \TYPO3\FLOW3\Utility\Arrays::arrayMergeRecursiveOverrule($inputArray1, $inputArray2, $dontAddNewKeys, $emptyValuesOverride); $this->assertSame($expected, $actual); }
/** * Merges specified arguments with arguments from request. * * If $this->request is no sub request, request arguments will only be merged if $this->addQueryString is set. * Otherwise all request arguments except for the ones prefixed with the current request argument namespace will * be merged. Additionally special arguments (PackageKey, SubpackageKey, ControllerName & Action) are merged. * * The argument provided through the $arguments parameter always overrule the request * arguments. * * The request hierarchy is structured as follows: * root (HTTP) > main (Action) > sub (Action) > sub sub (Action) * * @param array $arguments * @return void */ protected function mergeArgumentsWithRequestArguments(array &$arguments) { $requestArguments = array(); $mainRequest = $this->request->getMainRequest(); $isSubRequest = $this->request !== $mainRequest; if ($isSubRequest) { $requestArguments = $mainRequest->getArguments(); // remove all arguments of the current sub request if ($this->request->getArgumentNamespace() !== '') { $requestNamespace = $this->getRequestNamespacePath($this->request); if ($this->addQueryString === FALSE) { $requestArguments = Arrays::unsetValueByPath($requestArguments, $requestNamespace); } else { foreach ($this->argumentsToBeExcludedFromQueryString as $argumentToBeExcluded) { $requestArguments = Arrays::unsetValueByPath($requestArguments, $requestNamespace . '.' . $argumentToBeExcluded); } } } // merge special arguments (package, subpackage, controller & action) from main request $mainRequestPackageKey = $mainRequest->getControllerPackageKey(); if (!empty($mainRequestPackageKey)) { $requestArguments['@package'] = $mainRequestPackageKey; } $mainRequestSubpackageKey = $mainRequest->getControllerSubpackageKey(); if (!empty($mainRequestSubpackageKey)) { $requestArguments['@subpackage'] = $mainRequestSubpackageKey; } $mainRequestControllerName = $mainRequest->getControllerName(); if (!empty($mainRequestControllerName)) { $requestArguments['@controller'] = $mainRequestControllerName; } $mainRequestActionName = $mainRequest->getControllerActionName(); if (!empty($mainRequestActionName)) { $requestArguments['@action'] = $mainRequestActionName; } } elseif ($this->addQueryString === TRUE) { $requestArguments = $this->request->getArguments(); foreach ($this->argumentsToBeExcludedFromQueryString as $argumentToBeExcluded) { unset($requestArguments[$argumentToBeExcluded]); } } if (count($requestArguments) === 0) { return; } $arguments = Arrays::arrayMergeRecursiveOverrule($requestArguments, $arguments); }
/** * Takes the raw request data and - depending on the request method * maps them into the request object. Afterwards all mapped arguments * can be retrieved by the getArgument(s) method, no matter if they * have been GET, POST or PUT arguments before. * * @param array $getArguments Arguments as found in $_GET * @param array $postArguments Arguments as found in $_POST * @param array $uploadArguments Arguments as found in $_FILES * @return array the unified arguments */ protected function buildUnifiedArguments(array $getArguments, array $postArguments, array $uploadArguments) { $arguments = $getArguments; $contentArguments = NULL; if ($this->method === 'POST') { $contentArguments = $postArguments !== array() ? $postArguments : $this->decodeBodyArguments($this->getContent(), $this->headers->get('Content-Type')); } elseif ($this->method === 'PUT') { $contentArguments = $this->decodeBodyArguments($this->getContent(), $this->headers->get('Content-Type')); } if ($contentArguments !== NULL) { $arguments = Arrays::arrayMergeRecursiveOverrule($arguments, $contentArguments); } $arguments = Arrays::arrayMergeRecursiveOverrule($arguments, $this->untangleFilesArray($uploadArguments)); return $arguments; }
/** * Tries to load the reflection data from the compile time cache. * * The compile time cache is only supported for Development context and thus * this function will return in any other context. * * If no reflection data was found, this method will at least load the precompiled * reflection data of any possible frozen package. Even if precompiled reflection * data could be loaded, FALSE will be returned in order to signal that other * packages still need to be reflected. * * @return boolean TRUE if reflection data could be loaded, otherwise FALSE */ protected function loadClassReflectionCompiletimeCache() { $data = $this->reflectionDataCompiletimeCache->get('ReflectionData'); if ($data === FALSE) { if ($this->context->isDevelopment()) { $useIgBinary = extension_loaded('igbinary'); foreach ($this->packageManager->getActivePackages() as $packageKey => $package) { if ($this->packageManager->isPackageFrozen($packageKey)) { $pathAndFilename = $this->getPrecompiledReflectionStoragePath() . $packageKey . '.dat'; if (file_exists($pathAndFilename)) { $data = $useIgBinary ? igbinary_unserialize(file_get_contents($pathAndFilename)) : unserialize(file_get_contents($pathAndFilename)); foreach ($data as $propertyName => $propertyValue) { $this->{$propertyName} = \TYPO3\FLOW3\Utility\Arrays::arrayMergeRecursiveOverrule($this->{$propertyName}, $propertyValue); } } } } } return FALSE; } foreach ($data as $propertyName => $propertyValue) { $this->{$propertyName} = $propertyValue; } 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 \TYPO3\FLOW3\Mvc\Exception\InvalidRoutePartValueException * @see getMatchingUri() */ public function resolves(array $routeValues) { $this->matchingUri = NULL; if ($this->uriPattern === NULL) { return FALSE; } if (!$this->isParsed) { $this->parse(); } $matchingUri = ''; $mergedRouteValues = \TYPO3\FLOW3\Utility\Arrays::arrayMergeRecursiveOverrule($this->defaults, $routeValues); $requireOptionalRouteParts = FALSE; $matchingOptionalUriPortion = ''; foreach ($this->routeParts as $routePart) { if (!$routePart->resolve($routeValues)) { if (!$routePart->hasDefaultValue()) { return FALSE; } } $routePartValue = NULL; if ($routePart->hasValue()) { $routePartValue = $routePart->getValue(); if (!is_string($routePartValue)) { throw new \TYPO3\FLOW3\Mvc\Exception\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 \TYPO3\FLOW3\Mvc\Exception\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()) { $matchingUri .= $routePart->hasValue() ? $routePartValue : $routePartDefaultValue; $requireOptionalRouteParts = FALSE; continue; } if ($routePart->hasValue() && $routePartValue !== $routePartDefaultValue) { $matchingOptionalUriPortion .= $routePartValue; $requireOptionalRouteParts = TRUE; } else { $matchingOptionalUriPortion .= $routePartDefaultValue; } if ($requireOptionalRouteParts) { $matchingUri .= $matchingOptionalUriPortion; $matchingOptionalUriPortion = ''; } } if ($this->compareAndRemoveMatchingDefaultValues($this->defaults, $routeValues) !== TRUE) { return FALSE; } if (isset($routeValues['@format']) && $routeValues['@format'] === '') { unset($routeValues['@format']); } $this->throwExceptionIfTargetControllerDoesNotExist($mergedRouteValues); // add query string if (count($routeValues) > 0) { $routeValues = \TYPO3\FLOW3\Utility\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 !== '') { $matchingUri .= strpos($matchingUri, '?') !== FALSE ? '&' . $queryString : '?' . $queryString; } } $this->matchingUri = $matchingUri; return TRUE; }
/** * Returns an ActionRequest which referred to this request, if any. * * The referring request is not set or determined automatically but must be * explicitly set through the corresponding internal argument "__referrer". * This mechanism is used by FLOW3's form and validation mechanisms. * * @return \TYPO3\FLOW3\Mvc\ActionRequest the referring request, or NULL if no referrer found */ public function getReferringRequest() { if ($this->referringRequest !== NULL) { return $this->referringRequest; } if (!isset($this->internalArguments['__referrer'])) { return NULL; } if (is_array($this->internalArguments['__referrer'])) { $referrerArray = $this->internalArguments['__referrer']; $referringRequest = $this->getHttpRequest()->createActionRequest(); $arguments = array(); if (isset($referrerArray['arguments'])) { $serializedArgumentsWithHmac = $referrerArray['arguments']; $serializedArguments = $this->hashService->validateAndStripHmac($serializedArgumentsWithHmac); $arguments = unserialize(base64_decode($serializedArguments)); unset($referrerArray['arguments']); } $referringRequest->setArguments(\TYPO3\FLOW3\Utility\Arrays::arrayMergeRecursiveOverrule($arguments, $referrerArray)); return $referringRequest; } else { $this->referringRequest = $this->internalArguments['__referrer']; } return $this->referringRequest; }
/** * Imports fjson files into TYPO3CR nodes. * See Settings.yaml for an exemplary configuration for the documentation bundles * * @param string $bundle bundle to import. If not specified all configured bundles will be imported * @return void */ public function importCommand($bundle = NULL) { $bundles = $bundle !== NULL ? array($bundle) : array_keys($this->settings['bundles']); $defaultConfiguration = isset($this->settings['defaultConfiguration']) ? $this->settings['defaultConfiguration'] : array(); foreach ($bundles as $bundle) { if (!isset($this->settings['bundles'][$bundle])) { $this->outputLine('Bundle "%s" is not configured', array($bundle)); $this->quit(1); } $this->bundleConfiguration = \TYPO3\FLOW3\Utility\Arrays::arrayMergeRecursiveOverrule($defaultConfiguration, $this->settings['bundles'][$bundle]); $this->importBundle($bundle); $this->outputLine('---'); } $this->outputLine('Done'); }
/** * Routes the specified web request by setting the controller name, action and possible * parameters. If the request could not be routed, it will be left untouched. * * @param \TYPO3\FLOW3\Http\Request $httpRequest The web request to be analyzed. Will be modified by the router. * @return \TYPO3\FLOW3\Mvc\ActionRequest */ public function route(\TYPO3\FLOW3\Http\Request $httpRequest) { $this->actionRequest = $httpRequest->createActionRequest(); $routePath = substr($httpRequest->getUri()->getPath(), strlen($httpRequest->getBaseUri()->getPath())); $matchResults = $this->findMatchResults($routePath); if ($matchResults !== NULL) { $requestArguments = $this->actionRequest->getArguments(); $mergedArguments = Arrays::arrayMergeRecursiveOverrule($requestArguments, $matchResults); $this->actionRequest->setArguments($mergedArguments); } $this->setDefaultControllerAndActionNameIfNoneSpecified(); return $this->actionRequest; }
/** * Merges all routes in $routesConfiguration with the sub routes in $subRoutesConfiguration * * @param array $routesConfiguration * @param array $subRoutesConfiguration * @param string $subRouteKey the key of the sub route: <subRouteKey> * @return array the merged route configuration * @throws \TYPO3\FLOW3\Configuration\Exception\ParseErrorException */ protected function buildSubrouteConfigurations(array $routesConfiguration, array $subRoutesConfiguration, $subRouteKey) { $mergedSubRoutesConfigurations = array(); foreach ($subRoutesConfiguration as $subRouteConfiguration) { foreach ($routesConfiguration as $routeConfiguration) { $subRouteConfiguration['name'] = sprintf('%s :: %s', isset($routeConfiguration['name']) ? $routeConfiguration['name'] : 'Unnamed Route', isset($subRouteConfiguration['name']) ? $subRouteConfiguration['name'] : 'Unnamed Subroute'); if (!isset($subRouteConfiguration['uriPattern'])) { throw new \TYPO3\FLOW3\Configuration\Exception\ParseErrorException('No uriPattern defined in route configuration "' . $subRouteConfiguration['name'] . '".', 1274197615); } $subRouteConfiguration['uriPattern'] = str_replace('<' . $subRouteKey . '>', $subRouteConfiguration['uriPattern'], $routeConfiguration['uriPattern']); $subRouteConfiguration = Arrays::arrayMergeRecursiveOverrule($routeConfiguration, $subRouteConfiguration); unset($subRouteConfiguration['subRoutes']); $mergedSubRoutesConfigurations[] = $subRouteConfiguration; } } return $mergedSubRoutesConfigurations; }