/** * Find a route that matches the HTTP request and then dispatch to request * to the route's defined action * * @param \Psr\Http\Message\SererRequestInterface $request The incoming request * @return \Psr\Http\Message\ResponseInterface|null The response * returned by the last-called action, or null if no response returned or * route was matched */ public function dispatch(ServerRequestInterface $request) { $response = null; DomainEvents::dispatch(new ReceivedRequestEvent($request)); $nroutes = count($this->routes); $method = $request->getMethod(); $path = $request->getUri()->getPath(); for ($i = 0; $i < $nroutes; $i++) { $route = $this->routes[$i]; // intialize the list of injectable arguments for the action $args = $tmpargs = array(); // if a specified method doesn't match, skip to the next route if ($route->hasMethod() && !$route->matchMethod($method, $args)) { continue; } // if any specified headers don't match, skip to the next route if ($route->hasHeaders()) { foreach ($route->getHeaderNames() as $header) { if (!$request->hasHeader($header) || !$route->matchHeader($header, $request->getHeaderLine($header), $tmpargs)) { continue 2; } $args = array_merge($tmpargs); } } // if the URI doesn't match, skip to the next route if (!$route->matchUri($path, $tmpargs)) { continue; } $args = array_merge($args, $tmpargs); // add the request object as an injectable argument $args['request'] = $request; $action = $route->getAction(); if (is_callable($action)) { if ($action instanceof \Closure) { // call closure $response = $this->di->injectFunction($action, $args); } elseif (is_array($action)) { // call object->action $response = $this->di->injectMethod($action[0], $action[1], $args); } else { // call static class::action list($class, $method) = explode('::', $action); $response = $this->di->injectStaticMethod($class, $method, $args); } } elseif (is_string($action) && strpos($action, ':') !== false) { list($class, $method) = explode(':', $action); if (!method_exists($class, $method)) { throw new \InvalidArgumentException('$action doesn\'t exist'); } // check if we've already instantiated the object, // if so, then use the existing object if (!isset($this->controllers[$class])) { $this->controllers[$class] = $this->di->injectConstructor($class, array('di' => '%DI')); } // call object->action $response = $this->di->injectMethod($this->controllers[$class], $method, $args); } else { throw new \InvalidArgumentException('$action expects callable or "class:method"'); } DomainEvents::dispatch(new DispatchedRequestEvent($request, $route, $args)); // if we get a request returned, dispatch it if ($response instanceof ServerRequestInterface) { $request = $response; $method = $request->getMethod(); $path = $request->getUri()->getPath(); $i = 0; $response = null; } elseif ($response instanceof ResponseInterface) { break; } } return $response; }
/** * @return string The URL to forward to */ public function process() { $post = $this->request->post(); // populate default field names $fields = $this->fields; if (is_null($fields)) { $fields = ['__id' => 'Submission ID', '__ts' => 'Submission Timestamp']; } foreach (array_keys($post) as $k) { $fields[$k] = $k; } $this->fields = $fields; // pull wanted data from post values $data = []; foreach (array_keys($this->fields) as $k) { // ignore internal fields if (strpos($k, '__') === 0) { continue; } $data[$k] = $post[$k]; } // generate submission ID and add field/data $submissionId = sha1($this->id . serialize($data)); $submission = new Submission($submissionId, $this, $data); // raise submission processed event DomainEvents::dispatch(new SubmissionProcessedEvent($submission)); }