3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
6 * Galette ajax controller
10 * Copyright © 2023 The Galette Team
12 * This file is part of Galette (http://galette.tuxfamily.org).
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.
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.
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/>.
27 * @category Controllers
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
37 namespace Galette\Controllers
;
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
;
51 * Galette ajax controller
53 * @category Controllers
54 * @name GaletteController
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
63 class AjaxController
extends AbstractController
66 * Messages as JSON array
68 * @param Request $request PSR Request
69 * @param Response $response PSR Response
73 public function messages(Request
$request, Response
$response): Response
77 $errors = $this->flash
->getMessage('loginfault') ??
[];
78 $errors = array_merge($errors, $this->flash
->getMessage('error_detected') ??
[]);
79 $errors = array_merge($errors, $this->flash
->getMessage('error') ??
[]);
81 if (count($errors) > 0) {
82 $messages['error'] = [
83 'title' => _T('- ERROR -'),
84 'icon' => 'exclamation circle',
89 $warnings = $this->flash
->getMessage('warning_detected') ??
[];
90 $warnings = array_merge($warnings, $this->flash
->getMessage('warning') ??
[]);
92 if (count($warnings) > 0) {
93 $messages['warning'] = [
94 'title' => _T('- WARNING -'),
95 'icon' => 'exclamation triangle',
96 'messages' => $warnings
100 $info = $this->flash
->getMessage('info_detected') ??
[];
101 $info = array_merge($info, $this->flash
->getMessage('info') ??
[]);
103 if (count($info) > 0) {
104 $messages['info'] = [
111 $success = $this->flash
->getMessage('success_detected') ??
[];
112 $success = array_merge($success, $this->flash
->getMessage('succes') ??
[]);
114 if (count($success) > 0) {
115 $messages['success'] = [
117 'icon' => 'check circle outline',
118 'messages' => $success
122 return $this->withJson($response, $messages);
126 * Ajax Drag'N'Drop photo
128 * @param Request $request PSR Request
129 * @param Response $response PSR Response
133 public function photo(Request
$request, Response
$response): Response
135 $post = $request->getParsedBody();
136 $ret = ['result' => false];
139 !isset($post['member_id'])
140 ||
!isset($post['file'])
141 ||
!isset($post['filename'])
142 ||
!isset($post['filesize'])
144 $this->flash
->addMessage(
146 _T("Required argument not present!")
148 return $this->withJson($response, $ret);
151 $mid = $post['member_id'];
152 $fsize = $post['filesize'];
153 $fname = $post['filename'];
155 if ($post['cropping'] != false) {
156 $cropping = $post['cropping'];
158 $tmpname = GALETTE_TEMPIMAGES_PATH
. 'ajax_upload_' . $fname;
160 $temp = explode('base64,', $post['file']);
161 $raw_file = base64_decode($temp[1]);
163 //write temporary file
164 $fp = fopen($tmpname, 'w');
165 fwrite($fp, $raw_file);
168 $adh = new Adherent($this->zdb
, (int)$mid);
170 $res = $adh->picture
->store(
173 'tmp_name' => $tmpname,
181 $ret['message'] = $adh->picture
->getErrorMessage($res);
182 $this->flash
->addMessage(
187 $ret['result'] = true;
188 $this->flash
->addMessage(
190 _T('Member photo has been changed.')
194 return $this->withJson($response, $ret);
198 * Ajax town suggestion
200 * @param Request $request PSR Request
201 * @param Response $response PSR Response
202 * @param string $term Search term
206 public function suggestTowns(Request
$request, Response
$response, string $term): Response
211 $select1 = $this->zdb
->select(Adherent
::TABLE
);
212 $select1->columns(['ville_adh']);
213 $select1->where
->like('ville_adh', '%' . html_entity_decode($term) . '%');
215 $select2 = $this->zdb
->select(Adherent
::TABLE
);
216 $select2->columns(['lieu_naissance']);
217 $select2->where
->like('lieu_naissance', '%' . html_entity_decode($term) . '%');
219 $select1->combine($select2);
221 $select = $this->zdb
->sql
->select();
222 $select->from(['sub' => $select1])
223 ->order('ville_adh ASCC')
226 $towns = $this->zdb
->execute($select);
228 $ret['success'] = true;
229 $ret['results'] = [];
230 foreach ($towns as $town) {
231 $ret['results'][] = [
232 'title' => $town->ville_adh
235 } catch (Throwable
$e) {
237 'Something went wrong is towns suggestion: ' . $e->getMessage(),
243 return $this->withJson($response, $ret);
247 * Ajax countries suggestion
249 * @param Request $request PSR Request
250 * @param Response $response PSR Response
251 * @param string $term Search term
255 public function suggestCountries(Request
$request, Response
$response, string $term): Response
260 $select = $this->zdb
->select(Adherent
::TABLE
);
261 $select->columns(['pays_adh']);
262 $select->where
->like('pays_adh', '%' . html_entity_decode($term) . '%');
264 $select->order(['pays_adh ASC']);
266 $countries = $this->zdb
->execute($select);
268 $ret['success'] = true;
269 $ret['results'] = [];
270 foreach ($countries as $country) {
271 $ret['results'][] = [
272 'title' => $country->pays_adh
275 } catch (Throwable
$e) {
277 'Something went wrong is countries suggestion: ' . $e->getMessage(),
283 return $this->withJson($response, $ret);
287 * Telemetry info preview
289 * @param Request $request PSR Request
290 * @param Response $response PSR Response
294 public function telemetryInfos(Request
$request, Response
$response): Response
296 $telemetry = new Telemetry(
301 $body = $response->getBody();
302 $body->write('<pre>' . json_encode($telemetry->getTelemetryInfos(), JSON_PRETTY_PRINT
) . '</pre>');
307 * Send telemetry info
309 * @param Request $request PSR Request
310 * @param Response $response PSR Response
314 public function telemetrySend(Request
$request, Response
$response): Response
316 $telemetry = new Telemetry(
323 $message = _T('Telemetry information has been sent. Thank you!');
326 'message' => $message
328 } catch (Throwable
$e) {
331 'message' => $e->getMessage()
334 return $this->withJson($response, $result);
338 * Successful telemetry registration
340 * @param Request $request PSR Request
341 * @param Response $response PSR Response
345 public function telemetryRegistered(Request
$request, Response
$response): Response
347 $this->preferences
->pref_registration_date
= date('Y-m-d H:i:s');
348 $this->preferences
->store();
349 return $this->withJson($response, ['message' => _T('Thank you for registering!')]);
353 * Contributions dates
355 * @param Request $request PSR Request
356 * @param Response $response PSR Response
360 public function contributionDates(Request
$request, Response
$response): Response
362 $post = $request->getParsedBody();
364 $contrib = new Contribution(
368 'type' => (int)$post['fee_id'],
369 'adh' => (int)$post['member_id']
373 return $this->withJson(
376 'date_debut_cotis' => $contrib->begin_date
,
377 'date_fin_cotis' => $contrib->end_date
383 * Contributions dates
385 * @param Request $request PSR Request
386 * @param Response $response PSR Response
387 * @param int|null $page Page number
388 * @param string|null $search Search string
392 public function contributionMembers(Request
$request, Response
$response, int $page = null, string $search = null): Response
394 $post = $request->getParsedBody();
395 $filters = new MembersList();
396 if (isset($post['page'])) {
397 $filters->current_page
= (int)$post['page'];
398 } elseif ($page !== null) {
399 $filters->current_page
= $page;
402 if (isset($post['search'])) {
403 $search = $post['search'];
405 if ($search !== null) {
406 $filters->filter_str
= $search;
407 if (is_numeric($search)) {
408 $filters->field_filter
= Members
::FILTER_ID
;
412 $m = new Members($filters);
413 $list_members = $m->getDropdownMembers($this->zdb
, $this->login
);
416 if (count($list_members) > 0) {
417 foreach ($list_members as $pk => $member) {
425 return $this->withJson(
428 'results' => $members
436 * @param Request $request PSR Request
437 * @param Response $response PSR Response
441 public function passwordStrength(Request
$request, Response
$response): Response
443 //post params may be passed from security tab test password
444 $post = $request->getParsedBody();
446 if (isset($post['pref_password_length'])) {
447 $this->preferences
->pref_password_length
= $post['pref_password_length'];
450 if (isset($post['pref_password_strength'])) {
451 $this->preferences
->pref_password_strength
= $post['pref_password_strength'];
454 if (isset($post['pref_password_blacklist'])) {
455 $this->preferences
->pref_password_blacklist
= $post['pref_password_blacklist'];
458 $pass = new Password($this->preferences
);
459 $valid = $pass->isValid($post['value']);
461 return $this->withJson(
465 'score' => $pass->getStrenght(),
466 'errors' => $pass->getErrors(),
467 'warnings' => ($valid ?
$pass->getStrenghtErrors() : null)