/** * Construct a flat array of method arguments for the resource method. * * @param Route $route The route being processed. * @param ReflectionMethod $method The resource class method that arguments * are needed for. * * @return array */ protected function _getResourceMethodArguments(Route $route, ReflectionMethod $method) { $clsRenderable = 'Sonno\\Application\\Renderable'; $pathParamValues = $this->_uriInfo->getPathParameters(); $queryParamValues = $this->_uriInfo->getQueryParameters(); $headerParamValues = $this->_request->getHeaders(); $pathParams = $route->getPathParams() ?: array(); $queryParams = $route->getQueryParams() ?: array(); $headerParams = $route->getHeaderParams() ?: array(); $formParams = $route->getFormParams() ?: array(); $resourceMethodArgs = array(); parse_str($this->_request->getRequestBody(), $formParamValues); foreach ($method->getParameters() as $idx => $reflParam) { $parameterName = $reflParam->getName(); $parameterClass = $reflParam->getClass(); // if the parameter is a type that implements Renderable, use the // implementation's unrender() function to generate an instance // of the class from the request body as the parameter value if (null !== $parameterClass && $parameterClass->implementsInterface($clsRenderable)) { $parameterClassName = $parameterClass->getName(); $parameterValue = $parameterClassName::unrender($this->_request->getRequestBody(), new Variant(null, null, $this->_request->getContentType())); $resourceMethodArgs[$idx] = $parameterValue; } // search for an argument value in the Path parameter collection if (in_array($parameterName, $pathParams) && isset($pathParamValues[$parameterName])) { $resourceMethodArgs[$idx] = $pathParamValues[$parameterName]; } // search for an argument value in the Query parameter collection if (in_array($parameterName, $queryParams) && isset($queryParamValues[$parameterName])) { $resourceMethodArgs[$idx] = $queryParamValues[$parameterName]; } // search for an argument value in the Header parameter collection if (in_array($parameterName, $headerParams) && isset($headerParamValues[$parameterName])) { $resourceMethodArgs[$idx] = $headerParamValues[$parameterName]; } // search for an argument value in the Form parameter collection if (in_array($parameterName, $formParams) && isset($formParamValues[$parameterName])) { $resourceMethodArgs[$idx] = $formParamValues[$parameterName]; } } return $resourceMethodArgs; }
/** * Find candidate routes for an incoming request. * * @param RequestInterface $request The incoming request * @param array $pathParameters The set of Path parameters * matched on the incoming Request * path. * * @throws \Sonno\Http\Exception\MethodNotAllowedException * @throws \Sonno\Http\Exception\NotFoundException * @throws \InvalidArgumentException * @throws \Sonno\Http\Exception\NotAcceptableException * * @return array A collection of candidate Route objects. * * @todo When filtering candidate routes by matching the incoming * media type, Sonno is ignoring any Content-Type parameters * including the charset. This should be resolved, otherwise there * will be unintended consequences while dealing with charsets and * other Content-Type parameters. */ public function match(RequestInterface $request, &$pathParameters = array()) { if (null == $request) { throw new InvalidArgumentException('Missing function argument: request'); } $candidateRoutes = array(); $allRoutes = $this->_config->getRoutes(); $requestPath = $request->getRequestUri(); $requestMethod = $request->getMethod(); $requestContentType = $request->getContentType(); // drop the base path from the beginning of the incoming path $basePath = $this->_config->getBasePath(); if ($basePath && strstr($requestPath, $basePath) !== FALSE) { $requestPath = substr($requestPath, strlen($basePath)); } // locate matching routes using the incoming request path /** @var $route \Sonno\Configuration\Route */ foreach ($allRoutes as $route) { $params = $this->_matchPath($requestPath, $route->getPath()); if (false !== $params) { $pathParameters = $params; $candidateRoutes[] = $route; } } if (empty($candidateRoutes)) { throw new NotFoundException(); } // filter candidate routes further by matching the incoming request // method $allowedMethods = array(); foreach ($candidateRoutes as $i => $route) { if ($route->getHttpMethod() != $requestMethod) { $allowedMethods[] = $route->getHttpMethod(); unset($candidateRoutes[$i]); } } if (empty($candidateRoutes)) { throw new MethodNotAllowedException($allowedMethods); } // filter candidate routes further by matching the incoming media type if (!empty($requestContentType)) { foreach ($candidateRoutes as $i => $route) { if (($offset = strpos($requestContentType, ';')) !== false) { $requestContentType = substr($requestContentType, 0, $offset); } if (!in_array($requestContentType, $route->getConsumes())) { unset($candidateRoutes[$i]); } } } if (empty($candidateRoutes)) { throw new NotAcceptableException(); } return $candidateRoutes; }