]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Middleware/UpdateAndMaintenance.php
b606e1c8013091a2b9cd5caa3b6d97276454b0f7
[galette.git] / galette / lib / Galette / Middleware / UpdateAndMaintenance.php
1 <?php
2
3 /**
4 * Copyright © 2003-2024 The Galette Team
5 *
6 * This file is part of Galette (https://galette.eu).
7 *
8 * Galette is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * Galette is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 namespace Galette\Middleware;
23
24 use Galette\Core\I18n;
25 use Psr\Http\Message\ServerRequestInterface as Request;
26 use Psr\Http\Message\ResponseInterface as Response;
27 use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
28 use Slim\Routing\RouteParser;
29
30 /**
31 * Galette Slim middleware for maintenance and needs update pages display.
32 *
33 * Relies on Slim modes. Set 'MAINT' for maintenance mode, and 'NEED_UPDATE' for the need update one.
34 * Maintenance mode page will be displayed if current logged in user is not super admin.
35 *
36 * Renders maintenance and needs update pages, as 503 (service not available)
37 *
38 * @author Johan Cwiklinski <johan@x-tnd.be>
39 */
40 class UpdateAndMaintenance
41 {
42 public const MAINTENANCE = 0;
43 public const NEED_UPDATE = 1;
44
45 /**
46 * @var callable
47 */
48 protected $callback;
49
50 /**
51 * @var I18n
52 */
53 protected I18n $i18n;
54
55 /**
56 * @var RouteParser
57 */
58 protected RouteParser $routeParser;
59
60 /**
61 * Constructor
62 *
63 * @param I18n $i18n I18n instance
64 * @param RouteParser $routeParser Route parser
65 * @param callable|int $callback Callable or local constant
66 */
67 public function __construct(I18n $i18n, RouteParser $routeParser, callable|int $callback = self::MAINTENANCE)
68 {
69 $this->i18n = $i18n;
70 $this->routeParser = $routeParser;
71
72 if ($callback === self::MAINTENANCE) {
73 $this->callback = array($this, 'maintenancePage');
74 } elseif ($callback === self::NEED_UPDATE) {
75 $this->callback = array($this, 'needsUpdatePage');
76 } else {
77 if (!is_callable($callback)) {
78 throw new \InvalidArgumentException('argument callback must be callable');
79 } else {
80 $this->callback = $callback;
81 }
82 }
83 }
84
85 /**
86 * Middleware invokable class
87 *
88 * @param Request $request PSR7 request
89 * @param RequestHandler $handler PSR7 request handler
90 *
91 * @return Response
92 */
93 public function __invoke(Request $request, RequestHandler $handler): Response
94 {
95 $response = new \Slim\Psr7\Response();
96 $response
97 ->withStatus(503)
98 ->withHeader('Content-type', 'text/html')
99 ->getBody()->write(call_user_func($this->callback, $request));
100 return $response;
101 }
102
103 /**
104 * Renders the page
105 *
106 * @param Request $request PSR7 request
107 * @param string $contents HTML page contents
108 *
109 * @return string
110 */
111 private function renderPage(Request $request, string $contents): string
112 {
113 $path = $this->routeParser->urlFor('slash');
114
115 //add ending / if missing
116 if (
117 $path === ''
118 || $path !== '/'
119 && substr($path, -1) !== '/'
120 ) {
121 $path .= '/';
122 }
123
124 $theme_path = $path . GALETTE_THEME;
125
126 $body = "<!DOCTYPE html>
127 <html class=\"public_page\" lang=\"" . $this->i18n->getAbbrev() . "\">
128 <head>
129 <title>" . _T("Galette needs update!") . "</title>
130 <meta charset=\"UTF-8\"/>
131 <link rel=\"stylesheet\" type=\"text/css\" href=\"" . $theme_path . "ui/semantic.min.css\"/>
132 <link rel=\"shortcut icon\" href=\"" . $theme_path . "images/favicon.png\"/>
133 </head>
134 <body class=\"notup2date pushable\">
135 <div class=\"pusher\">
136 <div id=\"main\" class=\"ui container\">
137 <div class=\"ui basic segment\">
138 <div class=\"ui basic center aligned fitted segment\">
139 <img src=\"" . $theme_path . "images/galette.png\" alt=\"[ Galette ]\"/>
140 </div>
141 <div class=\"ui center aligned message\">" . $contents . "</div>
142 </div>
143 </div>
144 </div>
145 </body>
146 </html>";
147 return $body;
148 }
149
150 /**
151 * Displays maintenance page
152 *
153 * @param Request $request PSR7 request
154 *
155 * @return string
156 */
157 private function maintenancePage(Request $request): string
158 {
159 $contents = "<div class=\"header\">" . _T("Galette is currently under maintenance!") . "</div>
160 <p>" . _T("The Galette instance you are requesting is currently under maintenance. Please come back later.") . "</p>";
161 return $this->renderPage($request, $contents);
162 }
163
164 /**
165 * Displays needs update page
166 *
167 * @param Request $request PSR7 request
168 *
169 * @return string
170 */
171 private function needsUpdatePage(Request $request): string
172 {
173 $contents = "<h1>" . _T("Galette needs update!") . "</h1>
174 <p>" . _T("Your Galette database is not present, or not up to date.") . "</p>
175 <p><em>" . _T("Please run install or upgrade procedure (check the documentation)") . "</em></p>";
176 return $this->renderPage($request, $contents);
177 }
178 }