/** * Generate a controller for a package. The package key can contain * a subpackage with a slash after the package key (e.g. "MyPackage/Admin"). * * @param string $packageKey The package key of the package for the new controller with an optional subpackage * @param string $controllerName The name for the new controller. This may also be a comma separated list of controller names. * @return void * @author Christopher Hlubek <*****@*****.**> */ public function generateControllerAction($packageKey, $controllerName = 'Standard') { $subpackageName = ''; if (strpos('/', $packageKey) !== FALSE) { list($packageKey, $subpackageName) = explode('/', $packageKey, 2); } if (!$this->packageManager->isPackageKeyValid($packageKey)) { return 'Package key "' . $packageKey . '" is not valid. Only UpperCamelCase with alphanumeric characters and underscore, please!' . PHP_EOL; } if (!$this->packageManager->isPackageAvailable($packageKey)) { return 'Package "' . $packageKey . '" is not available.' . PHP_EOL; } $generatedFiles = array(); $controllerNames = \F3\FLOW3\Utility\Arrays::trimExplode(',', $controllerName); foreach ($controllerNames as $currentControllerName) { $generatedFiles += $this->generatorService->generateController($packageKey, $subpackageName, $currentControllerName); } return implode(PHP_EOL, $generatedFiles) . PHP_EOL; }
/** * 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 * @author Bastian Waidelich <*****@*****.**> */ protected function buildSubrouteConfigurations(array $routesConfiguration, array $subRoutesConfiguration, $subRouteKey) { $mergedSubRoutesConfiguration = array(); foreach ($subRoutesConfiguration as $subRouteConfiguration) { foreach ($routesConfiguration as $routeConfiguration) { $name = isset($routeConfiguration['name']) ? $routeConfiguration['name'] : $routeConfiguration; $name .= ' :: '; $name .= isset($subRouteConfiguration['name']) ? $subRouteConfiguration['name'] : 'Subroute'; $uriPattern = str_replace('<' . $subRouteKey . '>', $subRouteConfiguration['uriPattern'], $routeConfiguration['uriPattern']); $defaults = isset($routeConfiguration['defaults']) ? $routeConfiguration['defaults'] : array(); if (isset($subRouteConfiguration['defaults'])) { $defaults = \F3\FLOW3\Utility\Arrays::arrayMergeRecursiveOverrule($defaults, $subRouteConfiguration['defaults']); } $routeParts = isset($routeConfiguration['routeParts']) ? $routeConfiguration['routeParts'] : array(); if (isset($subRouteConfiguration['routeParts'])) { $routeParts = \F3\FLOW3\Utility\Arrays::arrayMergeRecursiveOverrule($routeParts, $subRouteConfiguration['routeParts']); } $mergedSubRoutesConfiguration[] = array('name' => $name, 'uriPattern' => $uriPattern, 'defaults' => $defaults, 'routeParts' => $routeParts); } } return $mergedSubRoutesConfiguration; }
/** * Around advice * * @around method(F3\FLOW3\MVC\Web\Routing\Router->resolve()) * @param F3\FLOW3\AOP\JoinPointInterface $joinPoint The current join point * @return string Result of the target method * @author Bastian Waidelich <*****@*****.**> * @author Karsten Dambekalns <*****@*****.**> */ public function cacheResolveCall(\F3\FLOW3\AOP\JoinPointInterface $joinPoint) { $routeValues = $joinPoint->getMethodArgument('routeValues'); $routeValues = $this->convertObjectsToHashes($routeValues); \F3\FLOW3\Utility\Arrays::sortKeysRecursively($routeValues); $cacheIdentifier = md5(http_build_query($routeValues)); if ($this->resolveCache->has($cacheIdentifier)) { return $this->resolveCache->get($cacheIdentifier); } $matchingUri = $joinPoint->getAdviceChain()->proceed($joinPoint); if ($matchingUri !== '') { $this->resolveCache->set($cacheIdentifier, $matchingUri); } return $matchingUri; }
/** * Checks whether $requestPath corresponds to this Route. * If all Route Parts match successfully TRUE is returned and * $this->matchResults contains an array combining Route default values and * calculated matchResults from the individual Route Parts. * * @param string $requestPath the request path without protocol, host and query string * @return boolean TRUE if this Route corresponds to the given $requestPath, otherwise FALSE * @author Bastian Waidelich <*****@*****.**> * @see getMatchResults() */ public function matches($requestPath) { $this->matchResults = NULL; if ($requestPath === NULL) { return FALSE; } if ($this->uriPattern === NULL) { return FALSE; } if (!$this->isParsed) { $this->parse(); } $matchResults = array(); $requestPath = trim($requestPath, '/'); $skipOptionalParts = FALSE; $optionalPartCount = 0; foreach ($this->routeParts as $routePart) { if ($routePart->isOptional()) { $optionalPartCount++; if ($skipOptionalParts) { if ($routePart->getDefaultValue() === NULL) { return FALSE; } continue; } } else { $optionalPartCount = 0; $skipOptionalParts = FALSE; } if (!$routePart->match($requestPath)) { if ($routePart->isOptional() && $optionalPartCount === 1) { if ($routePart->getDefaultValue() === NULL) { return FALSE; } $skipOptionalParts = TRUE; } else { return FALSE; } } if ($routePart->getValue() !== NULL) { $matchResults[$routePart->getName()] = $routePart->getValue(); } } if (strlen($requestPath) > 0) { return FALSE; } $this->matchResults = \F3\FLOW3\Utility\Arrays::arrayMergeRecursiveOverrule($this->defaults, $matchResults); return TRUE; }
/** * Transforms the convoluted _FILES superglobal into a manageable form. * * @param array $convolutedFiles The _FILES superglobal * @return array Untangled files */ protected function untangleFilesArray(array $convolutedFiles) { $untangledFiles = array(); $fieldPaths = array(); foreach ($convolutedFiles as $firstLevelFieldName => $fieldInformation) { if (!is_array($fieldInformation['error'])) { $fieldPaths[] = array($firstLevelFieldName); } else { $newFieldPaths = $this->calculateFieldPaths($fieldInformation['error'], $firstLevelFieldName); array_walk($newFieldPaths, function (&$value, $key) { $value = explode('/', $value); }); $fieldPaths = array_merge($fieldPaths, $newFieldPaths); } } foreach ($fieldPaths as $fieldPath) { if (count($fieldPath) === 1) { $fileInformation = $convolutedFiles[$fieldPath[0]]; } else { $fileInformation = array(); foreach ($convolutedFiles[$fieldPath[0]] as $key => $subStructure) { $fileInformation[$key] = \F3\FLOW3\Utility\Arrays::getValueByPath($subStructure, array_slice($fieldPath, 1)); } } $untangledFiles = \F3\FLOW3\Utility\Arrays::setValueByPath($untangledFiles, $fieldPath, $fileInformation); } return $untangledFiles; }
/** * Builds the URI * * @return string The URI * @api * @author Bastian Waidelich <*****@*****.**> */ public function build() { $arguments = array(); if ($this->addQueryString === TRUE) { $arguments = $this->request->getArguments(); foreach ($this->argumentsToBeExcludedFromQueryString as $argumentToBeExcluded) { unset($arguments[$argumentToBeExcluded]); } } $arguments = \F3\FLOW3\Utility\Arrays::arrayMergeRecursiveOverrule($arguments, $this->arguments); $uri = $this->router->resolve($arguments); $this->lastArguments = $arguments; if ($this->section !== '') { $uri .= '#' . $this->section; } if (!$this->environment->isRewriteEnabled()) { $uri = 'index.php/' . $uri; } if ($this->createAbsoluteUri === TRUE) { $uri = $this->request->getBaseUri() . $uri; } return $uri; }
/** * Checks, resolves and injects dependencies as properties through calling the setter methods or setting * properties directly through reflection. * * @param array $properties Array of \F3\FLOW3\Object\Configuration\ConfigurationProperty for the current object * @param object $object The recently created instance of the current object. Dependencies will be injected to it. * @return void * @author Robert Lemke <*****@*****.**> */ protected function injectProperties($properties, $object) { foreach ($properties as $propertyName => $property) { $propertyValue = $property->getValue(); switch ($property->getType()) { case \F3\FLOW3\Object\Configuration\ConfigurationProperty::PROPERTY_TYPES_OBJECT: if ($propertyValue instanceof \F3\FLOW3\Object\Configuration\Configuration) { $preparedValue = $this->createObject($propertyValue->getObjectName(), $propertyValue); } else { if (strpos($propertyValue, '.') !== FALSE) { $settingPath = explode('.', $propertyValue); $settings = $this->configurationManager->getConfiguration(\F3\FLOW3\Configuration\ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, array_shift($settingPath)); $propertyValue = \F3\FLOW3\Utility\Arrays::getValueByPath($settings, $settingPath); } $preparedValue = $this->objectManager->getObject($propertyValue); } break; case \F3\FLOW3\Object\Configuration\ConfigurationProperty::PROPERTY_TYPES_STRAIGHTVALUE: $preparedValue = $propertyValue; break; case \F3\FLOW3\Object\Configuration\ConfigurationProperty::PROPERTY_TYPES_SETTING: if (strpos($propertyValue, '.') !== FALSE) { $settingPath = explode('.', $propertyValue); $settings = $this->configurationManager->getConfiguration(\F3\FLOW3\Configuration\ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, array_shift($settingPath)); $preparedValue = \F3\FLOW3\Utility\Arrays::getValueByPath($settings, $settingPath); } else { $preparedValue = $this->configurationManager->getConfiguration(\F3\FLOW3\Configuration\ConfigurationManager::CONFIGURATION_TYPE_SETTINGS, $propertyValue); } break; } $setterMethodName = 'inject' . ucfirst($propertyName); if (method_exists($object, $setterMethodName)) { $object->{$setterMethodName}($preparedValue); continue; } $setterMethodName = 'set' . ucfirst($propertyName); if (method_exists($object, $setterMethodName)) { $object->{$setterMethodName}($preparedValue); continue; } if (property_exists($object, $propertyName)) { $propertyReflection = new \ReflectionProperty($object, $propertyName); $propertyReflection->setAccessible(TRUE); $propertyReflection->setValue($object, $preparedValue); } } }
/** * @test * @author Robert Lemke <*****@*****.**> */ public function getValueByPathReturnsNullIfThePathHasMoreSegmentsThanTheGivenArray() { $array = array('Foo' => array('Bar' => array('Baz' => 'the value'))); $this->assertNULL(\F3\FLOW3\Utility\Arrays::getValueByPath($array, array('Foo', 'Bar', 'Baz', 'Bux'))); }
/** * 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 \F3\FLOW3\MVC\Web\Request $request The web request which will contain the arguments * @return void * @author Robert Lemke <*****@*****.**> */ protected function setArgumentsFromRawRequestData(\F3\FLOW3\MVC\Web\Request $request) { foreach ($request->getRequestUri()->getArguments() as $argumentName => $argumentValue) { $request->setArgument($argumentName, $argumentValue); } switch ($request->getMethod()) { case 'POST': foreach ($this->environment->getRawPostArguments() as $argumentName => $argumentValue) { $request->setArgument($argumentName, $argumentValue); } foreach ($this->environment->getUploadedFiles() as $argumentName => $argumentValue) { if ($request->hasArgument($argumentName)) { $existingArgumentValue = $request->getArgument($argumentName); if (is_array($existingArgumentValue)) { $request->setArgument($argumentName, \F3\FLOW3\Utility\Arrays::arrayMergeRecursiveOverrule($existingArgumentValue, $argumentValue)); } } else { $request->setArgument($argumentName, $argumentValue); } } break; # case 'PUT' : # $putArguments = array(); # parse_str(file_get_contents("php://input"), $putArguments); # foreach ($putArguments as $argumentName => $argumentValue) { # $request->setArgument($argumentName, $argumentValue); # } # break; } }