]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Core/Galette.php
87e0476cd96a582ed984795d79d6015b1317e392
[galette.git] / galette / lib / Galette / Core / Galette.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\Core;
23
24 use Analog\Analog;
25 use Galette\Entity\Adherent;
26 use Galette\Entity\Document;
27 use Galette\Util\Release;
28 use RuntimeException;
29
30 /**
31 * Galette application instance
32 *
33 * @author Johan Cwiklinski <johan@x-tnd.be>
34 */
35 class Galette
36 {
37 public const MODE_PROD = 'PROD';
38 public const MODE_DEV = 'DEV';
39 public const MODE_MAINT = 'MAINT';
40 public const MODE_DEMO = 'DEMO';
41
42 /**
43 * Retrieve Galette version from git, if present.
44 *
45 * @param boolean $time Include time and timezone. Defaults to false.
46 *
47 * @return string
48 */
49 public static function gitVersion(bool $time = false): string
50 {
51 $galette_version = GALETTE_VERSION;
52
53 //used for both git and nightly installs
54 $version = str_replace('-dev', '-git', GALETTE_VERSION);
55 if (strstr($version, '-git') === false) {
56 $version .= '-git';
57 }
58
59 if (is_dir(GALETTE_ROOT . '../.git')) {
60 $commitHash = trim(exec('git log --pretty="%h" -n1 HEAD'));
61
62 $commitDate = new \DateTime(trim(exec('git log -n1 --pretty=%ci HEAD')));
63
64 $galette_version = sprintf(
65 '%s-%s (%s)',
66 $version,
67 $commitHash,
68 $commitDate->format(($time ? 'Y-m-d H:i:s T' : 'Y-m-d'))
69 );
70 } elseif (static::isNightly()) {
71 $galette_version = $version . '-' . GALETTE_NIGHTLY;
72 }
73 return $galette_version;
74 }
75
76 /**
77 * Get Galette new release
78 *
79 * @return array<string, string|array<string,mixed>>
80 */
81 public static function getNewRelease(): array
82 {
83 $release = new Release();
84 return [
85 'new' => $release->checkNewRelease(),
86 'version' => $release->getLatestRelease()
87 ];
88 }
89
90 /**
91 * Get all menus
92 *
93 * @return array<string, string|array<string,mixed>>
94 */
95 public static function getAllMenus(): array
96 {
97 return static::getMenus(true);
98 }
99
100 /**
101 * Get menus
102 *
103 * @param bool $public Include public menus. Defaults to false
104 *
105 * @return array<string, string|array<string,mixed>>
106 */
107 public static function getMenus(bool $public = false): array
108 {
109 /**
110 * @var Login $login
111 * @var Preferences $preferences
112 * @var Plugins $plugins
113 */
114 global $login, $preferences, $plugins;
115
116 $menus = [];
117
118 if ($login->isLogged()) {
119 if (!$login->isSuperAdmin()) {
120 //member menu
121 $menus['myaccount'] = [
122 'title' => _T("My Account"),
123 'icon' => 'user',
124 'items' => [
125 [
126 'label' => _T('My contributions'),
127 'title' => _T('View and filter all my contributions'),
128 'route' => [
129 'name' => 'myContributions',
130 'args' => ['type' => 'contributions']
131 ]
132 ],
133 [
134 'label' => _T('My transactions'),
135 'title' => _T('View and filter all my transactions'),
136 'route' => [
137 'name' => 'myContributions',
138 'args' => ['type' => 'transactions']
139 ]
140 ],
141 [
142 'label' => _T('My information'),
143 'title' => _T('View my member card'),
144 'route' => [
145 'name' => 'me',
146 'args' => []
147 ]
148 ]
149 ]
150 ];
151
152 if ($preferences->pref_bool_create_member) {
153 $menus['myaccount']['items'][] = [
154 'label' => _T('Add a child member'),
155 'title' => _T('Add new child member in database'),
156 'route' => [
157 'name' => 'addMemberChild',
158 'args' => []
159 ]
160 ];
161 }
162 }
163
164 $menus['members'] = [
165 'title' => _T("Members"),
166 'icon' => 'users',
167 'items' => []
168 ];
169
170 if ($login->isAdmin() || $login->isStaff() || $login->isGroupManager()) {
171 $menus['members']['items'] = [
172 [
173 'label' => _T("List of members"),
174 'title' => _T("View, search into and filter member's list"),
175 'route' => [
176 'name' => 'members',
177 'aliases' => ['editMember', 'member']
178 ]
179 ],
180 [
181 'label' => _T("Advanced search"),
182 'title' => _T("Perform advanced search into members list"),
183 'route' => [
184 'name' => 'advanced-search'
185 ]
186 ],
187 [
188 'label' => _T("Saved searches"),
189 'route' => [
190 'name' => 'searches'
191 ]
192 ]
193 ];
194 }
195
196 if (
197 $login->isAdmin()
198 || $login->isStaff()
199 || ($login->isGroupManager() && $preferences->pref_bool_groupsmanagers_create_member)
200 ) {
201 $menus['members']['items'][] = [
202 'label' => _T("Add a member"),
203 'title' => _T("Add new member in database"),
204 'route' => [
205 'name' => 'addMember'
206 ]
207 ];
208 }
209
210 if ($login->isAdmin() || $login->isStaff()) {
211 $menus['contributions'] = [
212 'title' => _T('Contributions'),
213 'icon' => 'receipt',
214 'items' => [
215 [
216 'label' => _T("List of contributions"),
217 'title' => _T("View and filter contributions"),
218 'route' => [
219 'name' => 'contributions',
220 'args' => ['type' => 'contributions'],
221 'aliases' => ['editContribution']
222 ]
223 ],
224 [
225 'label' => _T("List of transactions"),
226 'title' => _T("View and filter transactions"),
227 'route' => [
228 'name' => 'contributions',
229 'args' => ['type' => 'transactions'],
230 'aliases' => ['editTransaction']
231 ]
232 ],
233 [
234 'label' => _T("Add a membership fee"),
235 'title' => _T("Add new membership fee in database"),
236 'route' => [
237 'name' => 'addContribution',
238 'args' => ['type' => \Galette\Entity\Contribution::TYPE_FEE]
239 ]
240 ],
241 [
242 'label' => _T("Add a donation"),
243 'title' => _T("Add new donation in database"),
244 'route' => [
245 'name' => 'addContribution',
246 'args' => ['type' => \Galette\Entity\Contribution::TYPE_DONATION]
247 ]
248 ],
249 [
250 'label' => _T("Add a transaction"),
251 'title' => _T("Add new transaction in database"),
252 'route' => [
253 'name' => 'addTransaction'
254 ]
255 ],
256 [
257 'label' => _T("Reminders"),
258 'title' => _T("Send reminders to late members"),
259 'route' => [
260 'name' => 'reminders'
261 ]
262 ]
263 ]
264 ];
265 } //admin or staff
266
267 if ($login->isAdmin() || $login->isStaff() || $login->isGroupManager()) {
268 $menus['management'] = [
269 'title' => _T("Management"),
270 'icon' => 'dharmachakra',
271 'items' => [
272 [
273 'label' => _T("Manage groups"),
274 'title' => _T("View and manage groups"),
275 'route' => [
276 'name' => 'groups'
277 ]
278 ]
279 ]
280 ];
281
282 if ($login->isAdmin() || $login->isStaff()) {
283 $menus['management']['items'] = array_merge($menus['management']['items'], [
284 [
285 'label' => _T("Logs"),
286 'title' => _T("View application's logs"),
287 'route' => [
288 'name' => 'history'
289 ]
290 ],
291 [
292 'label' => _T("Manage mailings"),
293 'title' => _T("Manage mailings that has been sent"),
294 'route' => [
295 'name' => 'mailings'
296 ]
297 ],
298 [
299 'label' => _T("Exports"),
300 'title' => _T("Export some data in various formats"),
301 'route' => [
302 'name' => 'export'
303 ]
304 ],
305 [
306 'label' => _T("Imports"),
307 'title' => _T("Import members from CSV files"),
308 'route' => [
309 'name' => 'import',
310 'aliases' => ['importModel']
311 ]
312 ],
313 [
314 'label' => _T("Charts"),
315 'title' => _T("Various charts"),
316 'route' => [
317 'name' => 'charts'
318 ]
319 ], [
320 'label' => _T("Documents"),
321 'title' => _T("Add documents to share related to your association (status, rules of procedure, ...)"),
322 'route' => [
323 'name' => 'documentsList',
324 'aliases' => ['editDocument', 'addDocument']
325 ]
326 ]
327 ]);
328 }//admin or staff
329
330 if ($login->isAdmin()) {
331 $menus['configuration'] = [
332 'title' => _T("Configuration"),
333 'icon' => 'tools',
334 'items' => [
335 [
336 'label' => _T("Settings"),
337 'title' => _T("Set applications preferences (address, website, member's cards configuration, ...)"),
338 'route' => [
339 'name' => 'preferences'
340 ]
341 ],
342 [
343 'label' => _T("Plugins"),
344 'title' => _T("Information about available plugins"),
345 'route' => [
346 'name' => 'plugins'
347 ]
348 ],
349 [
350 'label' => _T("Core lists"),
351 'title' => _T("Customize lists fields and order"),
352 'route' => [
353 'name' => 'configureListFields',
354 'args' => ['table' => 'adherents']
355 ]
356 ],
357 [
358 'label' => _T("Core fields"),
359 'title' => _T("Customize fields order, set which are required, and for who they're visibles"),
360 'route' => [
361 'name' => 'configureCoreFields'
362 ]
363 ],
364 [
365 'label' => _T("Dynamic fields"),
366 'title' => _T("Manage additional fields for various forms"),
367 'route' => [
368 'name' => 'configureDynamicFields',
369 'aliases' => ['editDynamicField'],
370 ]
371 ],
372 [
373 'label' => _T("Translate labels"),
374 'title' => _T("Translate additional fields labels"),
375 'route' => [
376 'name' => 'dynamicTranslations'
377 ]
378 ],
379 [
380 'label' => _T("Manage statuses"),
381 'route' => [
382 'name' => 'status',
383 'aliases' => ['editStatus'],
384 'sub_select' => false
385 ]
386 ],
387 [
388 'label' => _T("Contributions types"),
389 'title' => _T("Manage contributions types"),
390 'route' => [
391 'name' => 'contributionsTypes',
392 ]
393 ],
394 [
395 'label' => _T("Emails content"),
396 'title' => _T("Manage emails texts and subjects"),
397 'route' => [
398 'name' => 'texts'
399 ]
400 ],
401 [
402 'label' => _T("Titles"),
403 'title' => _T("Manage titles"),
404 'route' => [
405 'name' => 'titles',
406 'aliases' => ['editTitle']
407 ]
408 ],
409 [
410 'label' => _T("PDF models"),
411 'title' => _T("Manage PDF models"),
412 'route' => [
413 'name' => 'pdfModels'
414 ]
415 ],
416 [
417 'label' => _T("Payment types"),
418 'title' => _T("Manage payment types"),
419 'route' => [
420 'name' => 'paymentTypes',
421 'aliases' => ['editPaymentType']
422 ]
423 ],
424 [
425 'label' => _T("Empty adhesion form"),
426 'title' => _T("Download empty adhesion form"),
427 'route' => [
428 'name' => 'emptyAdhesionForm'
429 ]
430 ]
431 ]
432 ];
433
434 if ($login->isSuperAdmin()) {
435 $menus['configuration']['items'][] = [
436 'label' => _T("Admin tools"),
437 'title' => _T("Various administrative tools"),
438 'route' => [
439 'name' => 'adminTools'
440 ]
441 ];
442 }
443 }
444 }
445 } // /isLogged
446
447 foreach (array_keys($plugins->getModules()) as $module_id) {
448 //get plugins menus entries
449 $plugin_class = $plugins->getClassName($module_id, true);
450 if (class_exists($plugin_class)) {
451 $plugin = new $plugin_class();
452 $menus = array_merge_recursive(
453 $menus,
454 $plugin->getMenus()
455 );
456 }
457 }
458
459 if ($public) {
460 $menus += static::getPublicMenus();
461 }
462
463 //cleanup empty entries (no items)
464 foreach ($menus as $key => $menu) {
465 if (!count($menu['items'])) {
466 unset($menus[$key]);
467 }
468 }
469
470 return $menus;
471 }
472
473 /**
474 * Get public menus
475 *
476 * @return array<string, string|array<string,mixed>>
477 */
478 public static function getPublicMenus(): array
479 {
480 /**
481 * @var Preferences $preferences
482 * @var Login $login
483 * @var Plugins $plugins
484 */
485 global $preferences, $login, $plugins, $zdb;
486
487 $menus = [];
488 if ($preferences->showPublicPages($login)) {
489 $menus['public'] = [
490 'title' => _T("Public pages"),
491 'icon' => 'eye outline',
492 'items' => [
493 [
494 'label' => _T("Members list"),
495 'route' => [
496 'name' => 'publicList',
497 'args' => ['type' => 'list']
498 ],
499 'icon' => 'address book'
500 ],
501 [
502 'label' => _T("Trombinoscope"),
503 'route' => [
504 'name' => 'publicList',
505 'args' => ['type' => 'trombi']
506 ],
507 'icon' => 'user friends'
508 ]
509 ]
510 ];
511
512 //display documents menu if at least one document is present with current ACLs
513 $document = new Document($zdb);
514 $documents = $document->getList();
515 if ($login->isSuperAdmin() || count($documents)) {
516 $menus['public']['items'][] = [
517 'label' => _T("Documents"),
518 'title' => _T("View documents related to your association"),
519 'route' => [
520 'name' => 'documentsPublicList'
521 ],
522 'icon' => 'file alternate'
523 ];
524 }
525
526 foreach (array_keys($plugins->getModules()) as $module_id) {
527 //get plugins public menus entries
528 $plugin_class = $plugins->getClassName($module_id, true);
529 if (class_exists($plugin_class)) {
530 $plugin = new $plugin_class();
531 $menus['public']['items'] = array_merge(
532 $menus['public']['items'],
533 $plugin->getPublicMenuItems()
534 );
535 }
536 }
537 }
538
539 return $menus;
540 }
541
542 /**
543 * Get dashboards
544 *
545 * @return array<string, string|array<string,mixed>>
546 */
547 public static function getDashboards(): array
548 {
549 /**
550 * @var Login $login
551 * @var Plugins $plugins
552 * @var Db $zdb
553 */
554 global $login, $plugins, $zdb;
555
556 $dashboards = [];
557
558 if ($login->isAdmin() || $login->isStaff() || $login->isGroupManager()) {
559 $dashboards = array_merge(
560 $dashboards,
561 [
562 [
563 'label' => _T("Members"),
564 'title' => _T("View, search into and filter member's list"),
565 'route' => [
566 'name' => 'members'
567 ],
568 'icon' => 'card_box'
569 ],
570 [
571 'label' => _T("Groups"),
572 'title' => _T("View and manage groups"),
573 'route' => [
574 'name' => 'groups'
575 ],
576 'icon' => 'busts_in_silhouette'
577 ],
578 ]
579 );
580 }
581
582 if ($login->isAdmin() || $login->isStaff()) {
583 $dashboards = array_merge(
584 $dashboards,
585 [
586 [
587 'label' => _T("Mailings"),
588 'title' => _T("Manage mailings that has been sent"),
589 'route' => [
590 'name' => 'mailings'
591 ],
592 'icon' => 'postbox'
593 ],
594 [
595 'label' => _T("Contributions"),
596 'title' => _T("View and filter contributions"),
597 'route' => [
598 'name' => 'contributions',
599 'args' => ['type' => 'contributions']
600 ],
601 'icon' => 'receipt'
602 ],
603 [
604 'label' => _T("Transactions"),
605 'title' => _T("View and filter transactions"),
606 'route' => [
607 'name' => 'contributions',
608 'args' => ['type' => 'transactions']
609 ],
610 'icon' => 'book'
611 ],
612 [
613 'label' => _T("Reminders"),
614 'title' => _T("Send reminders to late members"),
615 'route' => [
616 'name' => 'reminders'
617 ],
618 'icon' => 'bell'
619 ],
620 ]
621 );
622 }
623
624 //display documents menu if at least one document is present with current ACLs
625 $document = new Document($zdb);
626 $documents = $document->getList();
627 if ($login->isSuperAdmin() || count($documents)) {
628 $dashboards = array_merge(
629 $dashboards,
630 [
631 [
632 'label' => _T("Documents"),
633 'title' => _T("View documents related to your association"),
634 'route' => [
635 'name' => 'documentsPublicList'
636 ],
637 'icon' => 'dividers'
638 ]
639 ]
640 );
641 }
642
643 if ($login->isAdmin()) {
644 $dashboards = array_merge(
645 $dashboards,
646 [
647 [
648 'label' => _T("Settings"),
649 'title' => _T("Set applications preferences (address, website, member's cards configuration, ...)"),
650 'route' => [
651 'name' => 'preferences'
652 ],
653 'icon' => 'control_knobs'
654 ],
655 [
656 'label' => _T("Plugins"),
657 'title' => _T("Information about available plugins"),
658 'route' => [
659 'name' => 'plugins'
660 ],
661 'icon' => 'package'
662 ],
663 ]
664 );
665 }
666
667 if ($login->isLogged() && !$login->isSuperAdmin()) {
668 // Single member
669 $dashboards = array_merge(
670 $dashboards,
671 [
672 [
673 'label' => _T("My information"),
674 'title' => _T("View my member card"),
675 'route' => [
676 'name' => 'me'
677 ],
678 'icon' => 'bust_in_silhouette'
679 ],
680 [
681 'label' => _T("My contributions"),
682 'title' => _T("View and filter all my contributions"),
683 'route' => [
684 'name' => 'myContributions',
685 'args' => ['type' => 'contributions']
686 ],
687 'icon' => 'receipt'
688 ],
689 [
690 'label' => _T("My transactions"),
691 'title' => _T("View and filter all my transactions"),
692 'route' => [
693 'name' => 'myContributions',
694 'args' => ['type' => 'transactions']
695 ],
696 'icon' => 'book'
697 ]
698 ]
699 );
700 }
701
702 foreach (array_keys($plugins->getModules()) as $module_id) {
703 //get plugins menus entries
704 $plugin_class = $plugins->getClassName($module_id, true);
705 if (class_exists($plugin_class)) {
706 /** @var GalettePlugin $plugin */
707 $plugin = new $plugin_class();
708 $dashboards = array_merge_recursive(
709 $dashboards,
710 $plugin->getDashboards()
711 );
712 }
713 }
714
715 return $dashboards;
716 }
717
718 /**
719 * Get members list actions
720 *
721 * @param Adherent $member Current member
722 *
723 * @return array<string, string|array<string,mixed>>
724 */
725 public static function getListActions(Adherent $member): array
726 {
727 /**
728 * @var Login $login
729 * @var Plugins $plugins
730 */
731 global $login, $plugins;
732
733 $actions = [];
734
735 if ($member->canEdit($login)) {
736 $actions[] = [
737 'label' => str_replace(
738 "%membername",
739 $member->sname,
740 _T("%membername: edit information")
741 ),
742 'title' => str_replace(
743 "%membername",
744 $member->sname,
745 _T("%membername: edit information")
746 ),
747 'route' => [
748 'name' => 'editMember',
749 'args' => ['id' => $member->id]
750 ],
751 'icon' => 'user edit'
752 ];
753 }
754
755 if ($login->isAdmin() || $login->isStaff()) {
756 $actions = array_merge($actions, [
757 [
758 'label' => str_replace(
759 "%membername",
760 $member->sname,
761 _T("%membername: contributions")
762 ),
763 'title' => str_replace(
764 "%membername",
765 $member->sname,
766 _T("%membername: contributions")
767 ),
768 'route' => [
769 'name' => 'contributions',
770 'args' => [
771 "type" => "contributions",
772 "option" => "member",
773 'value' => $member->id
774 ]
775 ],
776 'icon' => 'receipt green'
777 ],
778 [
779 'label' => str_replace(
780 "%membername",
781 $member->sname,
782 _T("%membername: remove from database")
783 ),
784 'title' => str_replace(
785 "%membername",
786 $member->sname,
787 _T("%membername: remove from database")
788 ),
789 'route' => [
790 'name' => 'removeMember',
791 'args' => [
792 'id' => $member->id
793 ]
794 ],
795 'icon' => 'user times red',
796 'extra_class' => 'delete'
797 ]
798 ]);
799 }
800
801 if ($login->isSuperAdmin()) {
802 $actions[] = [
803 'label' => str_replace(
804 "%membername",
805 $member->sname,
806 _T("Log in in as %membername")
807 ),
808 'title' => str_replace(
809 "%membername",
810 $member->sname,
811 _T("Log in in as %membername")
812 ),
813 'route' => [
814 'name' => 'impersonate',
815 'args' => [
816 'id' => $member->id
817 ]
818 ],
819 'icon' => 'user secret grey'
820 ];
821 }
822
823 foreach (array_keys($plugins->getModules()) as $module_id) {
824 //get plugins menus entries
825 $plugin_class = $plugins->getClassName($module_id, true);
826 if (class_exists($plugin_class)) {
827 /** @var GalettePlugin $plugin */
828 $plugin = new $plugin_class();
829 $actions = array_merge_recursive(
830 $actions,
831 $plugin->getListActions($member)
832 );
833 }
834 }
835 return $actions;
836 }
837
838 /**
839 * Get member show actions
840 *
841 * @param Adherent $member Current member
842 *
843 * @return array<string, string|array<string,mixed>>
844 */
845 public static function getDetailedActions(Adherent $member): array
846 {
847 /**
848 * @var Login $login
849 * @var Plugins $plugins
850 */
851 global $login, $plugins;
852
853 $actions = [];
854
855 //TODO: add core detailed actions
856
857 foreach (array_keys($plugins->getModules()) as $module_id) {
858 //get plugins menus entries
859 $plugin_class = $plugins->getClassName($module_id, true);
860 if (class_exists($plugin_class)) {
861 /** @var GalettePlugin $plugin */
862 $plugin = new $plugin_class();
863 $actions = array_merge_recursive(
864 $actions,
865 $plugin->getDetailedActions($member)
866 );
867 }
868 }
869 return $actions;
870 }
871
872 /**
873 * Get members list batch actions
874 *
875 * @return array<string,array<string, string>>
876 */
877 public static function getBatchActions(): array
878 {
879 /**
880 * @var Login $login
881 * @var Plugins $plugins
882 * @var Preferences $preferences
883 */
884 global $login, $plugins, $preferences;
885
886 $actions = [];
887
888 if (
889 $login->isAdmin()
890 || $login->isStaff()
891 ) {
892 $actions = array_merge(
893 $actions,
894 [
895 [
896 'name' => 'masschange',
897 'label' => _T('Mass change'),
898 'icon' => 'user edit blue'
899 ],
900 [
901 'name' => 'masscontributions',
902 'label' => _T('Mass add contributions'),
903 'icon' => 'receipt bite green'
904 ],
905 [
906 'name' => 'delete',
907 'label' => _T('Delete'),
908 'icon' => 'user times red'
909 ]
910 ]
911 );
912 }
913
914 if (
915 ($login->isAdmin()
916 || $login->isStaff()
917 || $login->isGroupManager()
918 && $preferences->pref_bool_groupsmanagers_mailings)
919 && $preferences->pref_mail_method != \Galette\Core\GaletteMail::METHOD_DISABLED
920 ) {
921 $actions[] = [
922 'name' => 'sendmail',
923 'label' => _T('Mail'),
924 'icon' => 'mail bulk'
925 ];
926 }
927
928 if (
929 $login->isGroupManager()
930 && $preferences->pref_bool_groupsmanagers_exports
931 || $login->isAdmin()
932 || $login->isStaff()
933 ) {
934 $actions = array_merge(
935 $actions,
936 [
937 [
938 'name' => 'attendance_sheet',
939 'label' => _T('Attendance sheet'),
940 'icon' => 'file alternate'
941 ],
942 [
943 'name' => 'labels__directdownload',
944 'label' => _T('Generate labels'),
945 'icon' => 'address card'
946 ],
947 [
948 'name' => 'cards__directdownload',
949 'label' => _T('Generate Member Cards'),
950 'icon' => 'id badge'
951 ],
952 [
953 'name' => 'csv__directdownload',
954 'label' => _T('Export as CSV'),
955 'icon' => 'file csv'
956 ],
957 ]
958 );
959 }
960
961 foreach (array_keys($plugins->getModules()) as $module_id) {
962 //get plugins menus entries
963 $plugin_class = $plugins->getClassName($module_id, true);
964 if (class_exists($plugin_class)) {
965 /** @var GalettePlugin $plugin */
966 $plugin = new $plugin_class();
967 $actions = array_merge_recursive(
968 $actions,
969 $plugin->getBatchActions()
970 );
971 }
972 }
973 return $actions;
974 }
975
976 /**
977 * Is demonstration mode enabled
978 *
979 * @return bool
980 */
981 public static function isDemo(): bool
982 {
983 return GALETTE_MODE === static::MODE_DEMO;
984 }
985
986 /**
987 * Is debug mode enabled
988 *
989 * @return bool
990 */
991 public static function isDebugEnabled(): bool
992 {
993 if (GALETTE_MODE === static::MODE_DEV) {
994 //since 1.1.0, GALETTE_MODE with DEV value is deprecated.
995 Analog::log(
996 'Using GALETTE_MODE set to DEV is deprecated. Use GALETTE_DEBUG.',
997 Analog::WARNING
998 );
999 return true;
1000 }
1001 // @const bool GALETTE_DEBUG
1002 return GALETTE_DEBUG === true;
1003 }
1004
1005 /**
1006 * Is SQL debug mode enabled
1007 *
1008 * @return bool
1009 */
1010 public static function isSqlDebugEnabled(): bool
1011 {
1012 return defined('GALETTE_SQL_DEBUG') || static::isDebugEnabled();
1013 }
1014
1015 /**
1016 * Is a nightly build
1017 *
1018 * @return bool
1019 */
1020 public static function isNightly(): bool
1021 {
1022 return GALETTE_NIGHTLY !== false;
1023 }
1024
1025 /**
1026 * Check if a string is serialized
1027 *
1028 * @param string $string String to check
1029 *
1030 * @return bool
1031 */
1032 public static function isSerialized(string $string): bool
1033 {
1034 return (@unserialize($string) !== false);
1035 }
1036
1037 /**
1038 * JSON decode with exception
1039 *
1040 * @param string $string JSON encoded string to decode
1041 *
1042 * @return array<string|int, mixed>
1043 * @throws RuntimeException
1044 */
1045 public static function jsonDecode(string $string): array
1046 {
1047 $decoded = json_decode($string, true);
1048 if (json_last_error() !== JSON_ERROR_NONE) {
1049 throw new RuntimeException('JSON decode error: ' . json_last_error_msg());
1050 }
1051
1052 return $decoded;
1053 }
1054
1055 /**
1056 * JSON encode with exception
1057 *
1058 * @param array<string|int, mixed>|object $data Data to encode
1059 *
1060 * @return string
1061 * @throws RuntimeException
1062 */
1063 public static function jsonEncode(array|object $data): string
1064 {
1065 $encoded = json_encode($data);
1066 if (json_last_error() !== JSON_ERROR_NONE) {
1067 throw new RuntimeException('JSON encode error: ' . json_last_error_msg());
1068 }
1069
1070 return $encoded;
1071 }
1072 }