]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Controllers/AjaxController.php
504e710a665013ca7745dda1c2990f1c4b856689
[galette.git] / galette / lib / Galette / Controllers / AjaxController.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Galette ajax controller
7 *
8 * PHP version 5
9 *
10 * Copyright © 2023 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * @category Controllers
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2023 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link https://galette.eu
34 * @since 2023-02-01
35 */
36
37 namespace Galette\Controllers;
38
39 use Analog\Analog;
40 use Galette\Entity\Adherent;
41 use Galette\Entity\Contribution;
42 use Galette\Filters\MembersList;
43 use Galette\Repository\Members;
44 use Galette\Util\Password;
45 use Galette\Util\Telemetry;
46 use Slim\Psr7\Request;
47 use Slim\Psr7\Response;
48 use Throwable;
49
50 /**
51 * Galette ajax controller
52 *
53 * @category Controllers
54 * @name GaletteController
55 * @package Galette
56 * @author Johan Cwiklinski <johan@x-tnd.be>
57 * @copyright 2023 The Galette Team
58 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
59 * @link https://galette.eu
60 * @since 2023-02-01
61 */
62
63 class AjaxController extends AbstractController
64 {
65 /**
66 * Messages
67 *
68 * @param Request $request PSR Request
69 * @param Response $response PSR Response
70 *
71 * @return Response
72 */
73 public function messages(Request $request, Response $response): Response
74 {
75 $this->view->render(
76 $response,
77 'elements/ajax_messages.html.twig'
78 );
79 return $response;
80 }
81
82 /**
83 * Ajax Drag'N'Drop photo
84 *
85 * @param Request $request PSR Request
86 * @param Response $response PSR Response
87 *
88 * @return Response
89 */
90 public function photo(Request $request, Response $response): Response
91 {
92 $post = $request->getParsedBody();
93 $ret = ['result' => false];
94
95 if (
96 !isset($post['member_id'])
97 || !isset($post['file'])
98 || !isset($post['filename'])
99 || !isset($post['filesize'])
100 ) {
101 $this->flash->addMessage(
102 'error_detected',
103 _T("Required argument not present!")
104 );
105 return $this->withJson($response, $ret);
106 }
107
108 $mid = $post['member_id'];
109 $fsize = $post['filesize'];
110 $fname = $post['filename'];
111 $cropping = null;
112 if ($post['cropping'] != false) {
113 $cropping = $post['cropping'];
114 }
115 $tmpname = GALETTE_TEMPIMAGES_PATH . 'ajax_upload_' . $fname;
116
117 $temp = explode('base64,', $post['file']);
118 $raw_file = base64_decode($temp[1]);
119
120 //write temporary file
121 $fp = fopen($tmpname, 'w');
122 fwrite($fp, $raw_file);
123 fclose($fp);
124
125 $adh = new Adherent($this->zdb, (int)$mid);
126
127 $res = $adh->picture->store(
128 array(
129 'name' => $fname,
130 'tmp_name' => $tmpname,
131 'size' => $fsize
132 ),
133 true,
134 $cropping
135 );
136
137 if ($res < 0) {
138 $ret['message'] = $adh->picture->getErrorMessage($res);
139 $this->flash->addMessage(
140 'error_detected',
141 $ret['message']
142 );
143 } else {
144 $ret['result'] = true;
145 $this->flash->addMessage(
146 'success_detected',
147 _T('Member photo has been changed.')
148 );
149 }
150
151 return $this->withJson($response, $ret);
152 }
153
154 /**
155 * Ajax town suggestion
156 *
157 * @param Request $request PSR Request
158 * @param Response $response PSR Response
159 * @param string $term Search term
160 *
161 * @return Response
162 */
163 public function suggestTowns(Request $request, Response $response, string $term): Response
164 {
165 $ret = [];
166
167 try {
168 $select1 = $this->zdb->select(Adherent::TABLE);
169 $select1->columns(['ville_adh']);
170 $select1->where->like('ville_adh', '%' . html_entity_decode($term) . '%');
171
172 $select2 = $this->zdb->select(Adherent::TABLE);
173 $select2->columns(['lieu_naissance']);
174 $select2->where->like('lieu_naissance', '%' . html_entity_decode($term) . '%');
175
176 $select1->combine($select2);
177
178 $select = $this->zdb->sql->select();
179 $select->from(['sub' => $select1])
180 ->order('ville_adh ASCC')
181 ->limit(10);
182
183 $towns = $this->zdb->execute($select);
184
185 $ret['success'] = true;
186 $ret['results'] = [];
187 foreach ($towns as $town) {
188 $ret['results'][] = [
189 'title' => $town->ville_adh
190 ];
191 }
192 } catch (Throwable $e) {
193 Analog::log(
194 'Something went wrong is towns suggestion: ' . $e->getMessage(),
195 Analog::WARNING
196 );
197 throw $e;
198 }
199
200 return $this->withJson($response, $ret);
201 }
202
203 /**
204 * Ajax countries suggestion
205 *
206 * @param Request $request PSR Request
207 * @param Response $response PSR Response
208 * @param string $term Search term
209 *
210 * @return Response
211 */
212 public function suggestCountries(Request $request, Response $response, string $term): Response
213 {
214 $ret = [];
215
216 try {
217 $select = $this->zdb->select(Adherent::TABLE);
218 $select->columns(['pays_adh']);
219 $select->where->like('pays_adh', '%' . html_entity_decode($term) . '%');
220 $select->limit(10);
221 $select->order(['pays_adh ASC']);
222
223 $countries = $this->zdb->execute($select);
224
225 $ret['success'] = true;
226 $ret['results'] = [];
227 foreach ($countries as $country) {
228 $ret['results'][] = [
229 'title' => $country->pays_adh
230 ];
231 }
232 } catch (Throwable $e) {
233 Analog::log(
234 'Something went wrong is countries suggestion: ' . $e->getMessage(),
235 Analog::WARNING
236 );
237 throw $e;
238 }
239
240 return $this->withJson($response, $ret);
241 }
242
243 /**
244 * Telemetry info preview
245 *
246 * @param Request $request PSR Request
247 * @param Response $response PSR Response
248 *
249 * @return Response
250 */
251 public function telemetryInfos(Request $request, Response $response): Response
252 {
253 $telemetry = new Telemetry(
254 $this->zdb,
255 $this->preferences,
256 $this->plugins
257 );
258 $body = $response->getBody();
259 $body->write('<pre>' . json_encode($telemetry->getTelemetryInfos(), JSON_PRETTY_PRINT) . '</pre>');
260 return $response;
261 }
262
263 /**
264 * Send telemetry info
265 *
266 * @param Request $request PSR Request
267 * @param Response $response PSR Response
268 *
269 * @return Response
270 */
271 public function telemetrySend(Request $request, Response $response): Response
272 {
273 $telemetry = new Telemetry(
274 $this->zdb,
275 $this->preferences,
276 $this->plugins
277 );
278 try {
279 $telemetry->send();
280 $message = _T('Telemetry information has been sent. Thank you!');
281 $result = [
282 'success' => true,
283 'message' => $message
284 ];
285 } catch (Throwable $e) {
286 $result = [
287 'success' => false,
288 'message' => $e->getMessage()
289 ];
290 }
291 return $this->withJson($response, $result);
292 }
293
294 /**
295 * Successful telemetry registration
296 *
297 * @param Request $request PSR Request
298 * @param Response $response PSR Response
299 *
300 * @return Response
301 */
302 public function telemetryRegistered(Request $request, Response $response): Response
303 {
304 $this->preferences->pref_registration_date = date('Y-m-d H:i:s');
305 $this->preferences->store();
306 return $this->withJson($response, ['message' => _T('Thank you for registering!')]);
307 }
308
309 /**
310 * Contributions dates
311 *
312 * @param Request $request PSR Request
313 * @param Response $response PSR Response
314 *
315 * @return Response
316 */
317 public function contributionDates(Request $request, Response $response): Response
318 {
319 $post = $request->getParsedBody();
320
321 $contrib = new Contribution(
322 $this->zdb,
323 $this->login,
324 [
325 'type' => (int)$post['fee_id'],
326 'adh' => (int)$post['member_id']
327 ]
328 );
329
330 return $this->withJson(
331 $response,
332 [
333 'date_debut_cotis' => $contrib->begin_date,
334 'date_fin_cotis' => $contrib->end_date
335 ]
336 );
337 }
338
339 /**
340 * Contributions dates
341 *
342 * @param Request $request PSR Request
343 * @param Response $response PSR Response
344 * @param int|null $page Page number
345 * @param string|null $search Search string
346 *
347 * @return Response
348 */
349 public function contributionMembers(Request $request, Response $response, int $page = null, string $search = null): Response
350 {
351 $post = $request->getParsedBody();
352 $filters = new MembersList();
353 if (isset($post['page'])) {
354 $filters->current_page = (int)$post['page'];
355 } elseif ($page !== null) {
356 $filters->current_page = $page;
357 }
358
359 if (isset($post['search'])) {
360 $search = $post['search'];
361 }
362 if ($search !== null) {
363 $filters->filter_str = $search;
364 if (is_numeric($search)) {
365 $filters->field_filter = Members::FILTER_ID;
366 }
367 }
368
369 $m = new Members($filters);
370 $list_members = $m->getDropdownMembers($this->zdb, $this->login);
371
372 $members = [];
373 if (count($list_members) > 0) {
374 foreach ($list_members as $pk => $member) {
375 $members[] = [
376 'name' => $member,
377 'value' => $pk
378 ];
379 }
380 }
381
382 return $this->withJson(
383 $response,
384 [
385 'results' => $members
386 ]
387 );
388 }
389
390 /**
391 * Password strength
392 *
393 * @param Request $request PSR Request
394 * @param Response $response PSR Response
395 *
396 * @return Response
397 */
398 public function passwordStrength(Request $request, Response $response): Response
399 {
400 //post params may be passed from security tab test password
401 $post = $request->getParsedBody();
402
403 if (isset($post['pref_password_length'])) {
404 $this->preferences->pref_password_length = $post['pref_password_length'];
405 }
406
407 if (isset($post['pref_password_strength'])) {
408 $this->preferences->pref_password_strength = $post['pref_password_strength'];
409 }
410
411 if (isset($post['pref_password_blacklist'])) {
412 $this->preferences->pref_password_blacklist = $post['pref_password_blacklist'];
413 }
414
415 $pass = new Password($this->preferences);
416 $valid = $pass->isValid($post['value']);
417
418 return $this->withJson(
419 $response,
420 [
421 'valid' => $valid,
422 'score' => $pass->getStrenght(),
423 'errors' => $pass->getErrors(),
424 'warnings' => ($valid ? $pass->getStrenghtErrors() : null)
425 ]
426 );
427 }
428 }