1208909d8SGreg Roach<?php 2208909d8SGreg Roach 3208909d8SGreg Roach/** 4208909d8SGreg Roach * webtrees: online genealogy 5d11be702SGreg Roach * Copyright (C) 2023 webtrees development team 6208909d8SGreg Roach * This program is free software: you can redistribute it and/or modify 7208909d8SGreg Roach * it under the terms of the GNU General Public License as published by 8208909d8SGreg Roach * the Free Software Foundation, either version 3 of the License, or 9208909d8SGreg Roach * (at your option) any later version. 10208909d8SGreg Roach * This program is distributed in the hope that it will be useful, 11208909d8SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of 12208909d8SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13208909d8SGreg Roach * GNU General Public License for more details. 14208909d8SGreg Roach * You should have received a copy of the GNU General Public License 15208909d8SGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>. 16208909d8SGreg Roach */ 17208909d8SGreg Roach 18208909d8SGreg Roachdeclare(strict_types=1); 19208909d8SGreg Roach 20208909d8SGreg Roachnamespace Fisharebest\Webtrees\Factories; 21208909d8SGreg Roach 22208909d8SGreg Roachuse Fig\Http\Message\StatusCodeInterface; 23208909d8SGreg Roachuse Fisharebest\Webtrees\Contracts\ResponseFactoryInterface; 24208909d8SGreg Roachuse Fisharebest\Webtrees\Module\ModuleThemeInterface; 25208909d8SGreg Roachuse Fisharebest\Webtrees\Registry; 26208909d8SGreg Roachuse Fisharebest\Webtrees\Webtrees; 27208909d8SGreg Roachuse Psr\Http\Message\ResponseFactoryInterface as PSR17ResponseFactoryInterface; 28208909d8SGreg Roachuse Psr\Http\Message\ResponseInterface; 29208909d8SGreg Roachuse Psr\Http\Message\ServerRequestInterface; 30208909d8SGreg Roachuse Psr\Http\Message\StreamFactoryInterface; 31208909d8SGreg Roachuse Psr\Http\Message\UriInterface; 32208909d8SGreg Roach 33208909d8SGreg Roachuse function is_string; 34208909d8SGreg Roachuse function json_encode; 35208909d8SGreg Roachuse function view; 36208909d8SGreg Roach 37208909d8SGreg Roachuse const JSON_THROW_ON_ERROR; 38208909d8SGreg Roachuse const JSON_UNESCAPED_UNICODE; 39208909d8SGreg Roach 40208909d8SGreg Roach/** 41208909d8SGreg Roach * Make a PSR-7 response (using a PSR-17 response factory). 42208909d8SGreg Roach */ 43208909d8SGreg Roachclass ResponseFactory implements ResponseFactoryInterface 44208909d8SGreg Roach{ 45208909d8SGreg Roach private PSR17ResponseFactoryInterface $response_factory; 46208909d8SGreg Roach 47208909d8SGreg Roach private StreamFactoryInterface $stream_factory; 48208909d8SGreg Roach 49208909d8SGreg Roach /** 50208909d8SGreg Roach * @param PSR17ResponseFactoryInterface $response_factory 51208909d8SGreg Roach * @param StreamFactoryInterface $stream_factory 52208909d8SGreg Roach */ 53208909d8SGreg Roach public function __construct(PSR17ResponseFactoryInterface $response_factory, StreamFactoryInterface $stream_factory) 54208909d8SGreg Roach { 55208909d8SGreg Roach $this->response_factory = $response_factory; 56208909d8SGreg Roach $this->stream_factory = $stream_factory; 57208909d8SGreg Roach } 58208909d8SGreg Roach 59208909d8SGreg Roach /** 60208909d8SGreg Roach * Redirect to a named route. 61208909d8SGreg Roach * 62208909d8SGreg Roach * @param string $route_name 63208909d8SGreg Roach * @param array<bool|int|string|array<string>|null> $parameters 64208909d8SGreg Roach * @param int $status 65208909d8SGreg Roach * 66208909d8SGreg Roach * @return ResponseInterface 67208909d8SGreg Roach * 68208909d8SGreg Roach */ 69208909d8SGreg Roach public function redirect( 70208909d8SGreg Roach string $route_name, 71208909d8SGreg Roach array $parameters = [], 72208909d8SGreg Roach int $status = StatusCodeInterface::STATUS_FOUND 73208909d8SGreg Roach ): ResponseInterface { 74208909d8SGreg Roach $url = Registry::routeFactory()->route($route_name, $parameters); 75208909d8SGreg Roach 76208909d8SGreg Roach return $this->redirectUrl($url, $status); 77208909d8SGreg Roach } 78208909d8SGreg Roach 79208909d8SGreg Roach /** 80208909d8SGreg Roach * Redirect to a URL. 81208909d8SGreg Roach * 82ac71572dSGreg Roach * @param UriInterface|string $url 83208909d8SGreg Roach * @param int $code 84208909d8SGreg Roach * 85208909d8SGreg Roach * @return ResponseInterface 86208909d8SGreg Roach */ 87ac71572dSGreg Roach public function redirectUrl(UriInterface|string $url, int $code = StatusCodeInterface::STATUS_FOUND): ResponseInterface 88208909d8SGreg Roach { 89208909d8SGreg Roach return $this->response_factory 90208909d8SGreg Roach ->createResponse($code) 916172e7f6SGreg Roach ->withHeader('location', (string) $url); 92208909d8SGreg Roach } 93208909d8SGreg Roach 94208909d8SGreg Roach /** 95208909d8SGreg Roach * @param string|array<mixed>|object $content 96208909d8SGreg Roach * @param int $code 97208909d8SGreg Roach * @param array<string,string> $headers 98208909d8SGreg Roach * 99208909d8SGreg Roach * @return ResponseInterface 100208909d8SGreg Roach */ 101ac71572dSGreg Roach public function response(string|array|object $content = '', int $code = StatusCodeInterface::STATUS_OK, array $headers = []): ResponseInterface 102208909d8SGreg Roach { 103208909d8SGreg Roach if ($content === '' && $code === StatusCodeInterface::STATUS_OK) { 104208909d8SGreg Roach $code = StatusCodeInterface::STATUS_NO_CONTENT; 105208909d8SGreg Roach } 106208909d8SGreg Roach 107208909d8SGreg Roach if (is_string($content)) { 1086172e7f6SGreg Roach $headers['content-type'] ??= 'text/html; charset=UTF-8'; 109208909d8SGreg Roach } else { 110208909d8SGreg Roach $content = json_encode($content, JSON_THROW_ON_ERROR | JSON_UNESCAPED_UNICODE); 1116172e7f6SGreg Roach $headers['content-type'] ??= 'application/json'; 112208909d8SGreg Roach } 113208909d8SGreg Roach 114208909d8SGreg Roach $stream = $this->stream_factory->createStream($content); 115208909d8SGreg Roach 116208909d8SGreg Roach $response = $this->response_factory 117208909d8SGreg Roach ->createResponse($code) 118208909d8SGreg Roach ->withBody($stream); 119208909d8SGreg Roach 120208909d8SGreg Roach foreach ($headers as $key => $value) { 121208909d8SGreg Roach $response = $response->withHeader($key, $value); 122208909d8SGreg Roach } 123208909d8SGreg Roach 124208909d8SGreg Roach return $response; 125208909d8SGreg Roach } 126208909d8SGreg Roach 127208909d8SGreg Roach /** 128208909d8SGreg Roach * Create and render a view, and embed it in an HTML page. 129208909d8SGreg Roach * 130208909d8SGreg Roach * @param string $view_name 13124f79581SGreg Roach * @param array<string,mixed> $view_data 132208909d8SGreg Roach * @param int $status 133208909d8SGreg Roach * @param string $layout_name 134208909d8SGreg Roach * 135208909d8SGreg Roach * @return ResponseInterface 136208909d8SGreg Roach */ 137208909d8SGreg Roach public function view( 138208909d8SGreg Roach string $view_name, 139208909d8SGreg Roach array $view_data, 140208909d8SGreg Roach int $status = StatusCodeInterface::STATUS_OK, 141208909d8SGreg Roach string $layout_name = Webtrees::LAYOUT_DEFAULT 142208909d8SGreg Roach ): ResponseInterface { 143208909d8SGreg Roach // Render the view. 144208909d8SGreg Roach $content = view($view_name, $view_data); 145208909d8SGreg Roach 146208909d8SGreg Roach // Make the view's data available to the layout. 147208909d8SGreg Roach $layout_data = [ 148208909d8SGreg Roach 'content' => $content, 149*d35568b4SGreg Roach 'request' => Registry::container()->get(ServerRequestInterface::class), 150*d35568b4SGreg Roach 'theme' => Registry::container()->get(ModuleThemeInterface::class), 151208909d8SGreg Roach 'title' => $view_data['title'] ?? Webtrees::NAME, 152208909d8SGreg Roach ]; 153208909d8SGreg Roach 154d8d90d88SGreg Roach // Embed the content in the layout. 155208909d8SGreg Roach $html = view($layout_name, $layout_data); 156208909d8SGreg Roach 157208909d8SGreg Roach return $this->response($html, $status); 158208909d8SGreg Roach } 159208909d8SGreg Roach} 160