swoole = $response; $this ->setModel(new Error()) ->setModel(new ErrorDev()) ->setModel(new User()) ->setModel(new Session()) ->setModel(new Locale()) ->setModel(new Team()) ->setModel(new TeamList()) ->setModel(new Membership()) ->setModel(new MembershipList()) ; $this->startTime = \microtime(true); } /** * HTTP content types */ const CONTENT_TYPE_YAML = 'application/x-yaml'; /** * List of defined output objects */ protected $models = []; /** * Set Model Object * * @return self */ public function setModel(Model $instance): self { $this->models[$instance->getType()] = $instance; return $this; } /** * Get Model Object * * @return Model */ public function getModel(string $key): Model { if(!isset($this->models[$key])) { throw new Exception('Undefined model: '.$key); } return $this->models[$key]; } /** * Validate response objects and outputs * the response according to given format type */ public function dynamic(Document $document, string $model) { return $this->json($this->output($document, $model)); } /** * Generate valid response object from document data */ protected function output(Document $document, string $model): array { $data = $document; $model = $this->getModel($model); $output = []; foreach($model->getRules() as $key => $rule) { if(!$document->isSet($key)) { if(!is_null($rule['default'])) { $document->setAttribute($key, $rule['default']); } else { throw new Exception('Missing response key: '.$key); } } if($rule['array']) { if(!is_array($data[$key])) { throw new Exception($key.' must be an array of '.$rule['type'].' types'); } foreach ($data[$key] as &$item) { if(array_key_exists($rule['type'], $this->models) && $item instanceof Document) { $item = $this->output($item, $rule['type']); } } } $output[$key] = $data[$key]; } return $output; } /** * YAML * * This helper is for sending YAML HTTP response. * It sets relevant content type header ('application/x-yaml') and convert a PHP array ($data) to valid YAML using native yaml_parse * * @see https://en.wikipedia.org/wiki/YAML * * @param array $data */ public function yaml(array $data) { if(!extension_loaded('yaml')) { throw new Exception('Missing yaml extension. Learn more at: https://www.php.net/manual/en/book.yaml.php'); } $this ->setContentType(Response::CONTENT_TYPE_YAML) ->send(yaml_emit($data, YAML_UTF8_ENCODING)) ; } /** * Output response * * Generate HTTP response output including the response header (+cookies) and body and prints them. * * @param string $body * @param int $exit exit code or don't exit if code is null * * @return self */ public function send(string $body = '', int $exit = null): void { if(!$this->disablePayload) { $this->addHeader('X-Debug-Speed', microtime(true) - $this->startTime); $this ->appendCookies() ->appendHeaders() ; $this->size = $this->size + mb_strlen(implode("\n", $this->headers)) + mb_strlen($body, '8bit'); $this->swoole->end($body); $this->disablePayload(); } } /** * Append headers * * Iterating over response headers to generate them using native PHP header function. * This method is also responsible for generating the response and content type headers. * * @return self */ protected function appendHeaders(): self { // Send status code header $this->swoole->status($this->statusCode); // Send content type header $this ->addHeader('Content-Type', $this->contentType) ; // Set application headers foreach ($this->headers as $key => $value) { $this->swoole->header($key, $value); } return $this; } /** * Append cookies * * Iterating over response cookies to generate them using native PHP cookie function. * * @return self */ protected function appendCookies(): self { foreach ($this->cookies as $cookie) { $this->swoole->cookie( $cookie['name'], $cookie['value'], $cookie['expire'], $cookie['path'], $cookie['domain'], $cookie['secure'], $cookie['httponly'], $cookie['samesite'], ); } return $this; } }