Compare commits

...

456 Commits

Author SHA1 Message Date
20c09d8b0a 1.14.04 Fix methode name usersReportExport 2024-10-21 21:20:09 +02:00
4c88d7a71d Revert "Fix bug parametre de langue inutile dans RFM"
This reverts commit 889e2754fc.
2024-10-20 16:13:29 +02:00
bb9b8b086f 1.14.03 et non 1.14.04 2024-10-20 16:10:04 +02:00
61752a9a51 Optimisation récupérationstatistiques individuelle, la méthode getReports peut retourner les stats d'un utilisateur 2024-10-20 16:07:58 +02:00
889e2754fc Fix bug parametre de langue inutile dans RFM 2024-10-20 16:06:56 +02:00
77b241c69f 1.14.04 TEST Empêche qu'un espace réservé aux membres ne reste ouvert après une déconnexion de la session 2024-10-17 10:40:50 +02:00
442b84a99d Commente un test de validation de la consultation d'un espace 2024-10-16 12:27:32 +02:00
09f9f6bdd6 Optimisation setData 2024-10-12 11:16:44 +02:00
5eace20e26 Fix position d'un bouton 2024-10-12 11:10:58 +02:00
18df3848f8 Update Blog and News 2024-10-12 11:02:08 +02:00
7b9d145533 supprime console.log 2024-10-12 08:15:54 +02:00
75ad5853cf 1.14.03 fix subword 2024-10-10 19:59:53 +02:00
7862815f1f 1.14.02 Module blog bug de présentation, version 7.12 2024-10-08 15:23:51 +02:00
a87d439282 fix update store 2024-10-03 12:01:59 +02:00
509c1d6365 Bug de changement de mot de passe 2024-10-02 19:00:05 +02:00
e641ec1c03 Fix module checkup 2024-10-02 12:40:51 +02:00
3dec8a8ce5 Points virgules !! 2024-10-02 12:18:36 +02:00
54f0b0c6e3 redondance de déclaration de charset 2024-10-02 12:12:52 +02:00
931e59db2e Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCampus 2024-10-02 11:54:16 +02:00
cae0e6c8fb fix reset password key check 2024-10-02 11:54:11 +02:00
afee77b1e7 fix reset password key check 2024-10-02 11:50:19 +02:00
cf8963248e Merge branch 'reste_user_message' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCampus into reste_user_message 2024-10-02 07:56:09 +02:00
22af8ac751 message rest password 2024-10-02 07:56:04 +02:00
2d4385f038 :q 2024-10-02 07:52:40 +02:00
c4bb124bea Init 2024-09-30 19:22:08 +02:00
a474a41402 init 2024-09-30 18:50:31 +02:00
e9f65a1e22 Bug de connexion quand le site est à la racine 2024-09-30 15:38:15 +02:00
8183b0bb0b Install optimisation config 2024-09-29 18:55:30 +02:00
585c888007 supprime un log 2024-09-29 16:00:58 +02:00
d0997ccbf9 Version 1.13.00 2024-09-29 14:17:19 +02:00
1a6bfab54b Supprimer les traceurs de process de stockage 2024-09-29 14:12:32 +02:00
23f38a606f Forçage inutile 2024-09-28 18:34:10 +02:00
f1e1989c97 Corrections Rémi, optimisations 2024-09-28 17:54:05 +02:00
9bb5793720 save = false and saveDB 2024-09-28 15:34:00 +02:00
64443322a0 Merge branch 'master' into write_process 2024-09-28 13:32:46 +02:00
76258c835f 1.12.00.16 restaure l'onglet étiquette dans la configuration 2024-09-28 13:30:48 +02:00
dc81614114 init WIP 2024-09-28 13:24:55 +02:00
8dc1adc28a 1.12.00.15 Position d'un bouton de la vlidation dans la configuration 2024-09-27 10:25:20 +02:00
65eac4ac4a 1.12.00.14 user vide écrit au logout 2024-09-26 19:58:00 +02:00
a8f70dc73a suscribe 2.3 2024-09-26 19:42:24 +02:00
02aeb6ec22 readme 2024-09-26 14:25:19 +02:00
5bdb38dfec Message modification tag(s) 2024-09-26 10:54:13 +02:00
5700200bc3 erreur de commentaire 2024-09-26 10:51:19 +02:00
4ffca0e34a 1.12.00.13 bug initialisation et content dans le script RFM 2024-09-26 10:42:30 +02:00
f4553110e1 1.12.00.12 inverse la position des icones users et config 2024-09-19 10:52:07 +02:00
bf3b1f9cb0 suscribe 2.2 enum 2024-09-19 10:47:20 +02:00
05d8ae9e0b 1.12.00.11 empêche la saisie des caractères interdits lors de l'auto inscription dans le champ id du login 2024-09-19 10:43:24 +02:00
6128d0778d 2.2 register 2024-09-19 10:41:32 +02:00
c38bd7d12f 1.12.00.10 Erreur d'initialisation 2024-09-19 09:59:59 +02:00
cd509dfcb1 Suppression du cookie configLayout 2024-09-18 19:33:59 +02:00
5ab8efe72e 1.12.00.09 supprime le cookie pageLayout 2024-09-18 19:01:44 +02:00
6cf6a8d6b2 numéro de version 2024-09-18 10:19:05 +02:00
daaf309b4d Numero de version 2024-09-18 10:17:46 +02:00
2d5c395aec numérotation et changes 2024-09-17 19:14:03 +02:00
5d5b1e3140 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCampus 2024-09-17 19:05:27 +02:00
8aa24e50ab 1.12.08 empêche la déconnexion après la modification du compte connecté 2024-09-17 19:05:21 +02:00
8574970bb0 1.12.08 corrige l'affichage des flèches de navigation dans les vues des modules 2024-09-17 18:23:32 +02:00
89e6e12748 1.12.08 supprime le cookie relatif au contenu de site sans passer par main.php 2024-09-17 17:52:57 +02:00
9234b76062 1.12.08 change 2024-09-16 23:42:58 +02:00
08c1619162 1.12.08 suppression du cookie ZWII_SITE_CONTENT 2024-09-16 23:40:59 +02:00
576f349b4a changes 2024-09-16 23:01:40 +02:00
be6eaa748e 1.12.07 la clé n'a pas été déclarée 2024-09-16 22:55:58 +02:00
1dc7b08d2e 1.12.06 Index correct 2024-09-16 21:24:17 +02:00
35521766cd 1.12.06 Chemin du cookie de session 2024-09-16 21:20:35 +02:00
c8ee063963 1.12.05 modification du cookie de consentement 2024-09-15 19:00:40 +02:00
f0aba44ddb 1.12.05 icone plugin rouge si module mis à jour 2024-09-15 17:54:25 +02:00
e6236e5de2 readme 2024-09-09 20:55:20 +02:00
e5629de660 1.12.04 Complète l'ide de site avec le chemin 2024-09-08 15:00:06 +02:00
92d3da27a3 1.12.03 2024-09-07 18:17:24 +02:00
1fd0c5492f 1.12.03 bouton de génération du sitemap 2024-09-07 14:25:47 +02:00
bab06033ed 1.11.03 bloque les bots sauf les moteurs 2024-09-07 14:12:22 +02:00
f7cf0f94fc Search 3.3 une seule lecture de module 2024-09-07 09:53:54 +02:00
c244651b62 readme ! 2024-09-07 08:53:38 +02:00
beb58da3bd rfm thumb config 2024-09-07 08:18:40 +02:00
8756162428 1.12.01 default RFM thumb size 2024-09-07 08:11:24 +02:00
511a6ff0bb csrf key sur 64 octets 2024-09-06 17:18:17 +02:00
4175ff828d 1.12.00 Méthode d'authentification 2024-09-06 17:16:04 +02:00
087b5d9999 1.11.01 isole la session dans l'onglet 2024-09-06 09:35:12 +02:00
fea1c40a4b Bug datatables ajout dans user 2024-09-06 09:08:21 +02:00
2dce24f9f2 Bug datatables 2024-09-06 09:06:52 +02:00
0e0fd23913 version 1.11.00 2024-09-06 08:39:12 +02:00
0eab6c9049 1.11.02 datables.net filtrage des éléments, nombre d'éléments et position sur l'écran 2024-09-06 08:35:25 +02:00
ca7ce4e857 1.11.01 bouton décalé 2024-09-05 10:51:06 +02:00
510afbe8f1 1.11.01 le template file affiche le dossier du fichier ou de l'image sélectionnée 2024-09-05 10:31:35 +02:00
c89a64ca7f readme 2024-09-05 08:28:51 +02:00
9280d59aac readme 2024-09-05 08:24:33 +02:00
3accdc135b readme 2024-09-05 08:23:50 +02:00
3d31ce5e55 Libellés 2024-09-05 08:05:57 +02:00
8c60eba918 Icônes tag + design et zones d' aide 2024-09-04 20:28:43 +02:00
b182c2ec90 Titre de la page d'export 2024-09-04 20:21:42 +02:00
523f30027a Position des boutons selectall et selectnone dans le filtre 2024-09-04 20:06:36 +02:00
f9faaa651e Design gestion des tags 2024-09-04 19:26:29 +02:00
1aca92b1c7 Edition des tags 2024-09-04 18:03:50 +02:00
4444c58902 Amélioration esthétique 2024-09-04 09:34:10 +02:00
75dbae7cc6 commentaire et renomme resource 2024-09-04 09:27:27 +02:00
79e0ac2a38 Droits du profil associés à l'export 2024-09-04 09:19:17 +02:00
1cb4b191bf Formatage du code 2024-09-04 08:48:36 +02:00
485392e772 Optimisation de l'export 2024-09-04 08:48:10 +02:00
9c5f6448b1 Bug export 2024-09-04 08:30:38 +02:00
b78e52c5d4 course export Boutons tout et rien sélectionner
Portée sélection excluant les barres
2024-09-04 08:25:10 +02:00
e687f26d2d Tri des pages selon la position 2024-09-03 21:38:12 +02:00
769808ca4e Version 1.11.00 2024-09-03 19:05:00 +02:00
5ba20aec09 Pointer RFM sur le dossier de l'espace 2024-09-03 19:04:37 +02:00
5c0efda0ca Page manage, RFM pointe sur le dossier de l'espace 2024-09-03 19:02:02 +02:00
b6d3eb8ec2 Export du coentnu html ok 2024-09-03 18:54:41 +02:00
30df948d81 1.10.16 suppression de compte en masse, protection du compte connecté 2024-09-02 21:44:39 +02:00
15430af1d6 1.10.15 warning à la création d'une nouvelle page 2024-08-29 06:45:43 +02:00
2aae298d7d Revert plugin 2024-08-28 21:17:10 +02:00
adeaeb624b 1.10.14 catalogue parfois vide, erreur d'url, slash en fin d'adresse 2024-08-28 21:01:31 +02:00
d98e235dfc 1.10.13 Login, connexion persistante 2024-08-24 17:29:13 +02:00
ef5de018b0 1.10.12 fix bug mot clé [MODULE] absent 2024-08-24 07:20:17 +02:00
c024340af7 suprime un commentaire 2024-08-23 21:19:30 +02:00
6a964938bc 1.10.11 slider 7.1 2024-08-22 05:33:37 +02:00
f024a960e4 slider 7.1 2024-08-22 05:33:06 +02:00
c3ff13856b Version 2024-08-19 16:45:45 +02:00
806e1cc14f Slider 7.0 2024-08-19 16:45:07 +02:00
a48cdf6690 1.10.09 Étiquette et non Etiquette 2024-08-19 15:46:38 +02:00
df646488d6 1.10.08 2024-08-15 18:04:55 +02:00
1a36e233be Corrige le filtre FILTER_FLOAT: pour la géolocalisation 2024-08-15 17:54:22 +02:00
b8c5d613bc Filtres CMS 13.3.05 2024-08-14 09:23:38 +02:00
60455ae036 1.10.07 Mise à jour du module BLOG 2024-08-01 19:16:04 +02:00
893db4034d 1.10.06 mise à jour module News 2024-07-30 21:17:55 +02:00
3d1d4be997 Corrige la génération des miniatures au format avif et webp 2024-07-28 18:04:14 +02:00
5f3bd590a8 Module auto inscription en version 2 2024-07-20 17:33:14 +02:00
cbffc3f44b update suscribe 2024-07-17 20:13:53 +02:00
8131162dae Vérification de la réécriture 2024-06-09 02:51:55 +02:00
72655aec3d Page de configuration des modules inactives 2024-06-07 20:47:25 +02:00
08ed4075c7 Chargement lassif des images 2024-06-07 09:57:23 +02:00
6d5ddf1f8d Corrige le bug de FF 2024-06-07 09:47:20 +02:00
8b354ff40e Corrige la détection de serveur 2024-06-07 09:42:57 +02:00
5be3d0b1a7 Layout d'édition : supprime tous les boutons de gestion de page comme pour les pages avec module 2024-06-07 09:32:52 +02:00
f0c4ea6bd0 Lorsque des éléments inutiles sont ajoutés à l'adresse d'une page, une erreur 403 est levée. 2024-06-04 22:21:10 +02:00
cbe06426bb ** Corrections :**
- Dans la configuration, l'option Apache URL intelligentes ne s'active que si le serveur est Apache et que le module Rewriter est actif. Ce qui exclue les autres serveurs non compatibles comme Nginx, Caddy etc.
2024-06-02 15:07:55 +02:00
adac7395cc Lignes vides en trop dans htaccess 2024-06-02 14:40:38 +02:00
2c459a03d4 nouvel htaccess 2024-06-02 14:33:59 +02:00
751bc450b5 1.10.04
** Corrections :**
- L'ajout d'un slash en fin d'adresse avec la réécriture active provoquait une mauvaise détermination des adresses des images dans TinyMCE. Résolution : une directive htaccess supprime tous les slash en fin d'adresse.
- Lorsque la page est ouverte en édition, un clic sur le bouton édition dans la barre d'administration affiche une erreur, le lien étant incorrect. Afin d'éviter cette erreur et une redondance, le bouton d'édition est masqué lorsque la page est éditée.
2024-06-01 21:20:41 +02:00
6c8d9097f6 Readme version 2024-05-20 14:15:03 +02:00
b0814d50dc 1.10.03 Workshop Tri des espaces par titre 2024-05-18 18:47:06 +02:00
a7a2424d93 1.10.02 2024-05-16 09:26:23 +02:00
43b15987d6 Suivi Zwii 13.3.02 2024-05-16 09:25:40 +02:00
e100a580ad Mise à jour des modules 1.10.01 2024-05-08 18:47:43 +02:00
397bdee655 Merge branch '1902-isole-les-commandes-sur-les-espaces' 2024-04-23 18:13:06 +02:00
78b2d87ec1 supprime sync.db ! 2024-04-23 18:09:55 +02:00
8dedb39a33 Déplace les boutons de gestion des utilisateurs dans la liste des espaces. 2024-04-23 18:09:28 +02:00
7cee16389f commentaire 2024-04-23 17:25:50 +02:00
04b2877c48 1.10.00 2024-04-23 14:58:01 +02:00
f6c7e5f954 Dans router self devient common
Nouveau routage en cas de changement d'espace en évitant une 404
2024-04-23 14:57:10 +02:00
b5ea22021b redirige vers la page ouverte 2024-04-23 11:54:50 +02:00
3ee1398e2f supprime un commentaire 2024-04-23 11:54:32 +02:00
cfb07b81d5 Id non fourni 2024-04-22 21:46:41 +02:00
0da23149db 2.0.0 corrige le warning blog vide + transmet tn paramètre sécurisant l'édition des espaces dans plusieurs onglets 2024-04-22 15:40:35 +02:00
1322cb4eb0 Revert "section par main"
This reverts commit 271ee347a8.
2024-04-22 14:19:47 +02:00
167ad06dde Revert "section par main"
This reverts commit 271ee347a8.
2024-04-22 14:16:12 +02:00
271ee347a8 section par main 2024-04-22 10:56:49 +02:00
04a6d86999 1.9.01 supprime la balise section 2024-04-21 15:54:15 +02:00
05e6ff8f9b init 2024-04-18 14:52:13 +02:00
6e53ca8766 readme 2024-04-18 10:37:56 +02:00
dda93cf3d3 Merge branch 'master' of https://forge.chapril.org/fredtempez/ZwiiLMS 2024-04-18 10:37:19 +02:00
075e4afa1c changes 2024-04-18 10:37:11 +02:00
fd144d55f0 changes 2024-04-18 10:32:27 +02:00
b595120227 1.9 Désincription en masse de la plateforme 2024-04-18 10:27:33 +02:00
b0b3b34bde 1.8.01 alignement de boutons 2024-04-17 16:42:03 +02:00
2f592e2818 1.8.01
Corrige :
- Mauvais initialisation d'un profil
Modifie :
- Ajoute des effets de sélection dans la gestion des profils des espaces (add and edit)
2024-04-17 10:53:02 +02:00
8c9bc40a02 1.8.01
Corrige :
 - tableau de stats vides affichant une erreur
 - correction relative au rapport d'un participant
Nouvelle fonctionnalité :
- Bouton de réinitialisation d'un espace, efface les historiques et les inscriptions, les désinscriptions des participants et par autorité ne suppriment plus les historiques.
2024-04-17 10:33:00 +02:00
37f77b3d50 readme 2024-04-13 10:13:48 +02:00
a5130e1d9f readme 2024-04-13 10:13:13 +02:00
256da35d53 1.8.00 user report in csv 2024-04-13 10:07:47 +02:00
bb93b1b313 User report ok 2024-04-13 10:05:32 +02:00
195ed682f6 Merge branch 'master' into 1.8.00-report-csv 2024-04-12 22:10:38 +02:00
ae71b9649d Clic dans le TR active la case à cocher. 2024-04-12 22:09:37 +02:00
71418548e7 getReport utilisé dans la liste des users d'un courseId 2024-04-12 22:04:24 +02:00
03c7e0a7fa update.inc.php mise à jour ok 2024-04-12 21:22:57 +02:00
6bc8636692 Update json to csv ok 2024-04-12 09:52:39 +02:00
c0d14596a7 fonction update à tester 2024-04-11 15:46:42 +02:00
6a72676c7c update to test 2024-04-11 07:58:26 +02:00
44c4997436 upodaite to 1.8 WIP 2024-04-11 07:55:48 +02:00
cce73886a2 UsersHistory devient UsersReport 2024-04-11 07:46:27 +02:00
b9733d7391 User History devient user report 2024-04-11 07:44:43 +02:00
56ff0580a1 création du CS sans courseID 2024-04-10 18:59:41 +02:00
5b9f86fb38 Code à mettre dans une fonction 2024-04-10 18:58:04 +02:00
d43a78d307 1.7.09 icones de tout sélectionner ou tout déselectionner 2024-04-10 18:41:39 +02:00
deedb002e8 1.8.00 report csv 2024-04-10 14:31:29 +02:00
6d7c2f725d secure_file_put_contents stocke les données brutes 2024-04-10 11:56:31 +02:00
5ede9b71c2 1709 supprime la variable sessionId 2024-04-10 08:33:53 +02:00
04f4c7be6d 1.7.09 bug double slash initDB 2024-04-10 08:32:08 +02:00
0c94b2f546 erreur secure_file_put_contents 2024-04-09 18:58:22 +02:00
8b72ae01dc Revert "DOuble slashs"
This reverts commit 0934bf847d.
2024-04-09 18:51:11 +02:00
1ca77b89ce Merge branch 'master' of https://forge.chapril.org/fredtempez/ZwiiLMS 2024-04-09 18:42:06 +02:00
0934bf847d DOuble slashs 2024-04-09 18:40:52 +02:00
2a152a9a1d version 2024-04-09 18:38:50 +02:00
bc8fbc17b8 numéro de version² 2024-04-09 18:32:54 +02:00
a8635f0c8a supprime target new dans course manage 2024-04-09 18:32:05 +02:00
ca875f9f05 Supprime un echo de test. 2024-04-09 18:29:05 +02:00
b4258fe496 Supprimer le target blank 2024-04-09 18:20:54 +02:00
509c95a680 double fonction 2024-04-09 18:17:13 +02:00
2027c5918f Merge commit '0f55df8d31a7093f83c2ee4510a1d27bb9a087ac' 2024-04-09 18:14:16 +02:00
3593e853d8 DOuble slashs 2024-04-09 18:07:41 +02:00
cb13d2b0c9 session_id WIP 2024-04-09 15:09:02 +02:00
0f55df8d31 En test 2024-04-09 14:33:01 +02:00
939cb8d53f 1.7.09 réintalle la dernière version correcte 2024-04-09 13:32:25 +02:00
730e4ac9c4 1.7.09 reformatage 2024-04-07 18:14:43 +02:00
d3d96f795a formatage 2024-04-06 09:14:37 +02:00
e68f58fad1 Merge branch 'master' of https://forge.chapril.org/fredtempez/ZwiiLMS 2024-04-06 09:13:07 +02:00
6c0f34ae71 1.7.09 flock sur le fichier principal (PB sous win) 2024-04-06 09:10:52 +02:00
9373880239 Détruit le fichier de verrouillage créé par secureFilePutContent 2024-04-05 18:21:09 +02:00
a35036e0fa Double slashs 2024-04-05 17:54:10 +02:00
19246a59c9 déplace les constantes 2024-04-05 17:16:25 +02:00
15c4d1edd3 annule secureFilePutContents dans les modules. Non justifié dans la configuration du module 2024-04-05 16:51:03 +02:00
24f679d531 1.7.09 fonction secureFilePutContents 2024-04-05 16:33:46 +02:00
56f8f03581 readme 2024-04-05 09:22:38 +02:00
ae1f15e8b8 1.7.09 Formatage 2024-04-05 09:07:38 +02:00
7544bb9862 1.7.09 ajoute un temps d'attente 2024-04-05 09:06:42 +02:00
ebd078848a 1.7.09 durcit le contrôle d'enregistrement un verrou 2024-04-05 09:06:26 +02:00
e8e4f98be0 1.7.09 json db 2024-04-03 12:52:49 +02:00
c8c74d9be3 1.7.09 supprimer un test dans jsondb 2024-04-03 12:50:42 +02:00
63541cf83a 1.7.08 worhsop liend e désinscription dans les options 2024-04-02 18:25:39 +02:00
1cb54d46b1 Revert "1.7.08 Le lien de désinscription par l'utilisateur ne supprime plus l'historique."
This reverts commit 84df59c52b.
2024-04-02 18:12:24 +02:00
cf3936b7c0 Merge branch 'master' of https://forge.chapril.org/fredtempez/ZwiiLMS 2024-04-02 12:54:52 +02:00
84df59c52b 1.7.08 Le lien de désinscription par l'utilisateur ne supprime plus l'historique. 2024-04-02 12:54:47 +02:00
c75b71f217 1.7.07 Le lien de désinscription par l'utilisateur ne supprime plus l'historique. 2024-04-02 12:54:19 +02:00
269abc5699 Version 1.7.07 2024-03-30 09:17:06 +01:00
638ddadb61 jsondb stoppe après une erreur de chargement 2024-03-30 09:16:27 +01:00
10f8340e76 Module search 3.1 2024-03-30 09:12:14 +01:00
7c0feae8ee 1.7.06 renumérotation et annule filter modif 2024-03-29 22:09:24 +01:00
25889b0759 1.7.08 bug de permission de pages avec enfants 2024-03-29 21:33:49 +01:00
1e0cca8685 1.7.07 test filter id 2024-03-21 15:42:50 +01:00
a02a796f4a Mise à jour RSS Feed 2024-03-21 13:26:48 +01:00
e640aa327e Mise à jour RSS Feed 2024-03-21 13:20:34 +01:00
ed34728f5e affiche un message 2024-03-20 10:40:31 +01:00
b6e4b39e78 1.7.06 nom du backup non trouvé default is campus 2024-03-19 13:04:04 +01:00
64f19f0f96 i18n est toujours exclu 2024-03-18 19:23:23 +01:00
b6fb2d75b4 autobackup filter 2024-03-18 19:12:38 +01:00
7138c07a89 Ajouter le paramètre get FILTER 2024-03-18 19:05:37 +01:00
137c151e19 1.7.05 corrige un bug fatal lorsque l'enrolement est nul 2024-03-18 18:14:27 +01:00
548daad047 Update rolling backup 2024-03-18 17:49:54 +01:00
c8abde012c Update rolling backup 2024-03-18 17:42:31 +01:00
caa348a571 Supprimer core/module/config/tool/data.key 2024-03-18 17:31:37 +01:00
8e1488b86f add data.key to git ignore 2024-03-18 17:30:38 +01:00
1d4f8405b1 change key 2024-03-18 08:51:46 +01:00
0fece8c7ca Contrôle par clé 2024-03-18 08:49:16 +01:00
0deec384bc 1.7.05 clean auto backup 2024-03-17 15:37:46 +01:00
7452faab55 Version 2024-03-17 13:01:03 +01:00
e9ed55b065 1.7.05 outil de sauvegarde automatisé 2024-03-17 12:49:55 +01:00
d35010f100 Livre un outil de mise à jour automatisé appelable par CRON 2024-03-17 12:46:38 +01:00
14683133c8 Json vérif 2024-03-14 19:14:06 +01:00
4e174124fe 1.7.04 stop on load bad json 2024-03-14 19:08:14 +01:00
64594e23ff sharePath value 2024-03-14 13:26:31 +01:00
7d5d6edf25 Fix user path select 2024-03-14 10:28:00 +01:00
74fabce177 1.7.03 Datatables.net save state 2024-03-12 13:57:15 +01:00
e64e819d48 1.7.03 Datatables.net save state 2024-03-12 12:42:29 +01:00
2dd835593a 1.7.03 2024-03-12 11:54:51 +01:00
9664ce49b7 1.7.04 Erreur d'étiquette 2024-03-12 11:53:07 +01:00
3502d78632 1.7.04 Gestion des espaces divisions non fermées 2024-03-12 11:49:47 +01:00
65a121cb0a 1.7.03 gabarit accordéon dhtml 2024-03-10 18:07:35 +01:00
e6c52c29ee 1.7.02
Redirige le lien depuis l'icone RFM vers le sous-dossier de l'espace.
Empêche la modification de la configuration depuis un espace autre que home
2024-03-09 19:37:26 +01:00
31994d33e0 1.7.01 Lien vers l'espac =e sur le titre et non l'id 2024-03-08 17:14:00 +01:00
cfb0d8a0e9 1.7.01 Ecran de gestion des espaces 2024-03-08 17:04:59 +01:00
5a8fc68049 1700 Mise à jour des chemins dans le profil 2024-03-07 17:47:54 +01:00
8988e2e130 slide changes 2024-03-06 17:07:18 +01:00
724d391d00 supprime un dump 2024-03-05 18:46:46 +01:00
78102b96b4 Fix RFM config.php 2024-03-05 18:39:30 +01:00
0535556b68 'course' devient '' 2024-03-05 18:21:54 +01:00
db0637ca1c 1.7.00 gestion RFM WIP 2024-03-03 22:26:10 +01:00
6d42f792e4 1700 Gestion des partages dissoiant home et courseId 2024-03-01 18:37:10 +01:00
dd194e2488 Alerte si le dossier partagé a été supprimé 2024-03-01 18:25:33 +01:00
fc197b647d 1.6.02 routeur d'espace dans la config de RFM WIP 2024-02-29 15:37:29 +01:00
d2dc4c64c0 1.6.02 routeur d'espace dans la config de RFM WIP 2024-02-28 14:26:32 +01:00
f65fe62da7 1.6.02 libellés 2024-02-28 09:17:19 +01:00
372db6dc3a 1.6.02 exclure les dossiers des espaces des cours dans le profil 2024-02-28 08:54:56 +01:00
fd5aabd910 1.6.02 new path 2024-02-27 18:09:04 +01:00
36604a1ee4 1.6.02 Formateur 2024-02-27 17:56:30 +01:00
4dfd73453e salsh dans la variable du profil 2024-02-27 13:57:26 +01:00
2eab0090d1 commentaire 2024-02-27 09:56:45 +01:00
f74c7fd6f7 permission rfm 2024-02-22 18:44:20 +01:00
2bdb09b958 1.6.02 Corrige un erreur de tri dans RFM 2024-02-22 14:26:38 +01:00
0407bd082d 16.01 Bouton de gestion des espaces non affiché 2024-02-22 13:16:18 +01:00
d42ce3c733 1.6.00 Bug de chemin des images 2024-02-18 11:41:00 +01:00
260098d0a5 1.6.00 Block align 2024-02-16 11:12:25 +01:00
52fb225650 1.6 Fix last setup editor course permissions 2024-02-16 11:06:54 +01:00
b5693abbf5 Course manage icons bar 2024-02-15 16:28:07 +01:00
a8f1387c96 1.6.00 2024-02-15 15:58:20 +01:00
083d819597 Merge branch 'master' of https://forge.chapril.org/fredtempez/ZwiiLMS 2024-02-15 15:56:37 +01:00
d829f57582 Slider 6.4 2024-02-15 15:55:50 +01:00
31986d138e 1.5.04 message suppression page définie comme homePage Id 2024-02-15 15:55:50 +01:00
3b77452bbe 1.5.04 Propagation du renommade de la homePage dans course 2024-02-15 15:55:49 +01:00
c6358b4c63 1.5.04 Changement de nom d'une page met à jour les id dans les historiques 2024-02-15 15:55:49 +01:00
084471aa3b 1.5.04 Fix la dernière page vue a changé de nom, redirige vers l'accueil. 2024-02-15 15:54:19 +01:00
97a782eb4d Slider 6.4 2024-02-15 14:35:37 +01:00
3884573de9 1.5.04 message suppression page définie comme homePage Id 2024-02-14 18:25:06 +01:00
572f0206a8 1.5.04 Propagation du renommade de la homePage dans course 2024-02-14 11:49:43 +01:00
d3675f62f4 1.5.04 Changement de nom d'une page met à jour les id dans les historiques 2024-02-14 11:38:29 +01:00
8e9c356188 1.6.00 Esapces : Add profil 2024-02-14 08:16:46 +01:00
3b5ddb5a3f 1.6.00 Espaces de l'auteur author devient tutor 2024-02-14 08:12:33 +01:00
91e4a4047c 1.6.00 Default install 2024-02-13 18:13:25 +01:00
caf193611d 1.6.0 Gestion des droits éditeurs okay 2024-02-13 18:05:08 +01:00
ee4fc93afe 1.6.00 Gestion des droits de l'esapce par un éditeur limité ou étendu 2024-02-13 17:56:41 +01:00
3c76bcdf4c 1.6.00 Espaces de l'auteur ou tous les espaces WIP 2024-02-13 14:55:57 +01:00
e9e39f5a03 1.6.00 permissions pour le contrôle des espaces pour les éditeurs 2024-02-13 12:51:17 +01:00
b5382fa5f2 1.5.03 Erreur de version 2024-02-13 12:06:13 +01:00
cd69635448 1.5.04 Fix la dernière page vue a changé de nom, redirige vers l'accueil. 2024-02-13 11:33:03 +01:00
0c8569f7cf 1.6.00 Profil des espaces WIP 2024-02-13 11:22:49 +01:00
13227a5cd4 1.6 Autorisation d'éditer les espaces 2024-02-13 10:28:30 +01:00
c43ce394e4 Init 2024-02-13 09:02:41 +01:00
6c2c6a1acb 1.5.03 Ordre des Profils pour les espaces 2024-02-13 09:01:51 +01:00
656d6e557e Profils pour les espaces 2024-02-13 09:00:51 +01:00
9bf135337e 1.5.02
- graph page name
- graph time
- graph shit first time range
2024-02-13 08:43:09 +01:00
6d77995439 1.5.01 user date with time 2024-02-13 07:44:07 +01:00
9a3de92678 1.5.00 c'est mieux 2024-02-12 17:22:47 +01:00
7b5f182be4 1.6 ajoute un graph dans l'hostorique d'un participant 2024-02-12 17:21:37 +01:00
98f68f284c 1.5.00 Fix erreur 2024-02-12 15:23:17 +01:00
3ebb305cae 1.5.00 getCoursesByUser devient getCoursesByProfil 2024-02-12 15:16:46 +01:00
e80564c106 1.5.00 supprimer un echo inutile 2024-02-12 14:46:05 +01:00
e90929ea3b 1.5.00 fix default permanent profil 2024-02-12 14:13:54 +01:00
ac8d3016c7 1.5.00 petit correction d'égalité 2024-02-12 14:11:11 +01:00
ffb872fd03 1.5.00 fix show RFM icon for editors 2024-02-12 13:58:38 +01:00
08fb2d25fd 1.5.00 fix permission control 2024-02-12 13:27:56 +01:00
63f7767460 1.5.00 contrôle des permisison générale spour les comptes éditeurs 2024-02-12 13:14:02 +01:00
17b76e1a0f 1.4.26 Gestion des utilisateurs date de la dernière page vue 2024-02-11 17:53:56 +01:00
a4164e4a2d 1.4.26 Journal corrige format de la langue + version 2024-02-11 17:33:21 +01:00
595d068de2 1.4.25 Corrige la fonction delete de la classe dot 2024-02-10 19:46:52 +01:00
cc92c90403 1.4.24 icones de l'inscription et de la désincription de masse 2024-02-10 19:23:18 +01:00
6da8223209 1.4.23 Fix bug dot class 2024-02-10 17:13:38 +01:00
3bedbed4ef 1.4.23 Tri des progressions 2024-02-09 15:43:20 +01:00
023ba99c0b 1.4.23 User History modifié 2024-02-09 15:38:32 +01:00
b8123b0534 1.4.23 User Edit champ Tag non sauvé pour les comptes non admiN 2024-02-09 09:52:33 +01:00
931b56f6a3 1.4.23 Supprime tri par défaut 2024-02-08 19:43:31 +01:00
fcee5a8cde 1.4.23 Tri des champs date en cours de test 2024-02-08 19:39:51 +01:00
25d1c2400e TEST datetime sort 2024-02-08 16:56:39 +01:00
48725b8703 1.4.23 Groupe éditor ne peut modifier l'accueil 2024-02-08 09:51:44 +01:00
9bea40ed08 1.4.23 Installation vierge, création du dossier home dans file/source 2024-02-08 09:44:24 +01:00
01d6300d90 1.4.22 Autorise l'icône RFM pour les éditeurs 2024-02-07 18:39:58 +01:00
ac28fe496f 1.4.22 Le sélecteur de fichier et l'icône du gestionnaire de fichiers redirige vers le dossier de l'espace. 2024-02-07 15:51:01 +01:00
ef371092a0 1.4.22 le lien RFM de la barre ouvre le dossier de l'espace ou celui de tous les dossiers en mode home. 2024-02-06 21:14:53 +01:00
21afc43656 1.4.22 nettoyage 2024-02-06 20:31:46 +01:00
cd03316a9b 1.4.22 corrige une erreur 404 depuis un espace n'affichant pas l'erreur de l'accueil 2024-02-06 20:30:18 +01:00
7ce30078f6 1.4.22 Protection supplémentaire dans jsonDB 2024-02-06 20:08:26 +01:00
ded7bb5c81 1.4.21 evite une redirection vers une page d'erreur après login 2024-02-04 21:38:58 +01:00
87bfe71d9d 1.4.20 Journalise l'erreur de mise à jour 2024-02-03 18:59:42 +01:00
36537c4b17 1.4.20 feuille de style absente de l'index de l'installation 2024-02-03 18:44:13 +01:00
13b5adffac 1.4.20 auto update avec messages d'erreurs 2024-02-03 18:42:00 +01:00
28ee5e46a5 14.1.19 temps passé sur un espace en jours 2024-02-03 09:55:38 +01:00
0ce3f0d1cb "Mettre à jour" devient "Mise à jour" 2024-02-03 09:35:48 +01:00
f6019714b9 1.4.18 Evite une notice si la capture OpenGraph est indéfinie 2024-02-02 17:48:27 +01:00
e2316dc129 1.4.17 Opérateur booléen nouvelle version sans le type 2024-01-31 14:36:25 +01:00
fbbf671289 1.4.17 Désactivation des champs dans la page de consultation de la configuration d'un espace 2024-01-31 13:46:11 +01:00
9126d2887b 1.4.16 Les exports des historiques se font dans le dossier de l'espace 2024-01-30 18:57:24 +01:00
052f4ac035 1.4.16 corrige les statistiques des pages supprimées mais déjà consultées 2024-01-30 18:51:19 +01:00
0f7e271a28 Readme numéro de version 2024-01-27 16:39:24 +01:00
451174cdcf Désactive l'édition des tages pour les membres et éditeurs 2024-01-27 16:32:46 +01:00
8b8480b444 1.4.15 User Edit Désactive l'édition des tags pour les membres 2024-01-27 16:28:51 +01:00
eac4746e8a 1.4.15
Déplace le bouton de connexion à la fin du container
Désactive le sélecteur d'espaces pour les admins et les éditeurs
TinyMCE : les URL des images sont relatives
Sélecteur d'espace, améliore la feuille de style
2024-01-27 16:21:06 +01:00
91a57d30f7 Lien de désinscription et de retour vers l'accueil 2024-01-27 10:01:19 +01:00
0d94e67ffb 1414readme 2024-01-27 09:50:16 +01:00
09bf4d06f3 1414 compatible avec le group MODERATOR de certains modules 2024-01-27 09:47:55 +01:00
1461a35b7a 1413 Bug Date siteContent 2024-01-26 16:34:04 +01:00
e2b0a12824 1412 valide le sélecteur d'espace pour les membres éditeurs et admin 2024-01-24 17:55:25 +01:00
4fe81830e9 1.4.11 2024-01-21 12:04:23 +01:00
c3c5909ea6 1410 Espaces profils 2024-01-21 12:02:26 +01:00
b297584fbe Fix bug author 2024-01-21 11:28:38 +01:00
76721aa91c fix layout manage 2024-01-21 11:21:35 +01:00
efcfcc6287 fix bug sélecteur author 2024-01-21 11:18:05 +01:00
3885fbc475 Layout 2024-01-21 11:05:05 +01:00
7d23918617 1410 alignement du sélecteur d'espaces 2024-01-20 22:15:00 +01:00
12c12ff9bf Réinstaure la fonction pour un filtrage futur 2024-01-20 22:03:55 +01:00
511b90e7a8 1410 bug clé 2024-01-20 21:50:30 +01:00
dea8568992 1410 masque ce sélecteur à l'admin 2024-01-20 21:42:21 +01:00
8cfe76bdf6 1410 liste tous dans les sélecteurs d'espaces 2024-01-20 21:39:22 +01:00
21c49d8e53 1410 changement d'id 2024-01-20 21:22:16 +01:00
a0ffcca22a 1410 Ajoute l'affichage du sélecteur d'espace aux membres et ouvre les conditions d'accès aux espaces ouverts 2024-01-20 21:07:28 +01:00
489f3b0da6 Option d'affichage du sélecteur d'espaces 2024-01-19 14:37:03 +01:00
3e8da80e92 Clonage 2024-01-18 22:16:59 +01:00
efab38d4c5 Double variable Blog date 2024-01-18 19:19:37 +01:00
540070af8b warning user forgot 2024-01-18 18:33:07 +01:00
a67d426a13 Markdown in TinyMCE 2024-01-18 15:31:35 +01:00
3c6d1480ad 1.4.09 Ajoute sélecteur d'espace dans la barre de membre 2024-01-18 15:19:14 +01:00
4387dcda7a Compresse les fichiers de données
Corrige un problème dans la fonction getCoursesByUser lorsque le membre a un rôle inférieur à EDITOR
2024-01-18 14:41:03 +01:00
cf0fb4df53 1408 petit doublon 2024-01-17 18:26:33 +01:00
91c6c0347a 1408 commentaires 2024-01-17 18:25:09 +01:00
4d2bd1c34d 1408 petite optimisation admin.css 2024-01-17 18:20:10 +01:00
280962b852 1408 bloque la suppression d'une fonte mise en oeuvre dans le theme d'un autre espace.
Optimise le code
2024-01-17 18:14:30 +01:00
995a4364f6 147 en fait 2024-01-17 12:22:12 +01:00
9a1ed24295 1408 encore un bug avec le footer 2024-01-17 12:21:11 +01:00
e07ba9963b 1408 supprime un appel à locale qui n'existe plus 2024-01-17 12:20:58 +01:00
b9669a03e9 1406 bug footer 2024-01-16 15:52:29 +01:00
2d4e835269 Clone course 2024-01-14 20:56:23 +01:00
62d1a00a91 1406 2024-01-14 20:37:53 +01:00
b948f9baac Fix variable non déclarée 2024-01-14 19:37:25 +01:00
eb581b3fa5 2024 2024-01-14 19:31:22 +01:00
011d435ac5 Manage Course 2024-01-14 19:30:14 +01:00
104e3d408c Course sort 2024-01-13 22:35:57 +01:00
98ee5d4afe course link lien dans l'id uniquement 2024-01-13 22:22:16 +01:00
71ecbb1842 Remplace ZwiiLMS 2024-01-13 21:58:21 +01:00
5ecae99a87 1406 2024-01-13 13:29:40 +01:00
b18820f0b0 readme 1.4.05 2024-01-12 16:08:26 +01:00
0c25151012 1405 2024-01-08 17:25:47 +01:00
9d9db5b8ed Backup et restore okay 2024-01-08 17:24:05 +01:00
be7073e63f layout pour les memebres simples uniquement 2024-01-08 14:56:36 +01:00
108947ec3c user edit profil select current value 2024-01-08 14:42:39 +01:00
e39c76da33 1404 core 2024-01-07 16:15:44 +01:00
14def12f2e 1404 Fix user Add tags and language 2024-01-07 16:15:29 +01:00
88ff501195 restore WIP 2024-01-07 16:11:22 +01:00
ac133e1547 restore WIP 2024-01-07 16:11:09 +01:00
84b711eac5 Sauvegarde des fontes installées 2024-01-06 23:18:05 +01:00
127efc3925 fonte nettoyage des majuscules et des espaces dans l'id de la fonte 2024-01-06 16:19:58 +01:00
b3924c73b4 fonte installée ou importée 2024-01-06 16:04:17 +01:00
f2793d613d Fix mauvais message fonte en ligne 2024-01-06 15:48:46 +01:00
47c24d65f7 Bug fonte delete 2024-01-06 09:27:16 +01:00
8320ad6461 Bug ajout de fonte 2024-01-05 20:49:29 +01:00
c2dd9c7f99 charge les fontes avant tout + fontedit readonly 2024-01-05 20:30:57 +01:00
f57e7fcbdc Fix pb de chemin pour les rédacteurs avec droit RFM 2024-01-04 23:54:35 +01:00
2819e0d29b Bug chemin profil 2-2 2024-01-04 22:03:17 +01:00
283cc7f771 File cloud download icon 2024-01-04 16:46:24 +01:00
7ac5d9589c backup ok 2024-01-04 16:43:45 +01:00
2abc9812dc Backup ok 2024-01-04 16:24:00 +01:00
921dff5a82 Course backup 2024-01-03 16:40:23 +01:00
411565df77 Supprime un point final 2024-01-03 16:33:34 +01:00
1c1969dc49 Revert "1403 move enrolment database in course folder"
This reverts commit c6364183af.
2024-01-03 15:20:05 +01:00
c6364183af 1403 move enrolment database in course folder 2024-01-03 14:54:32 +01:00
a73b65d3fc Icône RFM Admin dans home 2024-01-03 10:51:05 +01:00
37d1915007 Fontes : datatables 2024-01-03 00:15:08 +01:00
a6a866c01d 1.4.02 fontes 2024-01-03 00:04:03 +01:00
bc9db7f525 nettoyage getPermission 2023-12-20 17:37:04 +01:00
2de0594719 News et blog uniformisation 2023-12-20 13:44:47 +01:00
cd0131e2d4 Blog 7.4 bouton de retour 2023-12-20 13:03:00 +01:00
667417c750 News tiret et espace 2023-12-20 12:48:44 +01:00
f7ea87fb1d News 5.3 2023-12-19 19:20:22 +01:00
acd6ddfc56 news : Un espace manquant 2023-12-19 19:19:49 +01:00
caf00c0d41 News 5.3 voir CMS 2023-12-19 19:10:49 +01:00
d64ffa02c7 Espace avant le ? 2023-12-19 17:30:37 +01:00
bfa1114a4e Evite une 404 et redirige vers l'espace et la page correcte 2023-12-15 22:51:05 +01:00
cf184e902e Evite une 404 si la page est contenue dans un espace 2023-12-15 22:07:25 +01:00
532aa91fd5 update url 2023-12-14 15:20:27 +01:00
b29bbcc21e Version + update url 2023-12-14 14:51:50 +01:00
9c32f1a560 1400 2023-12-14 14:50:03 +01:00
b528f223d5 Corrige les droits rfm pour les membres et plus 2023-12-14 14:43:53 +01:00
2b5b254c88 Aide sur le dossier de l'espace actif 2023-12-14 14:38:37 +01:00
f39601f37e fix bug banner link homePage 2023-12-14 14:29:39 +01:00
729152bef1 init 2023-12-14 13:44:24 +01:00
b1c8ea8047 savelog 2023-12-14 09:28:41 +01:00
867d8ac713 Statistiques 2023-12-09 23:35:21 +01:00
bce93cecba Format CSV Export et format progreesion export 2023-12-09 22:45:20 +01:00
86e9322afc user index datatables 2023-12-09 17:59:41 +01:00
e5d9936641 1304 datatables non chargée par défaut 2023-12-09 17:58:14 +01:00
103991b2be userHistory, one event a line 2023-12-09 17:51:36 +01:00
d59062cd46 Export userHistory 2023-12-09 17:45:31 +01:00
0fb328980c Stats de consultation 2023-12-09 17:20:40 +01:00
30d96fb24c users avec stats okay 2023-12-09 13:25:18 +01:00
59d7a8e5c3 Stocke la totalité des historiques et affiche la dernière page vue 2023-12-08 23:04:14 +01:00
4db14b5da6 Paragraphe sous le bloc 2023-12-07 14:21:11 +01:00
fb1e37536a extension md dans RFM 2023-12-07 13:46:51 +01:00
2bf867e876 supprime change.md 2023-12-07 11:42:20 +01:00
e326b3aeaa typo 2023-12-07 11:37:06 +01:00
d44b90b2a9 libellé installation 2023-12-07 11:35:17 +01:00
ff922ca58a Contenu devient espace 2023-12-07 10:40:47 +01:00
506e63597a 1303 Thème TinymCE selon thème du cours 2023-12-06 14:12:37 +01:00
d6b147f3b0 1303 participation 2023-12-06 13:46:31 +01:00
355 changed files with 8179 additions and 3598 deletions

1
.gitignore vendored
View File

@ -9,3 +9,4 @@ site/i18n/*.json
core/vendor/tinymce/link_list.json
robots.txt
sitemap.xml
core/module/config/tool/data.key

View File

@ -32,5 +32,13 @@ Options -Indexes
Options -MultiViews
</IfModule>
# Enlever le slash final des URL
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^(.+)/$
RewriteRule ^ %1 [R=301,L]
# ne pas supprimer la ligne URL rewriting !
# URL rewriting

View File

@ -1,3 +0,0 @@
# Changelog
C'est vide pour le moment

View File

@ -1,6 +1,16 @@
# ZwiiLMS 1.3.02
# ZwiiCampus 1.14.00
ZwiiLMS (Learning Management System) est logiciel auteur destiné à mettre en ligne des tutoriels. Il dispose de plusieurs modalités d'ouverture et d'accès des contenus. Basé sur la version 13 du CMS Zwii, la structure logicielle est solide, le framework de Zwii est éprouvé.
ZwiiCampus (Learning Management System) est logiciel auteur destiné à mettre en ligne des tutoriels. Il dispose de plusieurs modalités d'ouverture et d'accès des contenus. Basé sur la version 13 du CMS Zwii, la structure logicielle est solide, le framework de Zwii est éprouvé.
Ce logiciel s'installe en ligne ou localement depuis un serveur Web.
## Principales fonctionnalités :
- Gestion des espaces d'enseignement : Créez des espaces de formation avec accès restreint.
- Participation et suivi des apprenants : Inscription libre, imposée ou avec clé, et suivi statistique détaillé des participants.
- Gestion des accès : Contrôlez la disponibilité des espaces (ouvert, limité dans le temps, fermé).
- Outils statistiques : Visualisation et exportation CSV des progrès des apprenants.
- Facilité d'installation : Pas besoin de base de données, tout fonctionne avec des fichiers JSON.
- Sauvegarde et restauration : Outils de gestion pour réinitialiser les espaces et les participations.
## Configuration recommandée
@ -68,6 +78,7 @@ A l'occasion de l'installation d'une version majeure, il est recommandé de réa
[F] module.json Données des modules de pages
[F] theme.css Thème de ce contenu
[F] theme.json Thème de ce contenu
[F] report.csv Rapport de participation
[R] content Dossier des contenus de page
[F] accueil.html Exemple contenu de la page d'accueil
[R] fonts Dossier contenant les fontes installées
@ -84,7 +95,7 @@ A l'occasion de l'installation d'une version majeure, il est recommandé de réa
[F] core.json Configuration du noyau
[F] course.json Données de contenus
[F] custom.css Feuille de style de la personnalisation avancée
[F] enrolment.json Données des inscriptions et des statistiques par contenu
[F] enrolment.json Inscriptions dans les espaces, dernière page vue et timetamp
[F] font.json Descripteur des fontes personnalisées
[F] journal.log Journalisation des activités
[F] language.json Langues de l'interface
@ -96,7 +107,7 @@ A l'occasion de l'installation d'une version majeure, il est recommandé de réa
[R] thumb Miniatures des images
[R] tmp Répertoire temporaire
[F] index.php Fichier d'initialisation de ZwiiLMS
[F] index.php Fichier d'initialisation de ZwiiCampus
[F] robots.txt Filtrage des répertoires accessibles aux robots des moteurs de recherche
[F] sitemap.xml Plan du site
[F] sitemap.xml.gz Version compressée

View File

@ -8,7 +8,7 @@ class helper
/** Filtres personnalisés */
const FILTER_BOOLEAN = 1;
const FILTER_DATETIME = 2;
const FILTER_DATETIME = 2; // filtre pour le champ de formulaire A conserver pour la compatibilité
const FILTER_FLOAT = 3;
const FILTER_ID = 4;
const FILTER_INT = 5;
@ -16,8 +16,14 @@ class helper
const FILTER_PASSWORD = 7;
const FILTER_STRING_LONG = 8;
const FILTER_STRING_SHORT = 9;
const FILTER_TIMESTAMP = 10;
const FILTER_TIMESTAMP = 10; // Saisie d'une date en locatime
const FILTER_URL = 11;
const FILTER_DATE = 12; // filtre pour le champ de formulaire
const FILTER_TIME = 13; // filtre pour le champ de formulair
const FILTER_MONTH = 14; // filtre pour le champ de formulair
const FILTER_YEAR = 16; // filtre pour le champ de formulair
/**
@ -29,12 +35,12 @@ class helper
// La traduction existe déjà dans le core
/*
if (array_key_exists($text, core::$dialog) === false && !empty($text)) {
$dialogues = json_decode(file_get_contents('core/module/install/ressource/i18n/fr_FR.json' ), true);
$data = array_merge($dialogues,[$text => '']);
file_put_contents ('core/module/install/ressource/i18n/fr_FR.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
}
*/
if (array_key_exists($text, core::$dialog) === false && !empty($text)) {
$dialogues = json_decode(file_get_contents('core/module/install/ressource/i18n/fr_FR.json' ), true);
$data = array_merge($dialogues,[$text => '']);
file_put_contents ('core/module/install/ressource/i18n/fr_FR.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
}
*/
return (array_key_exists($text, core::$dialog) && !empty(core::$dialog[$text]) ? core::$dialog[$text] : $text);
}
@ -77,7 +83,7 @@ class helper
// Créer la variable
$data = array_merge($data, [$text => '']);
}
file_put_contents('site/i18n/' . $to . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
file_put_contents('site/i18n/' . $to . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
}
@ -338,13 +344,12 @@ class helper
{
// N'interroge que le serveur Apache
if (strpos($_SERVER["SERVER_SOFTWARE"], 'Apache') > 0) {
self::$rewriteStatus === false;
} elseif (self::$rewriteStatus === null) {
self::$rewriteStatus = false;
} else {
// Ouvre et scinde le fichier .htaccess
$htaccess = explode('# URL rewriting', file_get_contents('.htaccess'));
// Retourne un boolean en fonction du contenu de la partie réservée à l'URL rewriting
//self::$rewriteStatus = (empty($htaccess[1]) === false);
self::$rewriteStatus = (strpos($htaccess[1], 'RewriteEngine on') > 0) ? true : false;
self::$rewriteStatus = (strpos($htaccess[1], 'RewriteEngine on') !== false);
}
return self::$rewriteStatus;
}
@ -368,11 +373,10 @@ class helper
$version = helper::getOnlineVersion($channel);
$update = false;
if (!empty($version)) {
$update = version_compare(common::ZWII_VERSION, $version) === -1;
$update = version_compare(common::ZWII_VERSION, $version) == -1;
}
return $update;
}
/**
@ -391,10 +395,10 @@ class helper
'text' => self::relativeLuminanceW3C($rgba) > .22 ? "#222" : "#DDD",
'rgb' => 'rgb(' . $rgba[0] . ',' . $rgba[1] . ',' . $rgba[2] . ')',
'invert' => 'rgba (' .
($rgba[0] < 128 ? 255 : 0) . ',' .
($rgba[1] < 128 ? 255 : 0) . ',' .
($rgba[1] < 128 ? 255 : 0) . ',' .
($rgba[0] < 128 ? 255 : 0) . ')'
($rgba[0] < 128 ? 255 : 0) . ',' .
($rgba[1] < 128 ? 255 : 0) . ',' .
($rgba[1] < 128 ? 255 : 0) . ',' .
($rgba[0] < 128 ? 255 : 0) . ')'
];
}
@ -404,8 +408,8 @@ class helper
*/
public static function deleteCookie($cookieKey)
{
unset($_COOKIE[$cookieKey]);
setcookie($cookieKey, '', time() - 3600, helper::baseUrl(false, false), '', false, true);
unset($_COOKIE[$cookieKey]);
}
/**
@ -428,7 +432,8 @@ class helper
$text = (int) $date->format('U');
break;
case self::FILTER_FLOAT:
$text = filter_var($text, FILTER_SANITIZE_NUMBER_FLOAT);
$text = str_replace(',', '.', $text); // Remplacer les virgules par des points
$text = filter_var($text, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
$text = (float) $text;
break;
case self::FILTER_ID:
@ -475,6 +480,11 @@ class helper
case self::FILTER_URL:
$text = filter_var($text, FILTER_SANITIZE_URL);
break;
case self::FILTER_DATE:
$text = date('Y-m-d', $text);
break;
case self::FILTER_TIME:
$text = date('H:i', $text);
}
return $text;
}
@ -663,10 +673,30 @@ class helper
public static function subword($text, $start, $length)
{
$text = trim($text);
if (strlen($text) > $length) {
// Vérifier si la longueur du texte sans les balises dépasse la longueur souhaitée
if (mb_strlen(strip_tags($text)) > $length) {
// Utiliser mb_substr pour couper le texte
$text = mb_substr($text, $start, $length);
$text = mb_substr($text, 0, min(mb_strlen($text), mb_strrpos($text, ' ')));
// S'assurer que le texte ne se termine pas au milieu d'un mot
$lastSpace = mb_strrpos($text, ' ');
if ($lastSpace !== false) {
$text = mb_substr($text, 0, $lastSpace);
}
// Fermer les balises HTML ouvertes
$dom = new DOMDocument();
@$dom->loadHTML('<div>' . $text . '</div>', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$text = $dom->saveHTML();
// Retirer la balise de conteneur ajoutée
$text = preg_replace('~^<div>(.*)</div>$~s', '$1', $text);
// Ajouter des points de suspension si le texte a été coupé
$text .= '...';
}
return $text;
}

View File

@ -101,7 +101,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
}
} else {
// Iterate path
$keys = explode('.', (string)$key);
$keys = explode('.', (string) $key);
if ($pop === true) {
array_pop($keys);
}
@ -141,7 +141,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
} elseif (is_array($key)) {
// Iterate array of paths
foreach ($key as $k) {
self::delete($k);
self::deleteValue($array, $k);
}
}
}
@ -199,7 +199,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
*/
public function has($key)
{
$keys = explode('.', (string)$key);
$keys = explode('.', (string) $key);
$data = &$this->data;
foreach ($keys as $key) {
if (!isset($data[$key])) {
@ -371,7 +371,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
*/
public function isEmpty(): bool
{
return !(bool)count($this->data);
return !(bool) count($this->data);
}
/**
@ -391,7 +391,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
*/
public function toJson()
{
return json_encode($this->data, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
return json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
}
/**

View File

@ -121,17 +121,17 @@ class JsonDb extends \Prowebcraft\Dot
} else {
if ($this->config['backup']) {
try {
//todo make backup of database
copy($this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'], $this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'] . '.backup');
} catch (\Exception $e) {
error_log('Erreur de chargement : ' . $e);
exit('Erreur de chargement : ' . $e);
}
}
}
$this->data = json_decode(file_get_contents($this->db), true);
if (!$this->data === null) {
throw new \InvalidArgumentException('Database file ' . $this->db
. ' contains invalid json object. Please validate or remove file');
if (!$this->data === null && json_last_error() !== JSON_ERROR_NONE) {
throw new \InvalidArgumentException('Le fichier ' . $this->db
. ' contient des données invalides.');
}
}
return $this->data;
@ -142,20 +142,38 @@ class JsonDb extends \Prowebcraft\Dot
*/
public function save()
{
//$v = json_encode($this->data, JSON_UNESCAPED_UNICODE );
$v = json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT);
$l = strlen($v);
$t = 0;
while ($t < 5) {
$w = file_put_contents($this->db, $v); // Multi user get a locker
if ($w == $l) {
// Encode les données au format JSON avec les options spécifiées
$encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT);
// Vérifie la longueur de la chaîne JSON encodée
$encoded_length = strlen($encoded_data);
// Initialise le compteur de tentatives
$attempt = 0;
// Tente d'encoder les données en JSON et de les sauvegarder jusqu'à 5 fois en cas d'échec
while ($attempt < 5) {
// Essaye d'écrire les données encodées dans le fichier de base de données
$write_result = file_put_contents($this->db, $encoded_data, LOCK_EX); // Les utilisateurs multiples obtiennent un verrou
// $now = \DateTime::createFromFormat('U.u', microtime(true));
// file_put_contents("tmplog.txt", '[JsonDb][' . $now->format('H:i:s.u') . ']--' . $this->db . "\r\n", FILE_APPEND);
// Vérifie si l'écriture a réussi
if ($write_result === $encoded_length) {
// Sort de la boucle si l'écriture a réussi
break;
}
$t++;
// Incrémente le compteur de tentatives
$attempt++;
}
if ($w !== $l) {
exit('Erreur d\'écriture, les données n\'ont pas été sauvegardées');
// Vérifie si l'écriture a échoué même après plusieurs tentatives
if ($write_result !== $encoded_length) {
// Enregistre un message d'erreur dans le journal des erreurs
error_log('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
// Affiche un message d'erreur et termine le script
exit('Erreur d\'écriture, les données n\'ont pas été sauvegardées.');
}
}
}

View File

@ -82,17 +82,25 @@ class layout extends common
$content = 'col' . $blocks[1];
$blockright = 'col' . $blocks[2];
}
// Page pleine pour la configuration des modules et l'édition des pages sauf l'affichage d'un article de blog
$pattern = ['config', 'edit', 'add', 'comment', 'data'];
// Toujours en pleine page pour la configuration des modules et l'édition des pages sauf l'affichage d'un article de blog
$pattern = ['config', 'edit', 'add', 'comment', 'data', 'option', 'theme', 'comment', 'article', 'data', 'gallery', 'update', 'users', 'validate'];
if (
(sizeof($blocks) === 1 ||
in_array($this->getUrl(1), $pattern))
) { // Pleine page en mode configuration
if ($this->getData(['page', $this->getUrl(0), 'navLeft']) === 'top' || $this->getData(['page', $this->getUrl(0), 'navRight']) === 'top') {
if (
($this->getData(['page', $this->getUrl(0), 'navLeft']) === 'top'
|| $this->getData(['page', $this->getUrl(0), 'navRight']) === 'top')
&& in_array($this->getUrl(1), $pattern) === false
) {
$this->showNavButtons('top');
}
$this->showContent();
if ($this->getData(['page', $this->getUrl(0), 'navLeft']) === 'bottom' || $this->getData(['page', $this->getUrl(0), 'navRight']) === 'bottom') {
if (
($this->getData(['page', $this->getUrl(0), 'navLeft']) === 'bottom'
|| $this->getData(['page', $this->getUrl(0), 'navRight']) === 'bottom')
&& in_array($this->getUrl(1), $pattern) === false
) {
$this->showNavButtons('bottom');
}
} else {
@ -151,7 +159,7 @@ class layout extends common
}
echo '</div>';
}
echo '</main></section>';
echo '</section></main>';
}
/**
@ -291,8 +299,8 @@ class layout extends common
$label = empty($this->getData(['config', 'poweredPageLabel'])) ? 'Motorisé par' : $this->getData(['config', 'poweredPageLabel']);
$items .= '><wbr>&nbsp;' . $label . '&nbsp;</span>';
// Toujours afficher le nom du CMS
$items .= '<span id="footerZwiiLMS">';
$items .= '<a href="https://forge.chapril.org/fredtempez/ZwiiLMS" onclick="window.open(this.href);return false" >ZwiiLMS</a>';
$items .= '<span id="footerZwiiCampus">';
$items .= '<a href="https://forge.chapril.org/fredtempez/ZwiiCampus" onclick="window.open(this.href);return false" >ZwiiCampus</a>';
$items .= '</span>';
// Affichage du numéro de version
$items .= '<span id="footerDisplayVersion"';
@ -330,7 +338,7 @@ class layout extends common
// Affichage du lien de connexion
if (
($this->getData(['theme', 'footer', 'loginLink'])
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
and $this->isConnected() === false
)
or $this->getUrl(0) === 'theme'
) {
@ -353,9 +361,10 @@ class layout extends common
$items .= '<wbr>&nbsp;|&nbsp;';
if (
$this->getUser('permission', 'filemanager') === true
&& $this->getUser('permission', 'folder', (self::$siteContent === 'home' ? 'homePath' : 'coursePath')) !== 'none'
) {
$items .= '<wbr>' . template::ico('folder', [
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']),
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']) . '&fldr=/' . self::$siteContent,
'margin' => 'all',
'attr' => 'data-lity',
'help' => 'Fichiers du site'
@ -490,38 +499,47 @@ class layout extends common
// Menu extra
$itemsRight = $this->formatMenu(true);
// Lien de connexion
/**
* Commandes pour les membres simples
* Affichage du sélecteur d'espaces
*/
if (
($this->getData(['theme', 'menu', 'loginLink'])
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
)
or $this->getUrl(0) === 'theme'
$this->getUser('group') === self::GROUP_MEMBER
&& $this->getData(['theme', 'menu', 'selectSpace']) === true
) {
$itemsRight .= '<li id="menuLoginLink" ' . ($this->getUrl(0) === 'theme' ? 'class="displayNone"' : '') . '>' .
template::ico('login', [
'href' => helper::baseUrl() . 'user/login/' . strip_tags(str_replace('/', '_', $this->getUrl())),
'help' => "Connexion"
]) .
'</li>';
if ($this->getCoursesByProfil()) {
$itemsRight .= '<li><select id="menuSelectCourse" >';
$itemsRight .= '<option name="' . helper::translate('Accueil') . '" value="' . helper::baseUrl(true) . 'course/swap/home" ' . ('home' === self::$siteContent ? 'selected' : '') . '>' . helper::translate('Accueil') . '</option>';
foreach ($this->getCoursesByProfil() as $courseId => $value) {
$itemsRight .= '<option name="' . $this->getData(['course', $courseId, 'title']) . '" value="' . helper::baseUrl(true) . 'course/swap/' . $courseId . '" ' . ($courseId === self::$siteContent ? 'selected' : '') . '>' . $this->getData(['course', $courseId, 'title']) . '</option>';
}
$itemsRight .= '</select></li>';
}
}
// Commandes pour les membres simples
/**
* Commandes pour les membres simples
* Affichage des boutons gestionnaire de fichiers et mon compte
*/
if (
$this->getUser('group') >= self::GROUP_MEMBER && $this->getUser('group') < self::GROUP_ADMIN
$this->getUser('group') === self::GROUP_MEMBER
&& $this->getData(['theme', 'menu', 'memberBar']) === true
) {
// Affiche l'icône RFM
if (
$this->getUser('group') >= self::GROUP_MEMBER &&
$this->getUser('permission', 'filemanager') === true
&& $this->getUser('permission', 'folder', (self::$siteContent === 'home' ? 'homePath' : 'coursePath')) !== 'none'
) {
$itemsRight .= '<li>' . template::ico('folder', [
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']),
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']) . '&fldr=/' . self::$siteContent,
'attr' => 'data-lity',
'help' => 'Fichiers du site'
]) . '</li>';
}
if (
$this->getUser('permission', 'user', 'edit') === true
) {
// Affiche l'icône d'édition du compte
if ($this->getUser('permission', 'user', 'edit') === true) {
$itemsRight .= '<li>' . template::ico('user', [
'help' => 'Mon compte',
'margin' => 'right',
@ -535,6 +553,22 @@ class layout extends common
'id' => 'barLogout'
]) . '</li>';
}
// Lien de connexion
if (
($this->getData(['theme', 'menu', 'loginLink'])
and $this->isConnected() === false
)
or $this->getUrl(0) === 'theme'
) {
$itemsRight .= '<li id="menuLoginLink" ' . ($this->getUrl(0) === 'theme' ? 'class="displayNone"' : '') . '>' .
template::ico('login', [
'href' => helper::baseUrl() . 'user/login/' . strip_tags(str_replace('/', '_', $this->getUrl())),
'help' => "Connexion"
]) .
'</li>';
}
// Retourne les items du menu
echo '<ul class="navMain" id="menuLeft">' . $itemsLeft . '</ul><ul class="navMain" id="menuRight">' . $itemsRight;
echo '</ul>';
@ -568,9 +602,9 @@ class layout extends common
if (
($this->getData(['page', $parentPageId, 'disable']) === true
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
and $this->isConnected() === false
) or ($this->getData(['page', $parentPageId, 'disable']) === true
and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and $this->isConnected() === true
and $this->getUser('group') < self::GROUP_EDITOR
)
) {
@ -634,9 +668,9 @@ class layout extends common
$items .= '<li id=' . $childKey . '>';
if (
($this->getData(['page', $childKey, 'disable']) === true
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
and $this->isConnected() === false
) or ($this->getData(['page', $childKey, 'disable']) === true
and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and $this->isConnected() === true
and $this->getUser('group') < self::GROUP_EDITOR
)
) {
@ -730,7 +764,7 @@ class layout extends common
$items .= '<li class="menuSideChild">';
if (
$this->getData(['page', $parentPageId, 'disable']) === true
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
and $this->isConnected() === false
) {
$items .= '<a href="' . $this->getUrl(1) . '">';
} else {
@ -754,7 +788,7 @@ class layout extends common
if (
$this->getData(['page', $childKey, 'disable']) === true
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
and $this->isConnected() === false
) {
$itemsChildren .= '<a href="' . $this->getUrl(1) . '">';
} else {
@ -890,26 +924,27 @@ class layout extends common
*/
public function showBar()
{
if ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')) {
if ($this->isConnected() === true) {
// Items de gauche
$leftItems = '';
// Sélecteur de contenu
/**
* Les admins voient tousles contenus
* Les admins voient tous les contenus
* Les enseignants les contenus dont ils sont auteurs
*/
if ($this->getUser('group') >= self::GROUP_EDITOR) {
if ($this->getCoursesByUser($this->getUser('id'), $this->getUser('group'))) {
if (is_array($this->getCoursesByProfil())) {
$leftItems .= '<li><select id="barSelectCourse" >';
$leftItems .= '<option name="' . helper::translate('Accueil') . '" value="' . helper::baseUrl(true) . 'course/swap/home" ' . ('home' === self::$siteContent ? 'selected' : '') . '>' . helper::translate('Accueil') . '</option>';
foreach ($this->getCoursesByUser($this->getUser('id'), $this->getUser('group')) as $key => $value) {
$leftItems .= '<option name="' . $value['title'] . '" value="' . helper::baseUrl(true) . 'course/swap/' . $key . '" ' . ($key === self::$siteContent ? 'selected' : '') . '>' . $value['title'] . '</option>';
foreach ($this->getCoursesByProfil() as $courseId => $value) {
$leftItems .= '<option name="' . $this->getData(['course', $courseId, 'title']) . '" value="' . helper::baseUrl(true) . 'course/swap/' . $courseId . '" ' . ($courseId === self::$siteContent ? 'selected' : '') . '>' . $this->getData(['course', $courseId, 'title']) . '</option>';
}
$leftItems .= '</select></li>';
}
$leftItems .= '<li>' . template::ico('cubes', [
'href' => helper::baseUrl() . 'course',
'help' => 'Contenu'
'help' => 'Gérer les espaces'
]) . '</li>';
}
if ($this->getUser('group') >= self::GROUP_ADMIN) {
@ -918,8 +953,11 @@ class layout extends common
'href' => helper::baseUrl() . 'theme'
]) . '</li>';
}
// Liste des pages
if ($this->getUser('group') >= self::GROUP_EDITOR) {
// Liste des pages et bouton de gestion interdit pour l'accueil sauf admin
if (
($this->getUser('group') === self::GROUP_EDITOR && self::$siteContent != 'home')
|| $this->getUser('group') === self::GROUP_ADMIN
) {
$leftItems .= '<li><select id="barSelectPage">';
$leftItems .= '<option value="">' . helper::translate('Pages du site') . '</option>';
$leftItems .= '<optgroup label="' . helper::translate('Pages orphelines') . '">';
@ -973,7 +1011,7 @@ class layout extends common
// Bouton Ajouter une page
if ($this->getUser('permission', 'page', 'add')) {
$leftItems .= '<li>' . template::ico('plus', [
'href' => helper::baseUrl() . 'page/add',
'href' => helper::baseUrl() . 'page/add/' . self::$siteContent,
'help' => 'Nouvelle page ou barre latérale'
]) . '</li>';
}
@ -990,16 +1028,20 @@ class layout extends common
or $this->getUrl(0) === ''
) {
// Bouton Editer une page
if ($this->getUser('permission', 'page', 'edit')) {
if (
$this->getUser('permission', 'page', 'edit')
and $this->geturl(1) !== 'edit'
) {
$leftItems .= '<li>' . template::ico('pencil', [
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0),
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(0) . '/' . self::$siteContent,
'help' => 'Éditer la page'
]) . '</li>';
}
// Bouton Editer le module d'une page
if (
$this->getUser('permission', 'page', 'module')
&& $this->getData(['page', $this->getUrl(0), 'moduleId'])
and $this->geturl(1) !== 'edit'
and $this->getData(['page', $this->getUrl(0), 'moduleId'])
) {
$leftItems .= '<li>' . template::ico('gear', [
'href' => helper::baseUrl() . $this->getUrl(0) . '/config',
@ -1009,9 +1051,10 @@ class layout extends common
// Bouton dupliquer une page
if (
$this->getUser('permission', 'page', 'duplicate')
and $this->geturl(1) !== 'edit'
) {
$leftItems .= '<li>' . template::ico('clone', [
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(0),
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(0) . '/' . self::$siteContent,
'help' => 'Dupliquer la page'
])
. '</li>';
@ -1019,9 +1062,11 @@ class layout extends common
// Bouton Effacer une page
if (
$this->getUser('permission', 'page', 'delete')
and $this->geturl(1) !== 'edit'
) {
$leftItems .= '<li>' . template::ico('trash', [
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(0),
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(0) . '/' . self::$siteContent,
'help' => 'Supprimer la page',
'id' => 'pageDelete'
])
@ -1032,15 +1077,16 @@ class layout extends common
// Items de droite
$rightItems = '';
if (
$this->getUser('group') >= self::GROUP_EDITOR
&& $this->getUser(
'permission',
'filemanager'
(
$this->getUser('group') === self::GROUP_EDITOR
&& $this->getUser('permission', 'filemanager') === true
&& $this->getUser('permission', 'folder', (self::$siteContent === 'home' ? 'homePath' : 'coursePath')) !== 'none'
)
|| $this->getUser('group') === self::GROUP_ADMIN
) {
$rightItems .= '<li>' . template::ico('folder', [
'help' => 'Fichiers',
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']),
'href' => helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php?type=0&akey=' . md5_file(self::DATA_DIR . 'core.json') . '&lang=' . $this->getData(['user', $this->getUser('id'), 'language']) . '&fldr=/' . self::$siteContent,
'attr' => 'data-lity'
]) . '</li>';
}
@ -1048,22 +1094,18 @@ class layout extends common
self::$siteContent === 'home'
&& $this->getUser('group') >= self::GROUP_ADMIN
) {
$rightItems .= '<li>' . template::ico('puzzle', [
'help' => 'Modules',
'href' => helper::baseUrl() . 'plugin'
]) . '</li>';
$rightItems .= '<li>' . template::ico('flag', [
'help' => 'Langues',
'href' => helper::baseUrl() . 'language'
]) . '</li>';
$rightItems .= '<li>' . template::ico('cog-alt', [
'help' => 'Configuration',
'href' => helper::baseUrl() . 'config'
]) . '</li>';
$rightItems .= '<li>' . template::ico('users', [
'help' => 'Utilisateurs',
'href' => helper::baseUrl() . 'user'
]) . '</li>';
$rightItems .= '<li>' . template::ico('cog-alt', [
'help' => 'Configuration',
'href' => helper::baseUrl() . 'config'
]) . '</li>';
// Mise à jour automatique
$today = mktime(0, 0, 0);
$checkUpdate = $this->getData(['core', 'lastAutoUpdate']);
@ -1075,21 +1117,54 @@ class layout extends common
$today > $checkUpdate + $this->getData(['config', 'autoUpdateDelay', 86400])
) {
// Dernier auto controle
$this->setData(['core', 'lastAutoUpdate', $today]);
$this->setData(['core', 'lastAutoUpdate', $today], false);
if (
helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)
) {
$this->setData(['core', 'updateAvailable', true]);
$this->setData(['core', 'updateAvailable', true], false);
}
// Modules installés
$infoModules = helper::getModules();
// Recherche de mise à jour des modules
$store = plugin::getStore();
if (is_array($store)) {
// Parcourir les données des modules du store
foreach ($store as $key => $value) {
if (empty($key)) {
continue;
}
// Mise à jour d'un module
// Le module est installé et une mise à jour est en ligne
if (
isset($infoModules[$key])
&&
version_compare($infoModules[$key]['version'], $value['version'], '<')
) {
$this->setData(['core', 'updateModuleAvailable', true], false);
}
}
}
// Sauvegarde la base manuellement
$this->saveDB('core');
}
}
// Afficher le bouton : Mise à jour détectée + activée
if ($this->getData(['core', 'updateAvailable'])) {
$rightItems .= '<li><a href="' . helper::baseUrl() . 'install/update" data-tippy-content="Mettre à jour Zwii ' . common::ZWII_VERSION . ' vers ' . helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL) . '">' . template::ico('update colorRed') . '</a></li>';
}
}
if ($this->getData(['core', 'updateModuleAvailable'])) {
$rightItems .= '<li>' . template::ico('puzzle colorRed', [
'help' => 'Modules',
'href' => helper::baseUrl() . 'plugin'
]) . '</li>';
} else {
$rightItems .= '<li>' . template::ico('puzzle', [
'help' => 'Modules',
'href' => helper::baseUrl() . 'plugin'
]) . '</li>';
}
// Boutons depuis le groupe éditeur
if (
$this->getUser('group') >= self::GROUP_EDITOR
&& $this->getUser('permission', 'user', 'edit')
@ -1177,7 +1252,7 @@ class layout extends common
$vars = 'var baseUrl = ' . json_encode(helper::baseUrl(false)) . ';';
$vars .= 'var baseUrlQs = ' . json_encode(helper::baseUrl()) . ';';
if (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
$this->isConnected() === true
and $this->getUser('group') >= self::GROUP_EDITOR
) {
$vars .= 'var privateKey = ' . json_encode(md5_file(self::DATA_DIR . 'core.json')) . ';';

View File

@ -11,16 +11,16 @@ class core extends common
parent::__construct();
// Token CSRF
if (empty($_SESSION['csrf'])) {
$_SESSION['csrf'] = bin2hex(openssl_random_pseudo_bytes(128));
$_SESSION['csrf'] = bin2hex(openssl_random_pseudo_bytes(64));
}
// Fuseau horaire
self::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper
date_default_timezone_set(self::$timezone);
common::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper
date_default_timezone_set(common::$timezone);
// Supprime les fichiers temporaires
$lastClearTmp = mktime(0, 0, 0);
if ($lastClearTmp > $this->getData(['core', 'lastClearTmp']) + 86400) {
$iterator = new DirectoryIterator(self::TEMP_DIR);
$iterator = new DirectoryIterator(common::TEMP_DIR);
foreach ($iterator as $fileInfos) {
if (
$fileInfos->isFile() &&
@ -32,8 +32,6 @@ class core extends common
}
// Date de la dernière suppression
$this->setData(['core', 'lastClearTmp', $lastClearTmp]);
// Enregistre les données
//$this->SaveData();
}
// Backup automatique des données
$lastBackup = mktime(0, 0, 0);
@ -43,11 +41,11 @@ class core extends common
and $this->getData(['user']) // Pas de backup pendant l'installation
) {
// Copie des fichier de données
helper::autoBackup(self::BACKUP_DIR, ['backup', 'tmp', 'file']);
helper::autoBackup(common::BACKUP_DIR, ['backup', 'tmp', 'file']);
// Date du dernier backup
$this->setData(['core', 'lastBackup', $lastBackup]);
// Supprime les backups de plus de 30 jours
$iterator = new DirectoryIterator(self::BACKUP_DIR);
$iterator = new DirectoryIterator(common::BACKUP_DIR);
foreach ($iterator as $fileInfos) {
if (
$fileInfos->isFile()
@ -60,23 +58,23 @@ class core extends common
}
// Crée le fichier de personnalisation avancée
if (file_exists(self::DATA_DIR . 'custom.css') === false) {
file_put_contents(self::DATA_DIR . 'custom.css', ('core/module/theme/resource/custom.css'));
chmod(self::DATA_DIR . 'custom.css', 0755);
if (file_exists(common::DATA_DIR . 'custom.css') === false) {
file_put_contents(common::DATA_DIR . 'custom.css', ('core/module/theme/resource/custom.css'));
chmod(common::DATA_DIR . 'custom.css', 0755);
}
// Crée le fichier de personnalisation
if (file_exists(self::DATA_DIR . self::$siteContent . '/theme.css') === false) {
file_put_contents(self::DATA_DIR . self::$siteContent . '/theme.css', '');
chmod(self::DATA_DIR . self::$siteContent . '/theme.css', 0755);
if (file_exists(common::DATA_DIR . common::$siteContent . '/theme.css') === false) {
file_put_contents(common::DATA_DIR . common::$siteContent . '/theme.css', '');
chmod(common::DATA_DIR . common::$siteContent . '/theme.css', 0755);
}
// Crée le fichier de personnalisation de l'administration
if (file_exists(self::DATA_DIR . 'admin.css') === false) {
file_put_contents(self::DATA_DIR . 'admin.css', '');
chmod(self::DATA_DIR . 'admin.css', 0755);
if (file_exists(common::DATA_DIR . 'admin.css') === false) {
file_put_contents(common::DATA_DIR . 'admin.css', '');
chmod(common::DATA_DIR . 'admin.css', 0755);
}
// Check la version rafraichissement du theme
$cssVersion = preg_split('/\*+/', file_get_contents(self::DATA_DIR . self::$siteContent . '/theme.css'));
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . common::$siteContent . '/theme.css'));
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['theme'])))) {
// Version
$css = '/*' . md5(json_encode($this->getData(['theme']))) . '*/';
@ -92,7 +90,7 @@ class core extends common
// Fonts disponibles
$fontsAvailable['files'] = $this->getData(['font', 'files']);
$fontsAvailable['imported'] = $this->getData(['font', 'imported']);
$fontsAvailable['websafe'] = self::$fontsWebSafe;
$fontsAvailable['websafe'] = common::$fontsWebSafe;
// Fontes installées
$fonts = [
@ -105,53 +103,14 @@ class core extends common
// Suppression des polices identiques
$fonts = array_unique($fonts);
/**
* Charge les fontes websafe
*/
$fontFile = '';
foreach ($fonts as $fontId) {
if (isset($fontsAvailable['websafe'][$fontId])) {
$fonts[$fontId] = $fontsAvailable['websafe'][$fontId]['font-family'];
}
}
/**
* Chargement des polices en ligne dans un fichier font.html inclus dans main.php
*/
$fontFile = '';
$gf = false;
foreach ($fonts as $fontId) {
if (isset($fontsAvailable['imported'][$fontId])) {
$fontFile .= '<link href="' . $fontsAvailable['imported'][$fontId]['resource'] . '" rel="stylesheet">';
// Tableau pour la construction de la feuille de style
$fonts[$fontId] = $fontsAvailable['imported'][$fontId]['font-family'];
$gf = strpos($fontsAvailable['imported'][$fontId]['resource'], 'fonts.googleapis.com') === false ? $gf || false : $gf || true;
}
}
// Ajoute le préconnect des fontes Googles.
$fontFile = $gf ? '<link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>' . $fontFile
: $fontFile;
// Enregistre la personnalisation
if (!is_dir(self::DATA_DIR . 'font')) {
mkdir(self::DATA_DIR . 'font');
}
file_put_contents(self::DATA_DIR . 'font/font.html', $fontFile);
/**
* Fontes installées localement
* Charge les fontes
*/
foreach ($fonts as $fontId) {
// Validité du tableau :
if (isset($fontsAvailable['files'][$fontId])) {
if (file_exists(self::DATA_DIR . 'font/' . $fontId)) {
// Chargement de la police
$css .= '@font-face {font-family:"' . $fontsAvailable['files'][$fontId]['font-family'] . '";';
$css .= 'src: url("' . helper::baseUrl(false) . self::DATA_DIR . 'font/' . $fontsAvailable['files'][$fontId]['resource'] . '");}';
// Tableau pour la construction de la feuille de style
$fonts[$fontId] = $fontsAvailable['files'][$fontId]['font-family'];
} else {
// Le fichier de font n'est pas disponible, fonte par défaut
$fonts[$fontId] = 'verdana';
foreach (['websafe', 'imported', 'files'] as $typeFont) {
if (isset($fontsAvailable[$typeFont][$fontId])) {
$fonts[$fontId] = $fontsAvailable[$typeFont][$fontId]['font-family'];
}
}
}
@ -223,7 +182,7 @@ class core extends common
// Bannière
// Éléments communs
// Eléments communs
if ($this->getData(['theme', 'header', 'margin'])) {
if ($this->getData(['theme', 'menu', 'position']) === 'site-first') {
$css .= 'header{margin:0 20px}';
@ -311,14 +270,8 @@ class core extends common
$css .= '#footerText > p {text-align:' . $this->getData(['theme', 'footer', 'textAlign']) . '}';
$css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}';
// Enregistre les fontes
if (!is_dir(self::DATA_DIR . 'font')) {
mkdir(self::DATA_DIR . 'font');
}
file_put_contents(self::DATA_DIR . 'font/font.html', $fontFile);
// Enregistre la personnalisation
file_put_contents(self::DATA_DIR . self::$siteContent . '/theme.css', $css);
file_put_contents(common::DATA_DIR . common::$siteContent . '/theme.css', $css);
// Effacer le cache pour tenir compte de la couleur de fond TinyMCE
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
@ -329,7 +282,7 @@ class core extends common
}
// Check la version rafraichissement du theme admin
$cssVersion = preg_split('/\*+/', file_get_contents(self::DATA_DIR . 'admin.css'));
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . 'admin.css'));
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['admin'])))) {
// Version
@ -338,7 +291,7 @@ class core extends common
// Fonts disponibles
$fontsAvailable['files'] = $this->getData(['font', 'files']);
$fontsAvailable['imported'] = $this->getData(['font', 'imported']);
$fontsAvailable['websafe'] = self::$fontsWebSafe;
$fontsAvailable['websafe'] = common::$fontsWebSafe;
/**
* Import des polices de caractères
@ -352,44 +305,12 @@ class core extends common
$fonts = array_unique($fonts);
/**
* Charge les fontes websafe
*/
$fontFile = '';
foreach ($fonts as $fontId) {
if (isset($fontsAvailable['websafe'][$fontId])) {
$fonts[$fontId] = $fontsAvailable['websafe'][$fontId]['font-family'];
}
}
/**
* Chargement des polices en ligne dans un fichier font.html inclus dans main.php
*/
$fontFile = '';
foreach ($fonts as $fontId) {
if (isset($fontsAvailable['imported'][$fontId])) {
$fontFile .= '<link href="' . $fontsAvailable['imported'][$fontId]['resource'] . '" rel="stylesheet">';
// Tableau pour la construction de la feuille de style
$fonts[$fontId] = $fontsAvailable['imported'][$fontId]['font-family'];
}
}
// Enregistre la personnalisation
file_put_contents(self::DATA_DIR . 'font/font.html', $fontFile);
/**
* Fontes installées localement
* Charge les fontes
*/
foreach ($fonts as $fontId) {
// Validité du tableau :
if (isset($fontsAvailable['files'][$fontId])) {
if (file_exists(self::DATA_DIR . 'font/' . $fontId)) {
// Chargement de la police
$css .= '@font-face {font-family:"' . $fontsAvailable['files'][$fontId]['font-family'] . '";';
$css .= 'src: url("' . helper::baseUrl(false) . self::DATA_DIR . 'font/' . $fontsAvailable['files'][$fontId]['resource'] . '");}';
// Tableau pour la construction de la feuille de style
$fonts[$fontId] = $fontsAvailable['files'][$fontId]['font-family'];
} else {
// Le fichier de font n'est pas disponible, fonte par défaut
$fonts[$fontId] = 'verdana';
foreach (['websafe', 'imported', 'files'] as $typeFont) {
if (isset($fontsAvailable[$typeFont][$fontId])) {
$fonts[$fontId] = $fontsAvailable[$typeFont][$fontId]['font-family'];
}
}
}
@ -441,11 +362,11 @@ class core extends common
$css .= '.button.buttonGreen, button[type=submit] {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonGreen:hover, button[type=submit]:hover {background-color: ' . $colors['darken'] . ';color: ' . $colors['text'] . ';}.button.buttonGreen:active, button[type=submit]:active {background-color: ' . $colors['darken'] . ';color: ' . $colors['text'] . ';}';
$colors = helper::colorVariants($this->getData(['admin', 'backgroundBlockColor']));
$css .= '.buttonTab, .block {border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . ';}.buttonTab, .block h4 {background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';}';
$css .= 'table tr,input[type=email],input[type=date],input[type=time],input[type=month],input[type=week],input[type=datetime-local],input[type=text],input[type=password],select:not(#barSelectCourse),select:not(#barSelectPage),textarea:not(.editorWysiwyg), textarea:not(.editorWysiwygComment),.inputFile{background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . ';}';
$css .= 'table tr,input[type=email],input[type=date],input[type=time],input[type=month],input[type=week],input[type=datetime-local],input[type=text],input[type=password],select:not(#barSelectCourse),select:not(#menuSelectCourse),select:not(#barSelectPage),textarea:not(.editorWysiwyg), textarea:not(.editorWysiwygComment),.inputFile{background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . ';}';
// Bordure du contour TinyMCE
$css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}';
// Enregistre la personnalisation
file_put_contents(self::DATA_DIR . 'admin.css', $css);
file_put_contents(common::DATA_DIR . 'admin.css', $css);
}
}
/**
@ -461,8 +382,8 @@ class core extends common
require 'core/module/' . $classPath;
}
// Module
elseif (is_readable(self::MODULE_DIR . $classPath)) {
require self::MODULE_DIR . $classPath;
elseif (is_readable(common::MODULE_DIR . $classPath)) {
require common::MODULE_DIR . $classPath;
}
// Librairie
elseif (is_readable('core/vendor/' . $classPath)) {
@ -491,15 +412,23 @@ class core extends common
// Sauvegarde la dernière page visitée par l'utilisateur connecté et enregistre l'historique des consultations
if (
$this->getUser('id')
&& self::$siteContent !== 'home'
&& common::$siteContent !== 'home'
&& in_array($this->getUrl(0), array_keys($this->getData(['page'])))
// Le userId n'est pas celui d'un admis ni le prof du contenu
&& (
$this->getUser('group') < self::GROUP_ADMIN
|| $this->getUser('id') !== $this->getData(['course', self::$siteContent, 'author'])
$this->getUser('group') < common::GROUP_ADMIN
|| $this->getUser('id') !== $this->getData(['course', common::$siteContent, 'author'])
)
) {
$this->setData(['enrolment', self::$siteContent, $this->getUser('id'), 'history', $this->getUrl(0), time()]);
// Stocke la dernière page vue et sa date de consultation
$this->setData(['enrolment', common::$siteContent, $this->getUser('id'), 'lastPageView', $this->getUrl(0)], false);
$this->setData(['enrolment', common::$siteContent, $this->getUser('id'), 'datePageView', time()]);
// Stocke le rapport en CSV
$file = fopen(common::DATA_DIR . common::$siteContent . '/report.csv', 'a+');
fputcsv($file, [$this->getUser('id'), $this->getUrl(0), time()], ';');
fclose($file);
}
// Journalisation
@ -507,8 +436,8 @@ class core extends common
// Force la déconnexion des membres bannis ou d'une seconde session
if (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and ($this->getUser('group') === self::GROUP_BANNED
$this->isConnected() === true
and ($this->getUser('group') === common::GROUP_BANNED
or ($_SESSION['csrf'] !== $this->getData(['user', $this->getUser('id'), 'accessCsrf'])
and $this->getData(['config', 'connect', 'autoDisconnect']) === true)
)
@ -521,9 +450,9 @@ class core extends common
$this->getData(['config', 'maintenance'])
and in_array($this->getUrl(0), ['maintenance', 'user']) === false
and $this->getUrl(1) !== 'login'
and ($this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and $this->getUser('group') < self::GROUP_ADMIN
and ($this->isConnected() === false
or ($this->isConnected() === true
and $this->getUser('group') < common::GROUP_ADMIN
)
)
) {
@ -536,33 +465,12 @@ class core extends common
exit();
}
// Pour éviter une 404 sur une langue étrangère, bascule dans la langue correcte.
if (is_null($this->getData(['page', $this->getUrl(0)]))) {
foreach (self::$languages as $key => $value) {
if (
is_dir(self::DATA_DIR . $key) &&
file_exists(self::DATA_DIR . $key . '/page.json')
) {
$pagesId = json_decode(file_get_contents(self::DATA_DIR . $key . '/page.json'), true);
if (
is_array($pagesId['page']) &&
array_key_exists($this->getUrl(0), $pagesId['page'])
) {
$_SESSION['ZWII_SITE_CONTENT'] = $key;
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl(0));
exit();
}
}
}
}
// Check l'accès à la page
$access = null;
if ($this->getData(['page', $this->getUrl(0)]) !== null) {
if (
$this->getData(['page', $this->getUrl(0), 'group']) === self::GROUP_VISITOR
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
$this->getData(['page', $this->getUrl(0), 'group']) === common::GROUP_VISITOR
or ($this->isConnected() === true
// and $this->getUser('group') >= $this->getData(['page', $this->getUrl(0), 'group'])
// Modification qui tient compte du profil de la page
and ($this->getUser('group') * 10 + $this->getUser('profil')) >= ($this->getData(['page', $this->getUrl(0), 'group']) * 10 + $this->getData(['page', $this->getUrl(0), 'profil']))
@ -579,14 +487,38 @@ class core extends common
// Empêcher l'accès aux pages désactivées par URL directe
if (
($this->getData(['page', $this->getUrl(0), 'disable']) === true
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD')
and $this->isConnected() === false
) or ($this->getData(['page', $this->getUrl(0), 'disable']) === true
and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and $this->getUser('group') < self::GROUP_EDITOR
and $this->isConnected() === true
and $this->getUser('group') < common::GROUP_EDITOR
)
) {
$access = false;
}
// Lève une erreur si l'url est celle d'une page avec des éléments surnuméraires https://www.site.fr/page/truc
if (
array_key_exists($this->getUrl(0), $this->getData(['page']))
and $this->getUrl(1)
and $this->getData(['page', $this->getUrl(0), 'moduleId']) === ''
) {
$access = false;
}
/** Empêche la consultation d'un espace laissé ouvert après la déconnexion et redirige vers home
* L'utilisateur n'est pas connecté
* ET l'accueil n'est pas affiché
* ET l'espace affiché nécessite un compte d'accès, enrolment vaut 1,2 ou 3
* */
if (
$this->isConnected() === false
and self::$siteContent !== 'home'
and $this->getData(['course', self::$siteContent, 'enrolment']) > 0
) {
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
header(header: 'Location:' . helper::baseUrl(true) . 'swap/' . self::$siteContent);
exit();
}
}
/**
@ -608,9 +540,9 @@ class core extends common
$this->getUser('id') &&
$userId !== $this->getUser('id') &&
$this->getData(['user', $userId, 'accessUrl']) === $this->getUrl() &&
array_intersect($t, self::$concurrentAccess) &&
//array_intersect($t, self::$accessExclude) !== false &&
time() < $this->getData(['user', $userId, 'accessTimer']) + self::ACCESS_TIMER
array_intersect($t, common::$concurrentAccess) &&
//array_intersect($t, common::$accessExclude) !== false &&
time() < $this->getData(['user', $userId, 'accessTimer']) + common::ACCESS_TIMER
) {
$access = false;
$accessInfo['userName'] = $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']);
@ -620,10 +552,11 @@ class core extends common
}
// Accès concurrent stocke la page visitée
if (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
$this->isConnected() === true
&& $this->getUser('id')
&& !$this->isPost()
) {
$this->setData(['user', $this->getUser('id'), 'accessUrl', $this->getUrl()]);
$this->setData(['user', $this->getUser('id'), 'accessUrl', $this->getUrl()], false);
$this->setData(['user', $this->getUser('id'), 'accessTimer', time()]);
}
// Breadcrumb
@ -647,10 +580,10 @@ class core extends common
$inlineScript[] = $this->getData(['page', $this->getUrl(0), 'js']) === null ? '' : $this->getData(['page', $this->getUrl(0), 'js']);
// Importe le contenu, le CSS et le script des barres
$contentRight = $this->getData(['page', $this->getUrl(0), 'barRight']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barRight']), self::$siteContent) : '';
$contentRight = $this->getData(['page', $this->getUrl(0), 'barRight']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barRight']), common::$siteContent) : '';
$inlineStyle[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'css']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'css']);
$inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'js']);
$contentLeft = $this->getData(['page', $this->getUrl(0), 'barLeft']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barLeft']), self::$siteContent) : '';
$contentLeft = $this->getData(['page', $this->getUrl(0), 'barLeft']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barLeft']), common::$siteContent) : '';
$inlineStyle[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'css']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'css']);
$inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']);
@ -668,7 +601,7 @@ class core extends common
$this->addOutput([
'title' => $title,
'content' => $this->getPage($this->getUrl(0), self::$siteContent),
'content' => $this->getPage($this->getUrl(0), common::$siteContent),
'metaDescription' => $this->getData(['page', $this->getUrl(0), 'metaDescription']),
'metaTitle' => $this->getData(['page', $this->getUrl(0), 'metaTitle']),
'typeMenu' => $this->getData(['page', $this->getUrl(0), 'typeMenu']),
@ -694,7 +627,7 @@ class core extends common
: $this->getData(['page', $this->getUrl(0), 'metaDescription']);
// Importe le CSS de la page principale
$pageContent = $this->getPage($this->getUrl(0), self::$siteContent);
$pageContent = $this->getPage($this->getUrl(0), common::$siteContent);
$this->addOutput([
'title' => $title,
@ -739,8 +672,8 @@ class core extends common
$output = $module->output;
// Check le groupe de l'utilisateur
if (
($module::$actions[$action] === self::GROUP_VISITOR
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
($module::$actions[$action] === common::GROUP_VISITOR
or ($this->isConnected() === true
and $this->getUser('group') >= $module::$actions[$action]
and $this->getUser('permission', $moduleId, $action)
)
@ -752,10 +685,10 @@ class core extends common
foreach ($_POST as $postId => $postValue) {
if (is_array($postValue)) {
foreach ($postValue as $subPostId => $subPostValue) {
self::$inputBefore[$postId . '_' . $subPostId] = $subPostValue;
common::$inputBefore[$postId . '_' . $subPostId] = $subPostValue;
}
} else {
self::$inputBefore[$postId] = $postValue;
common::$inputBefore[$postId] = $postValue;
}
}
}
@ -795,9 +728,9 @@ class core extends common
// Contenu par vue
elseif ($output['view']) {
// Chemin en fonction d'un module du coeur ou d'un module
$modulePath = in_array($moduleId, self::$coreModuleIds) ? 'core/' : '';
$modulePath = in_array($moduleId, common::$coreModuleIds) ? 'core/' : '';
// CSS
$stylePath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.css';
$stylePath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.css';
if (file_exists($stylePath)) {
$this->addOutput([
'style' => file_get_contents($stylePath)
@ -810,7 +743,7 @@ class core extends common
}
// JS
$scriptPath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.js.php';
$scriptPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.js.php';
if (file_exists($scriptPath)) {
ob_start();
include $scriptPath;
@ -819,7 +752,7 @@ class core extends common
]);
}
// Vue
$viewPath = $modulePath . self::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.php';
$viewPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.php';
if (file_exists($viewPath)) {
ob_start();
include $viewPath;
@ -828,7 +761,7 @@ class core extends common
$this->addOutput([
'content' => ob_get_clean() . ($output['showPageContent'] ? $pageContent : '')
]);
} else if ($modpos === 'free') {
} elseif ($modpos === 'free' && strstr($pageContent, '[MODULE]')) {
if (strstr($pageContent, '[MODULE]', true) === false) {
$begin = strstr($pageContent, '[]', true);
} else {
@ -884,54 +817,65 @@ class core extends common
exit();
}
if ($access === false) {
// Bascule sur le site d'accueil
/*if (
isset($_SESSION['ZWII_SITE_CONTENT'])
&& $_SESSION['ZWII_SITE_CONTENT'] !== 'home'
) {
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
header('Location:' . helper::baseUrl() . $this->getUrl());
exit();
}*/
http_response_code(403);
if ($accessInfo['userName']) {
$this->addOutput([
'title' => 'Accès verrouillé',
'content' => template::speech('<p>'. sprintf(helper::translate('La page %s est ouverte par l\'utilisateur %s</p><p><a style="color:inherit" href="javascript:history.back()">%s</a></p>'), $accessInfo['pageId'], $accessInfo['userName'], helper::translate('Retour')))
'content' => template::speech('<p>' . sprintf(helper::translate('La page %s est ouverte par l\'utilisateur %s</p><p><a style="color:inherit" href="javascript:history.back()">%s</a></p>'), $accessInfo['pageId'], $accessInfo['userName'], helper::translate('Retour')))
]);
} else {
if (
$this->getData(['config', 'page403']) !== 'none'
and $this->getData(['page', $this->getData(['config', 'page403'])])
//and $this->getData(['page', $this->getData(['config', 'page403'])])
) {
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
header('Location:' . helper::baseUrl() . $this->getData(['config', 'page403']));
} else {
$this->addOutput([
'title' => 'Accès interdit',
'content' => template::speech('<p>' . helper::translate('Vous n\'êtes pas autorisé à consulter cette page (erreur 403)') . '</p><p><a style="color:inherit" href="javascript:history.back()">'. helper::translate('Retour') . '</a></p>')
'content' => template::speech('<p>' . helper::translate('Vous n\'êtes pas autorisé à consulter cette page (erreur 403)') . '</p><p><a style="color:inherit" href="javascript:history.back()">' . helper::translate('Retour') . '</a></p>')
]);
}
}
} elseif ($this->output['content'] === '') {
// Bascule sur le site d'accueil pour afficher la page d'erreur
/*if (
isset($_SESSION['ZWII_SITE_CONTENT'])
&& $_SESSION['ZWII_SITE_CONTENT'] !== 'home'
) {
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
header('Location:' . helper::baseUrl() . $this->getUrl());
exit();
}*/
// Pour éviter une 404, bascule dans l'espace correct si la page existe dans cet espace.
// Parcourir les espaces y compris l'accueil
foreach (array_merge(['home' => []], $this->getData(['course'])) as $courseId => $value) {
;
if (
// l'espace existe
is_dir(common::DATA_DIR . $courseId) &&
file_exists(common::DATA_DIR . $courseId . '/page.json')
) {
// Lire les données des pages
$pagesId = json_decode(file_get_contents(common::DATA_DIR . $courseId . '/page.json'), true);
if (
// La page existe
is_array($pagesId['page']) &&
array_key_exists($this->getUrl(0), $pagesId['page'])
) {
// Basculer
$_SESSION['ZWII_SITE_CONTENT'] = $courseId;
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
exit();
}
}
}
// La page n'existe pas dans les esapces, on génére une erreur 404
http_response_code(404);
if (
// une page est définie dans la configuration mais dans home
$this->getData(['config', 'page404']) !== 'none'
and $this->getData(['page', $this->getData(['config', 'page404'])])
) {
// Bascule sur l'acccueil et rediriger
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
header('Location:' . helper::baseUrl() . $this->getData(['config', 'page404']));
} else {
// Page par défaut
$this->addOutput([
'title' => 'Page indisponible',
'content' => template::speech('<p>' . helper::translate('La page demandée n\'existe pas ou est introuvable (erreur 404)') . '</p><p><a style="color:inherit" href="javascript:history.back()">'. helper::translate('Retour') . '</a></p>')
'content' => template::speech('<p>' . helper::translate('La page demandée n\'existe pas ou est introuvable (erreur 404)') . '</p><p><a style="color:inherit" href="javascript:history.back()">' . helper::translate('Retour') . '</a></p>')
]);
}
}
@ -954,25 +898,25 @@ class core extends common
}
switch ($this->output['display']) {
// Layout brut
case self::DISPLAY_RAW:
case common::DISPLAY_RAW:
echo $this->output['content'];
break;
// Layout vide
case self::DISPLAY_LAYOUT_BLANK:
case common::DISPLAY_LAYOUT_BLANK:
require 'core/layout/blank.php';
break;
// Affichage en JSON
case self::DISPLAY_JSON:
case common::DISPLAY_JSON:
header('Content-Type: application/json');
echo json_encode($this->output['content']);
break;
// RSS feed
case self::DISPLAY_RSS:
case common::DISPLAY_RSS:
header('Content-type: application/rss+xml; charset=UTF-8');
echo $this->output['content'];
break;
// Layout allégé
case self::DISPLAY_LAYOUT_LIGHT:
case common::DISPLAY_LAYOUT_LIGHT:
ob_start();
require 'core/layout/light.php';
$content = ob_get_clean();
@ -983,7 +927,7 @@ class core extends common
echo $content;
break;
// Layout principal
case self::DISPLAY_LAYOUT_MAIN:
case common::DISPLAY_LAYOUT_MAIN:
ob_start();
require 'core/layout/main.php';
$content = ob_get_clean();

View File

@ -128,7 +128,17 @@ class SitemapGenerator
*/
private $sampleRobotsLines = [
"User-agent: *",
"Disallow: /",
"User-agent: Googlebot",
"Allow: /",
"User-agent: bingbot",
"Allow: /",
"User-agent: Slurp",
"Allow: /",
"User-agent: DuckDuckBot",
"Allow: /",
"User-agent: Baiduspider",
"Allow: /"
];
/**
* @var array list of valid changefreq values according to the spec

View File

@ -28,7 +28,7 @@ class template
$attributes['value'] = helper::translate($attributes['value']);
$attributes['help'] = helper::translate($attributes['help']);
// Retourne le html
return sprintf(
return sprintf(
'<a %s class="button %s %s %s" %s>%s</a>',
helper::sprintAttributes($attributes, ['class', 'disabled', 'ico', 'value']),
$attributes['disabled'] ? 'disabled' : '',
@ -65,12 +65,12 @@ class template
// Limite addition et soustraction selon le type de captcha
$numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20];
$letters = ['u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a'];
$limit = $attributes['limit'] ? count($letters) - 1 : 10;
$limit = $attributes['limit'] ? count($letters) - 1 : 10;
// Tirage de l'opération
mt_srand();
// Captcha simple limité à l'addition
$operator = $attributes['limit'] ? mt_rand(1, 4) : 1;
$operator = $attributes['limit'] ? mt_rand(1, 4) : 1;
// Limite si multiplication ou division
if ($operator > 2) {
@ -94,15 +94,15 @@ class template
switch ($operator) {
case 1:
$operator = template::ico('plus', ['fontSize' => '2em;']);
$result = $firstNumber + $secondNumber;
$result = $firstNumber + $secondNumber;
break;
case 2:
$operator = template::ico('minus', ['fontSize' => '2em;']);
$result = $firstNumber - $secondNumber;
$result = $firstNumber - $secondNumber;
break;
case 3:
$operator = template::ico('cancel', ['fontSize' => '2em;']);
$result = $firstNumber * $secondNumber;
$result = $firstNumber * $secondNumber;
break;
case 4:
$operator = template::ico('divide', ['fontSize' => '2em;']);
@ -112,7 +112,7 @@ class template
}
mt_srand();
$secondNumber = mt_rand(1, $limit);
$firstNumber = $firstNumber * $secondNumber;
$firstNumber = $firstNumber * $secondNumber;
$result = $firstNumber / $secondNumber;
break;
}
@ -125,8 +125,8 @@ class template
$secondLetter = uniqid();
// Masquage image source pour éviter un décodage
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$firstNumber] . '.png', 'site/tmp/' . $firstLetter . '.png');
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$secondNumber] . '.png', 'site/tmp/' . $secondLetter . '.png');
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$firstNumber] . '.png', 'site/tmp/' . $firstLetter . '.png');
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$secondNumber] . '.png', 'site/tmp/' . $secondLetter . '.png');
// Début du wrapper
@ -134,7 +134,7 @@ class template
// Label
$html .= self::label(
$attributes['id'],
'<img class="captcha' . ucFirst($attributes['type']) . '" src="' . helper::baseUrl(false) . 'site/tmp/' . $firstLetter . '.png" />&nbsp;<strong>' . $operator . '</strong>&nbsp;<img class="captcha' . ucFirst($attributes['type']) . '" src="' . helper::baseUrl(false) . 'site/tmp/' . $secondLetter . '.png" />' . template::ico('eq', ['fontSize' => '2em;']),
'<img class="captcha' . ucFirst($attributes['type']) . '" src="' . helper::baseUrl(false) . 'site/tmp/' . $firstLetter . '.png" />&nbsp;<strong>' . $operator . '</strong>&nbsp;<img class="captcha' . ucFirst($attributes['type']) . '" src="' . helper::baseUrl(false) . 'site/tmp/' . $secondLetter . '.png" />' . template::ico('eq', ['fontSize' => '2em;']),
[
'help' => $attributes['help']
]
@ -224,7 +224,7 @@ class template
* Crée un champ date
* @param string $nameId Nom et id du champ
* @param array $attributes Attributs ($key => $value)
* @param string type date time datetime-local month week
* @param string type date seule ; time heure seule ; datetime-local (jour et heure)
* @return string
*/
public static function date($nameId, array $attributes = [])
@ -244,17 +244,32 @@ class template
'placeholder' => '',
'readonly' => false,
'value' => '',
'type'=> 'date',
'type' => 'date',
], $attributes);
// Traduction de l'aide et de l'étiquette
$attributes['label'] = helper::translate($attributes['label']);
$attributes['help'] = helper::translate($attributes['help']);
//$attributes['placeholder'] = helper::translate($attributes['placeholder']);
// Filtre selon le type
switch ($attributes['type']) {
case 'datetime-local':
$filter = helper::FILTER_TIMESTAMP;
break;
case 'date':
$filter = helper::FILTER_DATE; // Pour générer une valeur uniquement sur la date
break;
case 'time':
$filter = helper::FILTER_TIME; // Pour générer une valeur uniquement sur l'heure
break;
default:
$filter = null; // pas de filtre pour month and year
break;
}
// Sauvegarde des données en cas d'erreur
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
$attributes['value'] = common::$inputBefore[$attributes['id']];
} else {
$attributes['value'] = ($attributes['value'] ? helper::filter($attributes['value'], helper::FILTER_TIMESTAMP) : '');
$attributes['value'] = ($attributes['value'] ? helper::filter($attributes['value'], $filter) : '');
}
// Début du wrapper
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
@ -284,7 +299,7 @@ class template
$html .= '</div>';
// Retourne le html
return $html;
}
}
/**
@ -310,6 +325,7 @@ class template
'name' => $nameId,
'type' => 2,
'value' => '',
'folder' => '',
'language' => 'fr_FR'
], $attributes);
// Traduction de l'aide et de l'étiquette
@ -346,19 +362,21 @@ class template
$html .= sprintf(
'<a
href="' .
helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php' .
'?relative_url=1' .
'&lang=' . $attributes['language'] .
'&field_id=' . $attributes['id'] .
'&type=' . $attributes['type'] .
'&akey=' . md5_file(core::DATA_DIR . 'core.json') .
($attributes['extensions'] ? '&extensions=' . $attributes['extensions'] : '')
. '"
helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php' .
'?relative_url=1' .
'&lang=' . $attributes['language'] .
'&field_id=' . $attributes['id'] .
'&type=' . $attributes['type'] .
'&akey=' . md5_file(core::DATA_DIR . 'core.json') .
// Ajoute le nom du dossier si la variable est passée
(!empty($attributes['folder']) ? '&fldr=' . $attributes['folder'] : '') .
($attributes['extensions'] ? '&extensions=' . $attributes['extensions'] : '')
. '"
class="inputFile %s %s"
%s
data-lity
>
' . self::ico('upload', ['margin' => 'right']) . '
' . self::ico('upload-cloud', ['margin' => 'right']) . '
<span class="inputFileLabel"></span>
</a>',
$attributes['class'],
@ -471,7 +489,7 @@ class template
// Traduction de l'aide
$attributes['help'] = helper::translate($attributes['help']);
// Contenu de l'icône
$alt = $attributes['help'] ? $attributes['help'] : $ico;
$alt = $attributes['help'] ? $attributes['help'] : $ico;
$item = $attributes['href'] ? '<a id="' . $attributes['id'] . '" data-tippy-content="' . $attributes['help'] . '" alt="' . $alt . '" href="' . $attributes['href'] . '" ' . $attributes['attr'] . ' >' : '';
$item .= '<span class="zwiico-' . $ico . ($attributes['margin'] ? ' zwiico-margin-' . $attributes['margin'] : '') . ($attributes['animate'] ? ' animate-spin' : '') . '" style="font-size:' . $attributes['fontSize'] . '"><!----></span>';
$item .= ($attributes['href']) ? '</a>' : '';
@ -486,7 +504,7 @@ class template
*/
public static function flag($langId, $size = 'auto')
{
$lang = 'home';
$lang = 'fr_FR';
switch ($langId) {
case '':
break;
@ -496,6 +514,8 @@ class template
case 'selected':
if (isset($_SESSION['ZWII_SITE_CONTENT'])) {
$lang = $_SESSION['ZWII_SITE_CONTENT'];
} else {
$lang = 'fr_FR';
}
}
return '<img class="flag" src="' . helper::baseUrl(false) . 'core/vendor/i18n/png/' . $lang . '.png"
@ -684,12 +704,12 @@ class template
'label' => '',
'name' => $nameId,
'selected' => '',
'font' => [],
'font' => [],
'multiple' => ''
], $attributes);
// Traduction de l'aide et de l'étiquette
$attributes['label'] = helper::translate($attributes['label']);
$attributes['help'] = helper::translate($attributes['help']);
$attributes['help'] = helper::translate($attributes['help']);
// Stocker les fontes et remettre à zéro le tableau des fontes transmis pour éviter une erreur de sprintAttributes
if (empty($attributes['font']) === false) {
$fonts = $attributes['font'];
@ -726,7 +746,7 @@ class template
);
foreach ($options as $value => $text) {
// Select des liste de fontes
$html .= isset($fonts) ? sprintf(
$html .= isset($fonts) ? sprintf(
'<option value="%s"%s style="font-family: %s;">%s</option>',
$value,
$attributes['selected'] == $value ? ' selected' : '', // Double == pour ignorer le type de variable car $_POST change les types en string
@ -748,6 +768,7 @@ class template
return $html;
}
/**
* Crée une bulle de dialogue
* @param string $text Texte de la bulle
@ -779,7 +800,7 @@ class template
// Traduction de l'aide et de l'étiquette
$attributes['value'] = helper::translate($attributes['value']);
// Retourne le html
return sprintf(
return sprintf(
'<button type="submit" class="%s%s" %s>%s</button>',
$attributes['class'],
$attributes['uniqueSubmission'] ? 'uniqueSubmission' : '',
@ -807,7 +828,7 @@ class template
], $attributes);
// Traduction de l'aide et de l'étiquette
foreach ($head as $value) {
$head[array_search($value, $head)] = helper::translate($value);
$head[array_search($value, $head)] = helper::translate($value);
}
// Début du wrapper
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="tableWrapper ' . $attributes['classWrapper'] . '">';
@ -902,7 +923,7 @@ class template
$html .= self::notice($attributes['id'], $notice);
// Texte
$html .= sprintf(
'<input type="' . $attributes['type']. '" %s>',
'<input type="' . $attributes['type'] . '" %s>',
helper::sprintAttributes($attributes)
);
// Fin du wrapper

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -23,15 +23,15 @@ core.alert = function (text) {
.append(
$("<span>").text(text),
$("<div>")
.addClass("lightboxButtons")
.append(
$("<a>")
.addClass("button")
.text("Ok")
.on("click", function () {
lightbox.close();
})
)
.addClass("lightboxButtons")
.append(
$("<a>")
.addClass("button")
.text("Ok")
.on("click", function () {
lightbox.close();
})
)
)
}(jQuery));
// Validation de la lightbox avec le bouton entrée
@ -67,29 +67,29 @@ core.confirm = function (text, yesCallback, noCallback) {
.append(
$("<span>").text(text),
$("<div>")
.addClass("lightboxButtons")
.append(
$("<a>")
.addClass("button grey")
.text("<?php echo helper::translate('Non');?>")
.on("click", function () {
lightbox.options('button', true);
lightbox.close();
if (typeof noCallback !== "undefined") {
noCallback();
}
}),
$("<a>")
.addClass("button")
.text("<?php echo helper::translate('Oui');?>")
.on("click", function () {
lightbox.options('button', true);
lightbox.close();
if (typeof yesCallback !== "undefined") {
yesCallback();
}
})
)
.addClass("lightboxButtons")
.append(
$("<a>")
.addClass("button grey")
.text("<?php echo helper::translate('Non');?>")
.on("click", function () {
lightbox.options('button', true);
lightbox.close();
if (typeof noCallback !== "undefined") {
noCallback();
}
}),
$("<a>")
.addClass("button")
.text("<?php echo helper::translate('Oui');?>")
.on("click", function () {
lightbox.options('button', true);
lightbox.close();
if (typeof yesCallback !== "undefined") {
yesCallback();
}
})
)
)
}(jQuery));
// Callback lors d'un clic sur le fond et sur la croix de fermeture
@ -216,15 +216,16 @@ core.start = function () {
// Variables des cookies
var getUrl = window.location;
var domain = "domain=" + getUrl.hostname + ";";
var basePath = getUrl.pathname.substring(0, getUrl.pathname.lastIndexOf('/') + 1);
var path = "path=" + basePath + ";";
var e = new Date();
e.setFullYear(e.getFullYear() + 1);
var expires = "expires=" + e.toUTCString();
var expires = "expires=" + e.toUTCString() + ";";
// Stocke le cookie d'acceptation
document.cookie = "ZWII_COOKIE_CONSENT=true;samesite=strict;" + domain + expires;
document.cookie = "ZWII_COOKIE_CONSENT=true; samesite=lax; " + domain + path + expires;
});
/**
* Fermeture de la popup des cookies
*/
@ -291,14 +292,14 @@ core.start = function () {
});
// Confirmation de mise à jour
$("#barUpdate").on("click", function () {
message = "<?php echo helper::translate('Mettre à jour') . ' ?';?>";
message = "<?php echo helper::translate('Mise à jour') . ' ?';?>";
return core.confirm(message, function () {
$(location).attr("href", $("#barUpdate").attr("href"));
});
});
// Confirmation de déconnexion
$("#barLogout").on("click", function () {
message = "<?php echo helper::translate('Se déconnecter') . '?';?>";
message = "<?php echo helper::translate('Se déconnecter') . ' ?';?>";
return core.confirm(message, function () {
$(location).attr("href", $("#barLogout").attr("href"));
});
@ -462,7 +463,7 @@ $(document).ready(function () {
/**
* Chargement paresseux des images et des iframes
*/
$("img,picture,iframe").attr("loading", "lazy");
$("img").attr("loading", "lazy");
/**
* Effet accordéon
@ -525,7 +526,7 @@ $(document).ready(function () {
/**
* Sélection d'une langue du site
* Sélection d'un espace du site
*/
$("select#barSelectCourse").on("change", function () {
// La langue courante ne déclenche pas de chargement
@ -538,14 +539,37 @@ $(document).ready(function () {
var currentUrl = url.href.split("/");
// Change si différent, corrige le problème avec le thème et le rechargement de la langue.
if ((currentUrl !== "?theme" ||
currentUrl !== "theme") &&
currentUrl !== "theme") &&
langSelected[6] !== langSession
) {
//$(location).attr("href", langUrl);
var select = document.getElementById("barSelectCourse");
var selectedOption = select.options[select.selectedIndex];
if (selectedOption.value !== "") {
window.location = selectedOption.value; }
window.location = selectedOption.value;
}
}
});
$("select#menuSelectCourse").on("change", function () {
// La langue courante ne déclenche pas de chargement
var langSelected = $(this).val();
var langSelected = langSelected.split("/");
// Lit le cookie de langue
var langSession = "<?php echo isset($_SESSION['ZWII_SITE_CONTENT']) ? $_SESSION['ZWII_SITE_CONTENT'] : '';?>";
// Découpe l'URL pour exclure le changement de page avec le thème
var url = window.location;
var currentUrl = url.href.split("/");
// Change si différent, corrige le problème avec le thème et le rechargement de la langue.
if ((currentUrl !== "?theme" ||
currentUrl !== "theme") &&
langSelected[6] !== langSession
) {
var select = document.getElementById("menuSelectCourse");
var selectedOption = select.options[select.selectedIndex];
if (selectedOption.value !== "") {
window.location = selectedOption.value;
}
}
});

View File

@ -8,7 +8,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -29,6 +29,7 @@ class common
const GROUP_MEMBER = 1;
const GROUP_EDITOR = 2;
// Groupe MODERATOR, compatibilité avec les anciens modules :
const GROUP_MODERATOR = 2;
const GROUP_ADMIN = 3;
const SIGNATURE_ID = 1;
const SIGNATURE_PSEUDO = 2;
@ -50,7 +51,7 @@ class common
const ACCESS_TIMER = 1800;
// Numéro de version
const ZWII_VERSION = '1.3.02';
const ZWII_VERSION = '1.14.04';
// URL autoupdate
const ZWII_UPDATE_URL = 'https://forge.chapril.org/ZwiiCMS-Team/campus-update/raw/branch/master/';
@ -139,7 +140,7 @@ class common
'zwiico',
//'imagemap',
'simplelightbox',
'datatables'
//'datatables', désactivé par défaut
],
'view' => ''
];
@ -147,24 +148,24 @@ class common
self::GROUP_BANNED => 'Banni',
self::GROUP_VISITOR => 'Visiteur',
self::GROUP_MEMBER => 'Étudiant',
self::GROUP_EDITOR => 'Enseignant',
self::GROUP_EDITOR => 'Formateur',
self::GROUP_ADMIN => 'Administrateur'
];
public static $groupEdits = [
self::GROUP_BANNED => 'Banni',
self::GROUP_MEMBER => 'Étudiant',
self::GROUP_EDITOR => 'Enseignant',
self::GROUP_EDITOR => 'Formateur',
self::GROUP_ADMIN => 'Administrateur'
];
public static $groupNews = [
self::GROUP_MEMBER => 'Étudiant',
self::GROUP_EDITOR => 'Enseignant',
self::GROUP_EDITOR => 'Formateur',
self::GROUP_ADMIN => 'Administrateur'
];
public static $groupPublics = [
self::GROUP_VISITOR => 'Visiteur',
self::GROUP_MEMBER => 'Étudiant',
self::GROUP_EDITOR => 'Enseignant',
self::GROUP_EDITOR => 'Formateur',
self::GROUP_ADMIN => 'Administrateur'
];
@ -175,6 +176,7 @@ class common
public static $i18nUI = 'fr_FR';
// Langues de contenu
public static $siteContent = 'home';
public static $languages = [
'de' => 'Deutsch',
'en_EN' => 'English',
@ -318,31 +320,57 @@ class common
public function __construct()
{
// Construct cache
if (isset($GLOBALS['common_construct'])) {
$this->input['_POST'] = $GLOBALS['common_construct']['input']['_POST'];
$this->input['_COOKIE'] = $GLOBALS['common_construct']['input']['_COOKIE'];
self::$siteContent = $GLOBALS['common_construct']['siteContent'];
$this->dataFiles = $GLOBALS['common_construct']['dataFiles'];
$this->configFiles = $GLOBALS['common_construct']['configFiles'];
$this->user = $GLOBALS['common_construct']['user'];
self::$i18nUI = $GLOBALS['common_construct']['i18nUI'];
$this->hierarchy = $GLOBALS['common_construct']['hierarchy'];
$this->url = $GLOBALS['common_construct']['url'];
self::$dialog = $GLOBALS['common_construct']['dialog'];
return;
}
// Extraction des données http
if (isset($_POST)) {
$this->input['_POST'] = $_POST;
// Cache
$GLOBALS['common_construct']['input']['_POST'] = $this->input['_POST'];
}
if (isset($_COOKIE)) {
$this->input['_COOKIE'] = $_COOKIE;
// Cache
$GLOBALS['common_construct']['input']['_COOKIE'] = $this->input['_COOKIE'];
}
// Extraction de la sesion
// $this->input['_SESSION'] = $_SESSION;
// Déterminer le contenu du site
if (isset($_SESSION['ZWII_SITE_CONTENT'])) {
// Déterminé par la session présente
self::$siteContent = $_SESSION['ZWII_SITE_CONTENT'];
} else {
$_SESSION['ZWII_SITE_CONTENT'] = 'home';
self::$siteContent = 'home';
}
// Cache
$GLOBALS['common_construct']['siteContent'] = self::$siteContent;
// Instanciation de la classe des entrées / sorties
// Les fichiers de configuration
foreach ($this->configFiles as $module => $value) {
$this->initDB($module);
}
// Cache
$GLOBALS['common_construct']['configFiles'] = $this->configFiles;
// Les fichiers des contenus
foreach ($this->contentFiles as $module => $value) {
$this->initDB($module, self::$siteContent);
}
// Cache
$GLOBALS['common_construct']['dataFiles'] = $this->dataFiles;
// Installation fraîche, initialisation de la configuration inexistante
@ -369,6 +397,8 @@ class common
if ($this->user === []) {
$this->user = $this->getData(['user', $this->getInput('ZWII_USER_ID')]);
}
// Cache
$GLOBALS['common_construct']['user'] = $this->user;
// Langue de l'administration si le user est connecté
if ($this->getData(['user', $this->getUser('id'), 'language'])) {
@ -390,13 +420,18 @@ class common
}
// Stocker le cookie de langue pour l'éditeur de texte ainsi que l'url du contenu pour le theme
setcookie('ZWII_UI', self::$i18nUI, time() + 3600, '', '', false, false);
// Stocker l'courseId pour le thème de TinyMCE
//setcookie('ZWII_SITE_CONTENT', self::$siteContent, time() + 3600, '', '', false, false);
setlocale(LC_ALL, self::$i18nUI);
// Cache
$GLOBALS['common_construct']['i18nUI'] = self::$i18nUI;
// Construit la liste des pages parents/enfants
if ($this->hierarchy['all'] === []) {
$this->buildHierarchy();
}
// Cache
$GLOBALS['common_construct']['hierarchy'] = $this->hierarchy;
// Construit l'url
if ($this->url === '') {
@ -406,6 +441,8 @@ class common
$this->url = $this->homePageId();
}
}
// Cache
$GLOBALS['common_construct']['url'] = $this->url;
// Chargement des dialogues
if (!file_exists(self::I18N_DIR . self::$i18nUI . '.json')) {
@ -425,6 +462,8 @@ class common
self::$dialog = array_merge(self::$dialog, $d);
}
}
// Cache
$GLOBALS['common_construct']['dialog'] = self::$dialog;
// Données de proxy
$proxy = $this->getData(['config', 'proxyType']) . $this->getData(['config', 'proxyUrl']) . ':' . $this->getData(['config', 'proxyPort']);
@ -452,8 +491,6 @@ class common
}
/**
* Ajoute les valeurs en sortie
* @param array $output Valeurs en sortie
@ -513,8 +550,10 @@ class common
/**
* Sauvegarde des données
* @param array $keys Clé(s) des données
* @param bool $save Indique si le fichier doit être sauvegardé après modification (par défaut true)
* @return bool Succès de l'opération
*/
public function setData($keys = [])
public function setData($keys = [], $save = true)
{
// Pas d'enregistrement lorsqu'une notice est présente ou tableau transmis vide
if (
@ -542,11 +581,12 @@ class common
$query .= '.' . $keys[$i];
}
// Appliquer la modification, le dernier élément étant la donnée à sauvegarder
$success = is_object($db->set($query, $keys[count($keys) - 1], true));
$success = is_object($db->set($query, $keys[count($keys) - 1], $save));
}
return $success;
}
/**
* Accède aux données
* @param array $keys Clé(s) des données
@ -590,13 +630,13 @@ class common
/**
* Ecrire les données de la page
* @param string pageId
* @param string contenu de la page
* @param array contenu de la page
* @return int nombre d'octets écrits ou erreur
*/
public function setPage($page, $value, $path)
{
return file_put_contents(self::DATA_DIR . $path . '/content/' . $page . '.html', $value);
return $this->secure_file_put_contents(self::DATA_DIR . $path . '/content/' . $page . '.html', $value);
}
@ -612,18 +652,74 @@ class common
}
/**
* Écrit les données dans un fichier avec plusieurs tentatives d'écriture et verrouillage
*
* @param string $filename Le nom du fichier
* @param string $data Les données à écrire dans le fichier
* @param int $flags Les drapeaux optionnels à passer à la fonction $this->secure_file_put_contents
* @return bool True si l'écriture a réussi, sinon false
*/
function secure_file_put_contents($filename, $data, $flags = 0)
{
// Initialise le compteur de tentatives
$attempts = 0;
// Vérifie la longueur des données
$data_length = strlen($data);
// Effectue jusqu'à 5 tentatives d'écriture
while ($attempts < 5) {
// Essaye d'écrire les données dans le fichier avec verrouillage exclusif
$write_result = file_put_contents($filename, $data, LOCK_EX | $flags);
// $now = \DateTime::createFromFormat('U.u', microtime(true));
// file_put_contents("tmplog.txt", '[SecurePut][' . $now->format('H:i:s.u') . ']' . "\r\n", FILE_APPEND);
// Vérifie si l'écriture a réussi
if ($write_result !== false && $write_result === $data_length) {
// Sort de la boucle si l'écriture a réussi
break;
}
// Incrémente le compteur de tentatives
$attempts++;
sleep(1);
}
// Etat de l'écriture
return ($attempts < 5);
}
public function initDB($module, $path = '')
{
// Instanciation de la classe des entrées / sorties
// Constructeur JsonDB;
$this->dataFiles[$module] = new \Prowebcraft\JsonDb([
// Chemin complet vers le fichier JSON
$dir = empty($path) ? self::DATA_DIR : self::DATA_DIR . $path . '/';
$config = [
'name' => $module . '.json',
'dir' => self::DATA_DIR . $path . '/',
'backup' => file_exists('site/data/.backup')
]);
'dir' => $dir,
'backup' => file_exists('site/data/.backup'),
'update' => false,
];
// Instanciation de l'objet et stockage dans dataFiles
$this->dataFiles[$module] = new \Prowebcraft\JsonDb($config);
}
/**
* Cette fonction est liée à saveData
* @param mixed $module
* @return void
*/
public function saveDB($module): void
{
$db = $this->dataFiles[$module];
$db->save();
}
/**
* Initialisation des données sur un contenu ou la page d'accueil
* @param string $course : id du module à générer
@ -706,7 +802,7 @@ class common
* Fonction pour construire le tableau des pages
*/
private function buildHierarchy()
public function buildHierarchy()
{
$pages = helper::arrayColumn($this->getData(['page']), 'position', 'SORT_ASC');
@ -714,10 +810,10 @@ class common
foreach ($pages as $pageId => $pagePosition) {
if (
// Page parent
$this->getData(['page', $pageId, 'parentPageId']) === ''
$this->getData(['page', $pageId, 'parentPageId']) === ""
// Ignore les pages dont l'utilisateur n'a pas accès
and ($this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
or ($this->getUser('authKey') === $this->getInput('ZWII_AUTH_KEY')
//and $this->getUser('group') >= $this->getData(['page', $pageId, 'group'])
// Modification qui tient compte du profil de la page
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil']))
@ -736,21 +832,21 @@ class common
}
// Enfants
foreach ($pages as $pageId => $pagePosition) {
if (
// Page parent
$parentId = $this->getData(['page', $pageId, 'parentPageId'])
// Ignore les pages dont l'utilisateur n'a pas accès
and (
($this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
and $this->getData(['page', $parentId, 'group']) === self::GROUP_VISITOR
(
$this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
and
$this->getData(['page', $parentId, 'group']) === self::GROUP_VISITOR
)
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
//and $this->getUser('group') >= $this->getData(['page', $parentId, 'group'])
//and $this->getUser('group') >= $this->getData(['page', $pageId, 'group'])
// Modification qui tient compte du profil de la page
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $this->$parentId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $this->$parentId, 'profil']))
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $this->$pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil']))
or (
$this->getUser('authKey') === $this->getInput('ZWII_AUTH_KEY')
and
$this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil'])
)
)
@ -934,7 +1030,7 @@ class common
}
/**
* Retourne les permission de l'utilisateur connecté
* Retourne les permissions de l'utilisateur connecté
* @param int $key Clé de la valeur du groupe
* @return string|null
*/
@ -943,7 +1039,7 @@ class common
// Administrateur, toutes les permissions
if ($this->getUser('group') === self::GROUP_ADMIN) {
return true;
} elseif ($this->getUser('group') < 1) { // Groupe sans autorisation
} elseif ($this->getUser('group') <= self::GROUP_VISITOR) { // Groupe sans autorisation
return false;
} elseif (
// Groupe avec profil, consultation des autorisations sur deux clés
@ -967,16 +1063,24 @@ class common
if (class_exists($key1)) {
$module = new $key1;
if (array_key_exists($key2, $module::$actions)) {
// var_dump($this->getUser('group'));
// var_dump($module::$actions[$key2]);
// var_dump($this->getUser('group') >= $module::$actions[$key2]);
return $this->getUser('group') >= $module::$actions[$key2];
}
}
}
return false;
}
}
/**
* @return bool l'utilisateur est connecté true sinon false
*/
public function isConnected()
{
return (
!empty($this->getUser('authKey'))
&&
$this->getUser('authKey') === $this->getInput('ZWII_AUTH_KEY'));
}
/**
* Check qu'une valeur est transmise par la méthode _POST
* @return bool
@ -1067,13 +1171,14 @@ class common
}
// Articles du blog
if (
$this->getData(['page', $parentPageId, 'moduleId']) === 'blog' &&
!empty($this->getData(['module', $parentPageId]))
$this->getData(['page', $parentPageId, 'moduleId']) === 'blog'
&& !empty($this->getData(['module', $parentPageId]))
&& $this->getData(['module', $parentPageId, 'posts'])
) {
foreach ($this->getData(['module', $parentPageId, 'posts']) as $articleId => $article) {
if ($this->getData(['module', $parentPageId, 'posts', $articleId, 'state']) === true) {
$date = $this->getData(['module', $parentPageId, 'posts', $articleId, 'publishedOn']);
$sitemap->addUrl('/' . $parentPageId . '/' . $articleId, new DateTime('@{$date}', new DateTimeZone($timezone)));
$sitemap->addUrl('/' . $parentPageId . '/' . $articleId, DateTime::createFromFormat('U', $date));
$flag = true;
}
}
@ -1096,7 +1201,7 @@ class common
foreach ($this->getData(['module', $childKey, 'posts']) as $articleId => $article) {
if ($this->getData(['module', $childKey, 'posts', $articleId, 'state']) === true) {
$date = $this->getData(['module', $childKey, 'posts', $articleId, 'publishedOn']);
$sitemap->addUrl('/' . $childKey . '/' . $articleId, new DateTime('@{$date}', new DateTimeZone($timezone)));
$sitemap->addUrl('/' . $childKey . '/' . $articleId, DateTime::createFromFormat('U', $date));
$flag = true;
}
}
@ -1165,8 +1270,7 @@ class common
$source_image = imagecreatefromwebp($src);
break;
case 'avif':
$source_image = function_exists('imagecreatefromavif') ? imagecreatefromavif($src) : null;
break;
$source_image = imagecreatefromavif($src);
}
// Image valide
if ($source_image) {
@ -1186,9 +1290,9 @@ class common
return (imagepng($virtual_image, $dest));
case 'image/gif':
return (imagegif($virtual_image, $dest));
case 'webp':
case 'image/webp':
return (imagewebp($virtual_image, $dest));
case 'avif':
case 'image/avif':
return (imageavif($virtual_image, $dest));
}
} else {
@ -1406,7 +1510,7 @@ class common
public function saveLog($message = '')
{
// Journalisation
$dataLog = helper::dateUTF8('%Y %m %d', time(), self::$i18nUI) . ' - ' . helper::dateUTF8('%H:%M', time(), self::$i18nUI);
$dataLog = helper::dateUTF8('%Y%m%d', time(), self::$i18nUI) . ';' . helper::dateUTF8('%H:%M', time(), self::$i18nUI) . ';';
$dataLog .= helper::getIp($this->getData(['config', 'connect', 'anonymousIp'])) . ';';
$dataLog .= empty($this->getUser('id')) ? 'visitor;' : $this->getUser('id') . ';';
$dataLog .= $message ? $this->getUrl() . ';' . $message : $this->getUrl();
@ -1422,29 +1526,53 @@ class common
* Retourne les contenus d'un utilisateur
* @param string $userId identifiant
* @param string $serStatus teacher ou student ou admin
*
* CETTE FONCTION EST UTILISEE PAR LAYOUT
*
*/
public function getCoursesByUser($userId, $userStatus)
public function getCoursesByProfil()
{
$c = $this->getData([('course')]);
switch ($userStatus) {
$courses = $this->getData([('course')]);
$courses = helper::arraycolumn($courses, 'title', 'SORT_ASC');
$filter = array();
switch ($this->getUser('group')) {
case self::GROUP_ADMIN:
return $c;
// Affiche tout
return $courses;
case self::GROUP_EDITOR:
foreach ($c as $courseId => $value) {
if ($this->getData(['course', $courseId, 'author']) !== $userId) {
unset($c[$courseId]);
foreach ($courses as $courseId => $value) {
// Affiche les espaces gérés par l'éditeur, les espaces où il participe et les espaces anonymes
if (
// le membre est inscrit
($this->getData(['enrolment', $courseId]) && array_key_exists($this->getUser('id'), $this->getData(['enrolment', $courseId])))
// Il est l'auteur
|| $this->getUser('id') === $this->getData(['course', $courseId, 'author'])
// Le cours est ouvert
|| $this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST
) {
$filter[$courseId] = $courses[$courseId];
}
}
return $c;
return $filter;
case self::GROUP_MEMBER:
case self::GROUP_VISITOR:
foreach ($c as $courseId => $value) {
$students = $this->getData(['enrolment', $courseId, 'students']);
if (in_array($userId, $students) === false) {
unset($c[$courseId]);
foreach ($courses as $courseId => $value) {
// Affiche les espaces du participant et les espaces anonymes
if (
($this->getData(['enrolment', $courseId]) && array_key_exists($this->getUser('id'), $this->getData(['enrolment', $courseId])))
|| $this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST
) {
$filter[$courseId] = $courses[$courseId];
}
}
return $c;
return $filter;
case self::GROUP_VISITOR:
foreach ($courses as $courseId => $value) {
// Affiche les espaces anonymes
if ($this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST) {
$filter[$courseId] = $courses[$courseId];
}
}
return $filter;
default:
return null;
}

View File

@ -1,5 +1,48 @@
<?php
/**
* Mises à jour suivant les versions de Zwii
* Mises à jour suivant les versions de ZwiiCampus
*/
if (
$this->getData(['core', 'dataVersion']) < 1700
) {
// Supprime la variable path des profils, seul l'accès à l'espace et autorisé.
foreach (['1', '2'] as $group) {
foreach (array_keys($this->getData(['profil', $group])) as $profil) {
if (is_null($this->getData(['profil', $group, $profil, 'folder', 'path'])) === false) {
$path = $this->getData(['profil', $group, $profil, 'folder', 'path']);
$this->setData(['profil', $group, $profil, 'folder', 'homePath', $path]);
$this->setData(['profil', $group, $profil, 'folder', 'coursePath', $path]);
$this->deleteData(['profil', $group, $profil, 'folder', 'path']);
}
}
}
$this->setData(['core', 'dataVersion', 1700]);
}
if (
$this->getData(['core', 'dataVersion']) < 1800
) {
// Parcourir la structure pour écrire dans les fichiers CSV
foreach ($this->getData(['enrolment']) as $courseId => $users) {
$filename = self::DATA_DIR . $courseId . '/report.csv';
$fp = fopen($filename, 'w');
foreach ($users as $userId => $userData) {
$history = array_key_exists('history', $userData) ? $userData['history'] : null;
if (is_array($history)) {
foreach ($history as $pageId => $timestamps) {
foreach ($timestamps as $timestamp) {
fputcsv($fp, [$userId, $pageId, $timestamp], ';');
}
}
}
$this->deleteData(['enrolment', $courseId, $userId, 'history']);
}
fclose($fp);
}
$this->setData(['core', 'dataVersion', 1800]);
}

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -2,7 +2,7 @@
<html prefix="og: http://ogp.me/ns#" lang="fr_FR">
<head>
<meta charset="UTF-8">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-type" content="text/html;">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php $layout->showMetaTitle(); ?>
<?php $layout->showMetaDescription(); ?>
@ -12,6 +12,9 @@
<?php $layout->showVendor(); ?>
<?php $layout->showStyle(); ?>
<?php $layout->showFonts(); ?>
<?php if (file_exists(self::DATA_DIR . 'font/font.css')): ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>font/font.css?<?php echo md5_file(self::DATA_DIR . 'font/font.css'); ?>">
<?php endif; ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/common.css">
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/blank.css">
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR . self::$siteContent; ?>/theme.css?<?php echo md5_file(self::DATA_DIR. self::$siteContent . '/theme.css'); ?>">

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -118,7 +118,7 @@ h3 {
font-size: 1.4em;
}
h4 {
h4, details {
font-size: 1.0em;
}
@ -161,7 +161,8 @@ h4,
p,
hr,
ul,
ol {
ol,
details {
margin: 15px 0;
}
@ -551,6 +552,8 @@ body > nav {
/* Items du menu */
nav a>img {
margin: -4px 0;
vertical-align: middle;
@ -587,6 +590,7 @@ nav ul {
nav li {
display: inline-block;
position: relative;
align-self: center;
}
nav li ul {
@ -604,6 +608,22 @@ nav li ul li {
text-align: left;
}
nav li ul #menuSelectCourse {
text-align: left;
}
nav #menuSelectCourse {
width: 150px;
border: 0;
color: #111112;
font-size: 1em;
background-color: rgba(255, 255, 255, 1);
line-height: 45px;
padding: 5px 10px;
margin: 0px 10px;
}
/*
nav .navSub a{
@ -1108,7 +1128,7 @@ footer #footerSocials .zwiico-twitch:hover {
margin-bottom: 0;
}
.block h4 {
.block h4, details {
margin: -20px -20px 10px -20px;
padding: 10px;
/* background: #ECEFF1;*/

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -2,7 +2,7 @@
<html prefix="og: http://ogp.me/ns#" lang="fr_FR">
<head>
<meta charset="UTF-8">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-type" content="text/html;">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php $layout->showMetaTitle(); ?>
<?php $layout->showMetaDescription(); ?>
@ -12,6 +12,9 @@
<?php $layout->showVendor(); ?>
<?php $layout->showStyle(); ?>
<?php $layout->showFonts(); ?>
<?php if (file_exists(self::DATA_DIR . 'font/font.css')): ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>font/font.css?<?php echo md5_file(self::DATA_DIR . 'font/font.css'); ?>">
<?php endif; ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/common.css">
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/light.css">
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR . self::$siteContent; ?>/theme.css?<?php echo md5_file(self::DATA_DIR. self::$siteContent . '/theme.css'); ?>">

View File

@ -2,7 +2,7 @@
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr_FR">
<head>
<meta charset="UTF-8">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-type" content="text/html;">
<meta name="viewport" content="width=device-width">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="x-apple-disable-message-reformatting">

View File

@ -2,7 +2,7 @@
<html prefix="og: http://ogp.me/ns#" lang="fr_FR">
<head>
<meta charset="UTF-8">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta http-equiv="content-type" content="text/html;">
<meta meta="description=" content="ZwiiCMS le CMS multilingue sans base de données">
<meta name="generator" content="ZiiCMS https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS">
<meta name="viewport" content="width=device-width, initial-scale=1">
@ -13,6 +13,9 @@
<?php $layout->showFavicon(); ?>
<?php $layout->showVendor(); ?>
<?php $layout->showFonts(); ?>
<?php if (file_exists(self::DATA_DIR . 'font/font.css')): ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>font/font.css?<?php echo md5_file(self::DATA_DIR . 'font/font.css'); ?>">
<?php endif; ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/common.css?<?php echo md5_file('core/layout/common.css'); ?>">
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR . self::$siteContent; ?>/theme.css?<?php echo md5_file(self::DATA_DIR . self::$siteContent . '/theme.css'); ?>">
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>custom.css?<?php echo md5_file(self::DATA_DIR . 'custom.css'); ?>">
@ -44,7 +47,7 @@
if (
$this->getData(['theme', 'menu', 'position']) === 'top'
and $this->getData(['theme', 'menu', 'fixed']) === true
and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and $this->isConnected() === true
and $this->getUser('group') > self::GROUP_MEMBER
) {
echo '<nav id="navfixedconnected" >';
@ -130,7 +133,7 @@
)
) : ?>
<!-- Bannière dans le site -->
<?php echo ($this->getData(['theme', 'header', 'linkHomePage']) && $this->getData(['theme', 'header', 'feature']) === 'wallpaper') ? '<a href="' . helper::baseUrl(false) . '">' : ''; ?>
<?php echo ($this->getData(['theme', 'header', 'linkHomePage']) && $this->getData(['theme', 'header', 'feature']) === 'wallpaper') ? '<a href="' . helper::baseUrl(true) . 'course/swap/home">' : ''; ?>
<?php
$headerClass = $this->getData(['theme', 'header', 'position']) === 'hide' ? 'displayNone' : '';
$headerClass .= $this->getData(['theme', 'header', 'tinyHidden']) ? ' bannerDisplay ' : '';

View File

@ -9,7 +9,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -22,7 +22,7 @@ class config extends common
'copyBackups' => self::GROUP_ADMIN,
'delBackups' => self::GROUP_ADMIN,
'configMetaImage' => self::GROUP_ADMIN,
'siteMap' => self::GROUP_ADMIN,
'sitemap' => self::GROUP_ADMIN,
'index' => self::GROUP_ADMIN,
'restore' => self::GROUP_ADMIN,
'updateBaseUrl' => self::GROUP_ADMIN,
@ -30,7 +30,8 @@ class config extends common
'logReset' => self::GROUP_ADMIN,
'logDownload' => self::GROUP_ADMIN,
'blacklistReset' => self::GROUP_ADMIN,
'blacklistDownload' => self::GROUP_ADMIN
'blacklistDownload' => self::GROUP_ADMIN,
'register' => self::GROUP_ADMIN,
];
public static $timezones = [
@ -213,7 +214,7 @@ class config extends common
* Sitemap compressé et non compressé
* Robots.txt
*/
public function siteMap()
public function sitemap()
{
// La page n'existe pas
if (
@ -429,6 +430,17 @@ class config extends common
*/
public function index()
{
// Action interdite hors de l'espace accueil
if (
self::$siteContent !== 'home'
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
}
// Soumission du formulaire
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
@ -468,7 +480,7 @@ class config extends common
'poweredPageLabel' => empty($this->getInput('configLocalePoweredPageLabel', helper::FILTER_STRING_SHORT)) ? 'Motorisé par' : $this->getInput('configLocalePoweredPageLabel', helper::FILTER_STRING_SHORT),
'searchPageLabel' => empty($this->getInput('configLocaleSearchPageLabel', helper::FILTER_STRING_SHORT)) ? 'Rechercher' : $this->getInput('configLocaleSearchPageLabel', helper::FILTER_STRING_SHORT),
'legalPageLabel' => empty($this->getInput('configLocaleLegalPageLabel', helper::FILTER_STRING_SHORT)) ? 'Mentions légales' : $this->getInput('configLocaleLegalPageLabel', helper::FILTER_STRING_SHORT),
'sitemapPageLabel' => empty($this->getInput('configLocaleSitemapPageLabel', helper::FILTER_STRING_SHORT)) ? 'Plan du contenu' : $this->getInput('configLocaleSitemapPageLabel', helper::FILTER_STRING_SHORT),
'sitemapPageLabel' => empty($this->getInput('configLocaleSitemapPageLabel', helper::FILTER_STRING_SHORT)) ? 'Sommaire' : $this->getInput('configLocaleSitemapPageLabel', helper::FILTER_STRING_SHORT),
'metaDescription' => $this->getInput('configLocaleMetaDescription', helper::FILTER_STRING_LONG, true),
'title' => $this->getInput('configLocaleTitle', helper::FILTER_STRING_SHORT, true),
'cookies' => [
@ -479,7 +491,7 @@ class config extends common
'cookiesFooterText' => $this->getInput('configLocaleCookiesFooterText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
'buttonValidLabel' => $this->getInput('configLocaleCookiesButtonText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
],
'social' => [
'social' => [
'facebookId' => $this->getInput('socialFacebookId'),
'linkedinId' => $this->getInput('socialLinkedinId'),
'instagramId' => $this->getInput('socialInstagramId'),
@ -545,7 +557,7 @@ class config extends common
) {
// Ajout des lignes dans le .htaccess
$fileContent = file_get_contents('.htaccess');
$rewriteData = PHP_EOL .
$rewriteData =
'# URL rewriting' . PHP_EOL .
'<IfModule mod_rewrite.c>' . PHP_EOL .
"\tRewriteEngine on" . PHP_EOL .
@ -554,7 +566,7 @@ class config extends common
"\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL .
"\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL .
'</IfModule>' . PHP_EOL .
'# URL rewriting' . PHP_EOL;
'# URL rewriting';
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
file_put_contents(
'.htaccess',
@ -581,7 +593,7 @@ class config extends common
}
}
// Générer robots.txt et sitemap
$this->siteMap();
$this->sitemap();
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Configuration'),
@ -607,7 +619,7 @@ class config extends common
// Variable de version
if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) {
self::$updateButtonText = helper::translate('Mettre à jour');
self::$updateButtonText = helper::translate('Mise à jour');
}
@ -946,4 +958,40 @@ class config extends common
]);
}
}
/**
* Fonction pour vérifier la présence du module de réécriture
* @return bool
*/
public function isModRewriteEnabled() {
// Check if Apache and mod_rewrite is loaded
if (function_exists('apache_get_modules')) {
$modules = apache_get_modules();
return in_array('mod_rewrite', $modules);
} else {
// Fallback if not using Apache or unable to detect modules
return getenv('HTTP_MOD_REWRITE') == 'On' || getenv('REDIRECT_STATUS') == '200';
}
}
/**
* Stocke la variable dans les paramètres de l'utilisateur pour activer la tab à sa prochaine visite
* @return never
*/
public function register(): void
{
$this->setData([
'user',
$this->getUser('id'),
'view',
[
'config' => $this->getUrl(2),
'page' => $this->getData(['user', $this->getUser('id'), 'view', 'page']),
]
]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'config/' . $this->getUrl(2),
]);
}
}

View File

@ -0,0 +1,4 @@
<Files "data.key">
Order Allow,Deny
Deny from all
</Files>

View File

@ -0,0 +1,68 @@
<?php
/*
Ce script PHP est conçu pour être appelé via une requête HTTP GET avec une clé spécifique pour déclencher la création d'une archive ZIP de sauvegarde.
Exemple d'appel dans une URL :
http://example.com/chemin/vers/autobackup.php?key=your_secret_key&filter=site
La clé doit être fournie en tant que paramètre "key" dans l'URL et correspondre à celle stockée dans le fichier "data.key" pour que la création de l'archive soit autorisée. Si la clé est valide, le script parcourt le répertoire spécifié en fonction du paramètre "filter" et ajoute les fichiers à l'archive ZIP. Si la clé est invalide ou absente, le script renvoie une réponse avec le code d'erreur 401 Unauthorized.
Le paramètre "filter" en GET permet de spécifier le filtre à appliquer lors de la création de l'archive. Sa valeur peut être "file" ou "data". Si le paramètre n'est pas spécifié, le filtre est vide par défaut, ce qui signifie que tous les fichiers seront inclus dans l'archive.
*/
// Vérification de la clé
if (isset($_GET['key'])) {
$key = $_GET['key'];
$storedKey = file_get_contents('data.key');
if ($key !== $storedKey) {
http_response_code(401); // Clé invalide, renvoie une réponse avec le code d'erreur 401 Unauthorized
echo 'Clé incorrecte';
exit;
}
// Définition du filtre par défaut
$filter = ['backup', 'tmp', 'i18n'];
// Tableau de correspondance entre les valeurs de "filter" et les répertoires à inclure
$filterDirectories = [
'file' => ['backup', 'tmp', 'file'],
'data' => ['backup', 'tmp', 'data'],
];
// Vérification et traitement du paramètre "filter" en GET
if (isset($_GET['filter']) && isset($filterDirectories[$_GET['filter']])) {
$filter = $filterDirectories[$_GET['filter']];
}
// Création du ZIP
$fileName = date('Y-m-d-H-i-s', time()) . '-rolling-backup.zip';
$zip = new ZipArchive();
$zip->open('../../../../site/backup/' . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$directory = '../../../../site';
$files = new RecursiveIteratorIterator(
new RecursiveCallbackFilterIterator(
new RecursiveDirectoryIterator(
$directory,
RecursiveDirectoryIterator::SKIP_DOTS
),
function ($fileInfo, $key, $iterator) use ($filter) {
return $fileInfo->isFile() || !in_array($fileInfo->getBaseName(), $filter);
}
)
);
foreach ($files as $name => $file) {
if (!$file->isDir()) {
$filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen(realpath($directory)) + 1);
$zip->addFile($filePath, $relativePath);
}
}
$zip->close();
http_response_code(201); // Création de l'archive réussie, renvoie une réponse avec le code 201 Created
echo 'Sauvegarde terminée';
exit;
}
?>

View File

@ -0,0 +1,52 @@
<?php
/*
Ce script PHP est conçu pour supprimer les fichiers ayant l'extension 'tar.gz' dans un répertoire de sauvegarde si leur dernière modification remonte à un certain nombre de jours spécifié via une requête HTTP GET.
Exemple d'appel dans une URL avec le nombre de jours spécifié :
http://example.com/chemin/vers/script.php?days=7&key=your_secret_key
Le script vérifie également la présence et la validité d'une clé spécifique pour déclencher son exécution. La clé doit être fournie en tant que paramètre "key" dans l'URL et correspondre à celle stockée dans le fichier "data.key" pour que la suppression des fichiers soit autorisée. Si la clé est invalide ou absente, le script affiche un message d'erreur et termine son exécution.
*/
// Vérification de la clé
if (isset ($_GET['key'])) {
// Récupération de la clé fournie en GET
$key = $_GET['key'];
// Récupération de la clé stockée dans le fichier data.key
$storedKey = file_get_contents('data.key');
// Vérification de correspondance entre les clés
if ($key !== $storedKey) {
http_response_code(401);
echo 'Clé incorrecte';
exit;
}
// Récupère le nombre de jours à partir de la variable GET 'days'
$days = isset ($_GET['days']) ? (int) $_GET['days'] : 1; // Par défaut à 1 si non spécifié
// Chemin vers le répertoire contenant les fichiers
$directory = '../../../../site/backup/'; // Remplacez par le chemin réel
// Convertit le nombre de jours en secondes
$timeLimit = strtotime("-$days days");
// Crée un nouvel objet DirectoryIterator
foreach (new DirectoryIterator($directory) as $file) {
// Vérifie si l'élément courant est un fichier et a l'extension 'tar.gz'
if ($file->isFile() && $file->getExtension() === 'tar.gz') {
// Vérifie si le fichier a été modifié avant la limite de temps
if ($file->getMTime() < $timeLimit) {
// Supprime le fichier
unlink($file->getRealPath());
}
}
}
// Si la clé est manquante, affiche un message d'erreur et arrête l'exécution du script
http_response_code(201);
echo 'Sauvegarde terminée';
exit;
}

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -5,8 +5,8 @@
* file that was distributed with this source code.
*
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
$(document).ready((function(){$("#configBackupForm").submit((function(e){e.preventDefault();var url="<?php echo helper::baseUrl() . $this->getUrl(0); ?>/backup",message_success="<?php echo helper::translate('Sauvegarde générée avec succès.'); ?>",message_error="<?php echo helper::translate('Erreur : sauvegarde non générée !'); ?>",message_title="<?php echo helper::translate('Sauvegarder'); ?>";$.ajax({type:"POST",url:url,data:$("form").serialize(),success:function(data){$("body, .button").css("cursor","default"),core.alert(message_success)},error:function(data){$("body, .button").css("cursor","default"),core.alert(message_error)},complete:function(){$("#configBackupSubmit").removeClass("disabled").prop("disabled",!1),$("#configBackupSubmit").removeClass("uniqueSubmission").prop("uniqueSubmission",!1),$("#configBackupSubmit span").removeClass("zwiico-spin animate-spin"),$("#configBackupSubmit span").addClass("zwiico-check zwiico-margin-right").text(message_title)}})})),$("#configBackupSubmit").on("click",(function(){if($("input[name=configBackupOption]").is(":checked")){var message_warning="<?php echo helper::translate('La sauvegarde des fichiers peut prendre du temps. Continuer ?'); ?>";return core.confirm(message_warning,(function(){$("body, .button").css("cursor","wait"),$("form#configBackupForm").submit()}))}}))}));
$(document).ready((function(){$("#configBackupForm").submit((function(e){e.preventDefault();var url="<?php echo helper::baseUrl() . $this->getUrl(0); ?>/backup",message_success="<?php echo helper::translate('Sauvegarde générée avec succès'); ?>",message_error="<?php echo helper::translate('Erreur : sauvegarde non générée !'); ?>",message_title="<?php echo helper::translate('Sauvegarder'); ?>";$.ajax({type:"POST",url:url,data:$("form").serialize(),success:function(data){$("body, .button").css("cursor","default"),core.alert(message_success)},error:function(data){$("body, .button").css("cursor","default"),core.alert(message_error)},complete:function(){$("#configBackupSubmit").removeClass("disabled").prop("disabled",!1),$("#configBackupSubmit").removeClass("uniqueSubmission").prop("uniqueSubmission",!1),$("#configBackupSubmit span").removeClass("zwiico-spin animate-spin"),$("#configBackupSubmit span").addClass("zwiico-check zwiico-margin-right").text(message_title)}})})),$("#configBackupSubmit").on("click",(function(){if($("input[name=configBackupOption]").is(":checked")){var message_warning="<?php echo helper::translate('La sauvegarde des fichiers peut prendre du temps. Continuer ?'); ?>";return core.confirm(message_warning,(function(){$("body, .button").css("cursor","wait"),$("form#configBackupForm").submit()}))}}))}));

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -5,7 +5,7 @@
* file that was distributed with this source code.
*
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -66,11 +66,12 @@ $(document).ready(function () {
$("#connectCaptchaStrong").prop("checked", false);
}
var configLayout = getCookie("configLayout");
if (configLayout == null) {
configLayout = "locale";
setCookie("configLayout", "locale");
}
var configLayout = "<?php echo $this->getData(['user', $this->getUser('id'), 'view', 'config']);?>";
// Non défini, valeur par défaut
if (configLayout == "") {
configLayout = "setup";
}
$("#localeContainer").hide();
$("#socialContainer").hide();
$("#connectContainer").hide();
@ -168,7 +169,6 @@ $(document).ready(function () {
$("#configSocialButton").removeClass("activeButton");
$("#configConnectButton").removeClass("activeButton");
$("#configNetworkButton").removeClass("activeButton");
setCookie("configLayout", "locale");
});
$("#configSetupButton").on("click", function () {
$("#localeContainer").hide();
@ -181,7 +181,6 @@ $(document).ready(function () {
$("#configSocialButton").removeClass("activeButton");
$("#configConnectButton").removeClass("activeButton");
$("#configNetworkButton").removeClass("activeButton");
setCookie("configLayout", "setup");
});
$("#configSocialButton").on("click", function () {
@ -195,7 +194,6 @@ $(document).ready(function () {
$("#configSocialButton").addClass("activeButton");
$("#configConnectButton").removeClass("activeButton");
$("#configNetworkButton").removeClass("activeButton");
setCookie("configLayout", "social");
});
$("#configConnectButton").on("click", function () {
$("#setupContainer").hide();
@ -208,7 +206,6 @@ $(document).ready(function () {
$("#configSocialButton").removeClass("activeButton");
$("#configConnectButton").addClass("activeButton");
$("#configNetworkButton").removeClass("activeButton");
setCookie("configLayout", "connect");
});
$("#configNetworkButton").on("click", function () {
$("#setupContainer").hide();
@ -221,7 +218,6 @@ $(document).ready(function () {
$("#configSocialButton").removeClass("activeButton");
$("#configConnectButton").removeClass("activeButton");
$("#configNetworkButton").addClass("activeButton");
setCookie("configLayout", "network");
});
@ -308,27 +304,6 @@ $(document).ready(function () {
});
function setCookie(name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/; samesite=lax";
}
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
// Define function to capitalize the first letter of a string
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);

View File

@ -7,44 +7,35 @@
'value' => template::ico('home')
]); ?>
</div>
<div class="col1">
<?php /**echo template::button('configHelp', [
'class' => 'buttonHelp',
'href' => 'https://doc.zwiicms.fr/configuration-du-site',
'target' => '_blank',
'value' => template::ico('help'),
'help' => 'Consulter l\'aide en ligne'
]); */?>
</div>
<div class="col2 offset8">
<div class="col2 offset9">
<?php echo template::submit('Submit'); ?>
</div>
</div>
<div class="tab">
<?php echo template::button('configLocaleButton', [
'value' => 'Identité - Etiquettes',
'value' => 'Identité - Étiquettes',
'class' => 'buttonTab'
]); ?>
<?php echo template::button('configSetupButton', [
'value' => 'Configuration - Outils',
'class' => 'buttonTab'
'value' => 'Configuration',
'class' => 'buttonTab',
//'href' => helper::baseUrl() . 'config/register/setup'
]); ?>
<?php echo template::button('configSocialButton', [
'value' => 'Réseaux sociaux',
'class' => 'buttonTab'
'value' => 'Référencement',
'class' => 'buttonTab',
//'href' => helper::baseUrl() . 'config/register/social'
]); ?>
<?php echo template::button('configConnectButton', [
'value' => 'Sécurité',
'class' => 'buttonTab'
'value' => 'Connexion',
'class' => 'buttonTab',
//'href' => helper::baseUrl() . 'config/register/connect'
]); ?>
<?php echo template::button('configNetworkButton', [
'value' => 'Réseau',
'class' => 'buttonTab'
'class' => 'buttonTab',
//'href' => helper::baseUrl() . 'config/register/network'
]); ?>
</div>
<?php include('core/module/config/view/locale/locale.php') ?>
<?php include('core/module/config/view/setup/setup.php') ?>

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -47,7 +47,7 @@
<?php echo template::select('configLocaleHomePageId', helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC'), [
'label' => 'Page d\'accueil de la plate-forme',
'selected' => $this->homePageId(),
'help' => 'Ce n\'est pas la page d\'accueil d\'un contenu.'
'help' => 'Ce n\'est pas la page d\'accueil d\'un espace.'
]); ?>
</div>
<div class="col4">
@ -98,7 +98,7 @@
<h4>
<?php echo helper::translate('Étiquettes des pages spéciales'); ?>
<!--<span id="labelHelpButton" class="helpDisplayButton" title="Cliquer pour consulter l'aide en ligne">
<a href="https://doc.zwiicms.fr/etiquettes-des-pages-speciales" target="_blank">
<a href="https://doc.zwiicms.fr/Étiquettes-des-pages-speciales" target="_blank">
<?php //echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>-->
@ -129,8 +129,8 @@
<div class="row">
<div class="col4 offset2">
<?php echo template::text('configLocaleSitemapPageLabel', [
'label' => 'Plan du contenu',
'placeholder' => 'Plan du contenu',
'label' => 'Sommaire',
'placeholder' => 'Sommaire',
'value' => $this->getData(['config', 'sitemapPageLabel']),
]); ?>
</div>

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -5,7 +5,7 @@
* file that was distributed with this source code.
*
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
'value' => template::ico('left')
]); ?>
</div>
<div class="col2 offset8">
<div class="col2 offset9">
<?php echo template::submit('configManageSubmit', [
'value' => 'Valider',
'ico' => 'check'

View File

@ -3,12 +3,6 @@
<div class="col12">
<div class="block">
<h4><?php echo helper::translate('Paramètres'); ?>
<!--<span id="setupHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/parametres" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']);
?>
</a>-->
</span>
</h4>
<div class="row">
<div class="col4">
@ -17,7 +11,8 @@
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
'help' => 'Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.',
'label' => 'Favicon',
'value' => $this->getData(['config', 'favicon'])
'value' => $this->getData(['config', 'favicon']),
'folder' => $this->getData(['config', 'favicon']) ? dirname($this->getData(['config', 'favicon'])) : ''
]); ?>
</div>
<div class="col4">
@ -26,7 +21,8 @@
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
'help' => 'Sélectionnez une icône adaptée à un thème sombre.<br>Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.',
'label' => 'Favicon thème sombre',
'value' => $this->getData(['config', 'faviconDark'])
'value' => $this->getData(['config', 'faviconDark']),
'folder' => $this->getData(['config', 'faviconDark']) ? dirname($this->getData(['config', 'faviconDark'])) : ''
]); ?>
</div>
<div class="col4">
@ -47,8 +43,8 @@
<div class="col6">
<?php echo template::checkbox('configRewrite', true, 'Apache URL intelligentes', [
'checked' => helper::checkRewrite(),
'help' => 'Supprime le point d\'interrogation dans les URL, l\'option est indisponible avec les autres serveurs Web',
'disabled' => stripos($_SERVER["SERVER_SOFTWARE"], 'nginx')
'help' => 'Supprime le point d\'interrogation dans les URL, l\'option est indisponible avec les autres serveurs Web',
'disabled' => stripos($_SERVER["SERVER_SOFTWARE"], 'Apache') === false and $module->isModRewriteEnabled()
]); ?>
</div>
</div>
@ -59,12 +55,6 @@
<div class="col12">
<div class="block">
<h4><?php echo helper::translate('Mise à jour automatisée'); ?>
<!--<span id="updateHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/mise-a-jour" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']);
?>
</a>
</span>-->
</h4>
<div class="row">
<div class="col6">
@ -90,8 +80,8 @@
]); ?>
</div>
<div class="col3 offset1 verticalAlignBottom">
<pre>Version installée : <strong><?php echo common::ZWII_VERSION ; ?></strong></pre>
<pre>Version en ligne : <strong><?php echo helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL) ; ?></strong></pre>
<pre>Version installée : <strong><?php echo common::ZWII_VERSION; ?></strong></pre>
<pre>Version en ligne : <strong><?php echo helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL); ?></strong></pre>
</div>
<div class="col3 offset2 verticalAlignBottom">
<?php echo template::button('configUpdateForced', [
@ -109,12 +99,6 @@
<div class="col12">
<div class="block">
<h4><?php echo helper::translate('Maintenance'); ?>
<!--<span id="maintenanceHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/mode-maintenance" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']);
?>
</a>
</span>-->
</h4>
<div class="row">
<div class="col6">
@ -169,12 +153,6 @@
<div class="col12">
<div class="block">
<h4><?php echo helper::translate('Scripts externes'); ?>
<!--<span id="specialeHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/scripts-externes" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']);
?>
</a>
</span>-->
</h4>
<div class="row">
<div class="col4 offset1 verticalAlignBottom">
@ -198,13 +176,21 @@
<div class="row">
<div class="col12">
<div class="block">
<h4>ZwiiCMS <a href="https://zwiicms.fr" target="_blank">Site Web</a> - <a href="https://forum.zwiicms.fr" target="_blank">Forum</a>
<h4>ZwiiCMS <a href="https://zwiicms.fr" target="_blank">Site Web</a> - <a
href="https://forum.zwiicms.fr" target="_blank">Forum</a>
</h4>
<div class="row textAlignCenter">
<div class="col12">
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img alt="Licence Creative Commons" style="border-width:0" src="https://i.creativecommons.org/l/by-nc-nd/4.0/88x31.png" /></a>
<p>Cette œuvre est mise à disposition selon les termes de la <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/">Licence Creative Commons Attribution - Pas d&#39;Utilisation Commerciale - Pas de Modification 4.0 International.</a></p>
<p>Pour voir une copie de cette licence, visitez http://creativecommons.org/licenses/by-nc-nd/4.0/ ou écrivez à Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.</p>
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img
alt="Licence Creative Commons" style="border-width:0"
src="https://i.creativecommons.org/l/by-nc-nd/4.0/88x31.png" /></a>
<p>Cette œuvre est mise à disposition selon les termes de la <a rel="license"
href="http://creativecommons.org/licenses/by-nc-nd/4.0/">Licence Creative Commons
Attribution - Pas d&#39;Utilisation Commerciale - Pas de Modification 4.0
International.</a></p>
<p>Pour voir une copie de cette licence, visitez
http://creativecommons.org/licenses/by-nc-nd/4.0/ ou écrivez à Creative Commons, PO Box
1866, Mountain View, CA 94042, USA.</p>
</div>
</div>
</div>

View File

@ -4,11 +4,6 @@
<div class="block">
<h4>
<?php echo helper::translate('Capture d\'écran Open Graph'); ?>
<!--<span id="specialeHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/referencement" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>-->
</h4>
<div class="row">
<div class="col6">
@ -18,29 +13,30 @@
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
'label' => 'Image Open Graph',
'value' => $this->getData(['config', 'seo', 'openGraphImage']),
'folder' => $this->getData(['config', 'seo', 'openGraphImage']) ? dirname($this->getData(['config', 'seo', 'openGraphImage'])) : '',
'type' => 1,
'help' => sprintf('%s : JPG - PNG<br />', helper::translate('Format')) .
sprintf('%s : 1200 x 630 pixels<br />', helper::translate('Dimensions minimales')) .
sprintf('%s : 1.91:1<br />', helper::translate('Ratio')) .
sprintf('%s : %s, %s<br />', helper::translate('Taille maximale du fichier'), helper::translate('5 Mo pour les images JPEG'), helper::translate('1 Mo pour les images PNG'))
'help' => sprintf('%s : JPG - PNG<br />', helper::translate('Format')) .
sprintf('%s : 1200 x 630 pixels<br />', helper::translate('Dimensions minimales')) .
sprintf('%s : 1.91:1<br />', helper::translate('Ratio')) .
sprintf('%s : %s, %s<br />', helper::translate('Taille maximale du fichier'), helper::translate('5 Mo pour les images JPEG'), helper::translate('1 Mo pour les images PNG'))
]); ?>
</div>
</div>
<div class="row">
<div class="col10 textAlignCenter">
<?php if( $module::$imageOpenGraph['type']): ?>
<p>
<?php echo sprintf('%s : <span id="screenType">%s</span>', helper::translate('Format'), $module::$imageOpenGraph['type']); ?>
</p>
<p>
<?php echo sprintf('%s : <span id="screenWide">%s</span> x <span id="screenHeight">%s</span> pixels', helper::translate('Dimensions minimales'), $module::$imageOpenGraph['wide'], $module::$imageOpenGraph['height'] ); ?>
</p>
<p>
<?php echo sprintf('%s : <span id="screenRatio">%s</span><span id="screenFract">:1</span>' , helper::translate('Ratio'), round($module::$imageOpenGraph['ratio'], 2)); ?>
</p>
<p>
<?php echo sprintf('%s : <span id="screenWeight">%s</span>', helper::translate('Poids'), $module::$imageOpenGraph['size']); ?>
</p>
<?php if (!empty($module::$imageOpenGraph['type'])): ?>
<p>
<?php echo sprintf('%s : <span id="screenType">%s</span>', helper::translate('Format'), $module::$imageOpenGraph['type']); ?>
</p>
<p>
<?php echo sprintf('%s : <span id="screenWide">%s</span> x <span id="screenHeight">%s</span> pixels', helper::translate('Dimensions minimales'), $module::$imageOpenGraph['wide'], $module::$imageOpenGraph['height']); ?>
</p>
<p>
<?php echo sprintf('%s : <span id="screenRatio">%s</span><span id="screenFract">:1</span>', helper::translate('Ratio'), round($module::$imageOpenGraph['ratio'], 2)); ?>
</p>
<p>
<?php echo sprintf('%s : <span id="screenWeight">%s</span>', helper::translate('Poids'), $module::$imageOpenGraph['size']); ?>
</p>
<?php endif; ?>
</div>
</div>
@ -48,10 +44,10 @@
<div class="col6">
<?php if (
$this->getData(['config', 'seo', 'openGraphImage']) &&
file_exists(self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']))
file_exists(self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']))
): ?>
<img
src="<?php echo self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']); ?>" />
src="<?php echo self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']); ?>" />
<?php endif; ?>
</div>
</div>
@ -84,12 +80,6 @@
<div class="col12">
<div class="block">
<h4>
<?php echo helper::translate('Réseaux sociaux'); ?>
<!--<span id="specialeHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/reseaux-sociaux" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>-->
</h4>
<div class="row">
<div class="col3">

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,98 @@
/* Réinitialisation de base pour supprimer les marges et les espacements par défaut */
body, h1, h2, h3, h4, h5, h6, p, ul, ol, li {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
line-height: 1.6;
}
body {
margin: 20px;
padding: 0;
background-color: #f5f5f5;
color: #333;
}
h1, h2, h3, h4, h5, h6 {
margin-bottom: 10px;
color: #2c3e50;
}
p {
margin-bottom: 10px;
}
ul, ol {
margin-bottom: 10px;
padding-left: 20px;
}
a {
color: #3498db;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
img {
max-width: 100%;
height: auto;
display: block;
margin: 0 auto 10px;
}
.container {
max-width: 800px;
margin: 0 auto;
background-color: #fff;
padding: 20px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.header, .footer {
background-color: #34495e;
color: #fff;
text-align: center;
padding: 10px 0;
}
.header h1, .footer p {
margin: 0;
}
.content {
padding: 20px;
}
code {
background-color: #f4f4f4;
border: 1px solid #e1e1e1;
padding: 2px 4px;
font-family: "Courier New", Courier, monospace;
color: #c7254e;
display: block;
margin-bottom: 10px;
white-space: pre-wrap;
}
pre {
background-color: #f4f4f4;
border: 1px solid #e1e1e1;
padding: 10px;
font-family: "Courier New", Courier, monospace;
overflow-x: auto;
color: #333;
}
/* Media Queries pour rendre la page responsive */
@media (max-width: 600px) {
body {
margin: 10px;
}
.container {
padding: 10px;
}
}

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @authorFrédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -77,7 +77,7 @@
<div class="row">
<div class="col6">
<?php echo template::select('courseAddEnrolment', $module::$courseEnrolment, [
'label' => 'Inscription'
'label' => 'Participation'
]); ?>
</div>
<div class="col6">

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @authorFrédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -3,7 +3,7 @@
<div class="col1">
<?php echo template::button('courseEditBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'course',
'href' => helper::baseUrl() . 'course/manage/' . $this->getUrl(2),
'value' => template::ico('left')
]); ?>
</div>
@ -27,14 +27,14 @@
<div class="col5">
<?php echo template::select('courseEditAuthor', $module::$courseTeachers, [
'label' => 'Auteur',
'value' => $this->getdata(['course', $this->getUrl(2), 'author'])
'selected' => $this->getdata(['course', $this->getUrl(2), 'author'])
]); ?>
</div>
</div>
<div class="row">
<div class="col6">
<?php echo template::select('courseEditHomePageId', helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC'), [
'label' => 'Accueil du contenu',
<?php echo template::select('courseEditHomePageId', helper::arrayColumn($module::$pagesList, 'title'), [
'label' => 'Page d\'accueil',
'selected' => $this->getdata(['course', $this->getUrl(2), 'homePageId']),
]); ?>
</div>
@ -78,7 +78,7 @@
<div class="row">
<div class="col4">
<?php echo template::select('courseEditEnrolment', $module::$courseEnrolment, [
'label' => 'Inscription',
'label' => 'Participation',
'selected' => $this->getdata(['course', $this->getUrl(2), 'enrolment'])
]); ?>
</div>
@ -106,4 +106,5 @@
</div>
</div>
</div>
<?php echo template::formClose(); ?>
</div>
<?php echo template::formClose(); ?>

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -0,0 +1,27 @@
/**
* This file is part of Zwii.
*
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
$(document).ready(function() {
// Quand le bouton "Cocher toutes" est cliqué
$('#courseExportSelectAll').on('click', function() {
// Cocher toutes les checkboxes avec la classe 'courseManageCheckbox'
$('.courseManageCheckbox').prop('checked', true);
});
// Quand le bouton "Décocher toutes" est cliqué
$('#courseExportSelectNone').on('click', function() {
// Décocher toutes les checkboxes avec la classe 'courseManageCheckbox'
$('.courseManageCheckbox').prop('checked', false);
});
});

View File

@ -0,0 +1,42 @@
<?php echo template::formOpen('courseExportForm'); ?>
<div class="row">
<div class="col1">
<?php echo template::button('courseExportBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'course/manage/' . $this->getUrl(2),
'value' => template::ico('left')
]); ?>
</div>
<div class="col1 offset7">
<?php echo template::button('courseExportSelectAll', [
'value' => template::ico('square-check'),
'help' => 'Tout sélectionner'
]); ?>
</div>
<div class="col1">
<?php echo template::button('courseExportSelectNone', [
'value' => template::ico('square-check-empty'),
'help' => 'Tout désélectionner'
]); ?>
</div>
<div class="col2">
<?php echo template::submit('courseExportSubmit', [
'value' => 'Valider'
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4><?php echo helper::translate('Sélection des pages de l\'espace') ?></h4>
<div class='row'>
<div class='col10 offset2'>
<?php foreach ($module::$pagesList as $key => $value) {
echo $value;
}
?>
</div>
</div>
</div>
</div>
</div>

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -6,28 +6,25 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
$(document).ready(function () {
/**
* Confirmation de suppression
*/
$(".courseDelete").on("click", function () {
var _this = $(this);
var message = "<?php echo helper::translate('Supprimer ce contenu ?'); ?>";
return core.confirm(message, function () {
$(location).attr("href", _this.attr("href"));
});
});
$('#dataTables').DataTable({
language: {
url: "core/vendor/datatables/french.json"
},
locale: 'fr',
stateSave: true,
"lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "Tout"]],
"columnDefs": [
{
target: 2,
orderable: false,
searchable: false
},
{
target: 3,
orderable: false,
@ -37,16 +34,6 @@ $(document).ready(function () {
target: 4,
orderable: false,
searchable: false
},
{
target: 5,
orderable: false,
searchable: false
},
{
target: 6,
orderable: false,
searchable: false
}
]
});

View File

@ -6,25 +6,38 @@
'value' => template::ico('home')
]); ?>
</div>
<?php if ($this->getUser('group') === self::GROUP_ADMIN): ?>
<div class="col1 offset9">
<?php echo template::button('courseCategory', [
'href' => helper::baseUrl() . 'course/category',
'value' => template::ico('table'),
'help' => 'Catégories'
]); ?>
</div>
<div class="col1 ">
<?php echo template::button('courseAdd', [
'class' => 'buttonGreen',
'href' => helper::baseUrl() . 'course/add',
'value' => template::ico('plus')
]); ?>
<div class="col1 offset8">
<?php if ($this->getUser('permission', 'course', 'add') === true): ?>
<?php echo template::button('courseAdd', [
'class' => 'buttonGreen',
'href' => helper::baseUrl() . 'course/add',
'value' => template::ico('plus'),
'help' => 'Ajouter un espace'
]); ?>
<?php endif; ?>
</div>
<div class="col1">
<?php if ($this->getUser('permission', 'course', 'category') === true): ?>
<?php echo template::button('courseCategory', [
'href' => helper::baseUrl() . 'course/category',
'value' => template::ico('table'),
'help' => 'Catégories des espaces'
]); ?>
<?php endif; ?>
</div>
<div class="col1">
<?php if ($this->getUser('permission', 'course', 'restore') === true): ?>
<?php echo template::button('courseUpload', [
'href' => helper::baseUrl() . 'course/restore/',
'value' => template::ico('upload-cloud'),
'help' => 'Restaurer un espace'
]); ?>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<?php if($module::$courses): ?>
<?php echo template::table([2, 2, 2, 3, 1, 1, 1], $module::$courses, ['Titre court', 'Auteur', 'Description', 'Lien direct', '', '', ''], ['id' => 'dataTables']); ?>
<?php if ($module::$courses): ?>
<?php echo template::table([4, 3, 3, 1, 1], $module::$courses, ['Titre court', 'Description', 'Inscription', '', '',], ['id' => 'dataTables']); ?>
<?php else: ?>
<?php echo template::speech('Aucun Contenu'); ?>
<?php endif; ?>
<?php echo template::speech('Aucun espace'); ?>
<?php endif; ?>

View File

@ -1,25 +1,18 @@
/**
* This file is part of Zwii.
*
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
$(document).ready((function () {
$('#dataTables').DataTable({
language: {
url: "core/vendor/datatables/french.json"
},
locale: 'fr',
searching: false,
pageLength: 100,
lengthChange: false,
paging: false
});
}));
/** NE PAS EFFACER
* admin.css
*/

View File

@ -0,0 +1,34 @@
/**
* This file is part of Zwii.
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
/**
* Confirmation de suppression
*/
$(".courseDelete").on("click", function () {
var _this = $(this);
var message = "<?php echo helper::translate('Supprimer cet espace et les documents du gestionnaire de fichier ?'); ?>";
return core.confirm(message, function () {
$(location).attr("href", _this.attr("href"));
});
});
/**
* Confirmation de suppression
*/
$(".courseReset").on("click", function () {
var _this = $(this);
var message = "<?php echo helper::translate('Réinitialiser cet espace ?'); ?>";
return core.confirm(message, function () {
$(location).attr("href", _this.attr("href"));
});
});

View File

@ -0,0 +1,182 @@
<div class="row">
<div class="col1">
<?php echo template::button('courseManageBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'course',
'value' => template::ico('left')
]); ?>
</div>
</div>
<div class="row textAlignCenter">
<?php if ($this->getUser('permission', 'course', 'delete') === true): ?>
<div class="col2 ">
<?php echo template::button('courseManageDelete' . $this->getUrl(2), [
'class' => 'courseDelete buttonRed',
'href' => helper::baseUrl() . 'course/delete/' . $this->getUrl(2),
'value' => 'Supprimer',
'ico' => 'trash',
'help' => 'Supprime l\'espace et les historiques des participants',
]); ?>
</div>
<?php endif; ?>
<?php if ($this->getUser('permission', 'course', 'reset') === true): ?>
<div class="col2 ">
<?php echo template::button('courseManageReset' . $this->getUrl(2), [
'class' => 'courseReset buttonRed',
'href' => helper::baseUrl() . 'course/reset/' . $this->getUrl(2),
'value' => 'Réinitaliser',
'ico' => 'cancel',
'help' => 'Désinscrit les participants et supprime les historiques',
]); ?>
</div>
<?php endif; ?>
<?php if ($this->getUser('permission', 'course', 'backup') === true): ?>
<div class="col2">
<?php echo template::button('courseManageDownload' . $this->getUrl(2), [
'href' => helper::baseUrl() . 'course/backup/' . $this->getUrl(2),
'value' => 'Sauvegarder',
'ico' => 'download-cloud',
'help' => 'Génère une copie de sauvegarde de l\'espace',
]); ?>
</div>
<?php endif; ?>
<?php if ($this->getUser('permission', 'course', 'clone') === true): ?>
<div class="col2">
<?php echo template::button('courseManageDuplicate' . $this->getUrl(2), [
'href' => helper::baseUrl() . 'course/clone/' . $this->getUrl(2),
'value' => 'Cloner',
'ico' => 'clone',
'help' => 'Copie l\'espace et son contenu sans les participants et leurs historiques',
]); ?>
</div>
<?php endif; ?>
<?php if ($this->getUser('permission', 'course', 'edit') === true): ?>
<div class="col2">
<?php echo template::button('courseManageEdit' . $this->getUrl(2), [
'href' => helper::baseUrl() . 'course/edit/' . $this->getUrl(2),
'value' => 'Éditer',
'ico' => 'pencil',
'help' => 'Modifie les paramètres de l\'espace',
]); ?>
</div>
<?php endif; ?>
<?php if ($this->getUser('permission', 'course', 'export') === true): ?>
<div class="col2">
<?php echo template::button('courseManageExport' . $this->getUrl(2), [
'href' => helper::baseUrl() . 'course/export/' . $this->getUrl(2),
'value' => 'Exporter HTML',
'ico' => 'upload',
'help' => 'Le contenu de l\'espace est exporté dans une page web autonome',
]); ?>
</div>
<?php endif; ?>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>
<?php echo helper::translate('Paramètres'); ?>
</h4>
<div class="row">
<div class="col7">
<?php echo template::text('courseManageShortTitle', [
'label' => 'Titre',
'value' => $this->getdata(['course', $this->getUrl(2), 'title']),
'readonly' => true,
]); ?>
</div>
<div class="col5">
<?php echo template::text('courseManageAuthor', [
'label' => 'Auteur',
'value' => $this->signature($this->getdata(['course', $this->getUrl(2), 'author'])),
'readonly' => true,
]); ?>
</div>
</div>
<div class="row">
<div class="col6">
<?php echo template::text('courseManageHomePageId', [
'label' => 'Page d\'accueil',
'value' => $module::$pagesList[$this->getdata(['course', $this->getUrl(2), 'homePageId'])]['shortTitle'],
'readonly' => true,
]); ?>
</div>
<div class="col6">
<?php echo template::text('courseManageCategorie', [
'label' => 'Catégorie',
'value' => $module::$courseCategories[$this->getdata(['course', $this->getUrl(2), 'category'])],
'readonly' => true,
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<?php echo template::textarea('courseManageDescription', [
'label' => 'Description',
'value' => $this->getdata(['course', $this->getUrl(2), 'description']),
'readonly' => true,
]); ?>
</div>
</div>
<div class="row">
<div class="col4">
<?php echo template::text('courseManageAccess', [
'label' => 'Disponibilité',
'value' => $module::$courseAccess[$this->getdata(['course', $this->getUrl(2), 'access'])],
'readonly' => true,
]); ?>
</div>
<div class="col4">
<?php echo template::date('courseOpeningDate', [
'type' => 'datetime-local',
'label' => 'Ouverture',
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'openingDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'openingDate']) / 60) * 60,
'readonly' => true,
]); ?>
</div>
<div class="col4">
<?php echo template::date('courseClosingDate', [
'type' => 'datetime-local',
'label' => 'Fermeture',
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'closingDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'closingDate']) / 60) * 60,
'readonly' => true,
]); ?>
</div>
</div>
<div class="row">
<div class="col4">
<?php echo template::text('courseManageEnrolment', [
'label' => 'Participation',
'value' => $module::$courseEnrolment[$this->getdata(['course', $this->getUrl(2), 'enrolment'])],
'readonly' => true,
]); ?>
</div>
<div class="col4">
<?php echo template::text('courseManageEnrolmentKey', [
'label' => 'Clé',
'value' => $this->getdata(['course', $this->getUrl(2), 'enrolmentKey']),
'readonly' => true,
]); ?>
</div>
</div>
<div class="row">
<div class="col4">
<?php echo template::checkbox('courseManageEnrolmentLimit', true, 'Date de fin d\'inscription', [
'checked' => $this->getdata(['course', $this->getUrl(2), 'limitEnrolment']),
'help' => 'Ne s\'applique pas à l\'inscription anonyme',
'disabled' => true,
]); ?>
</div>
<div class="col4">
<?php echo template::date('courseManageEnrolmentLimitDate', [
'type' => 'datetime-local',
'label' => 'Fermeture',
'value' => is_null($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate'])) ? '' : floor($this->getdata(['course', $this->getUrl(2), 'limitEnrolmentDate']) / 60) * 60,
'readonly' => true,
]); ?>
</div>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,20 @@
/**
* This file is part of Zwii.
*
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
/** @import url("site/data/admin.css"); */
/** NE PAS EFFACER
* admin.css
*/

View File

@ -0,0 +1,33 @@
<?php echo template::formOpen('courseRestoreForm'); ?>
<div class="row">
<div class="col1">
<?php echo template::button('courseRestoreBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'course',
'value' => template::ico('left')
]); ?>
</div>
<div class="col2 offset9">
<?php echo template::submit('courseRestoreSubmit', [
'value' => 'Valider'
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>
<?php echo sprintf('%s : %s', helper::translate('Restaurer depuis le dossier de l\'espace id'), self::$siteContent ); ?>
</h4>
<div class="row">
<div class="col10 offset1">
<?php echo template::file('courseRestoreFile', [
'language' => $this->getData(['course', $this->getUser('id'), 'language']),
//'label' => 'Fichier de sauvegarde :'
]); ?>
</div>
</div>
</div>
</div>
</div>
<?php echo template::formClose(); ?>

View File

@ -1,25 +0,0 @@
<div class="row">
<div class="col1">
<?php echo template::button('courseUserHistoryBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'course/user/' . $this->getUrl(2),
'value' => template::ico('left')
]); ?>
</div>
<div class="col1 offset10">
<?php echo template::button('userDeleteAll', [
'href' => helper::baseUrl() . 'course/userHistoryExport/' . $this->getUrl(2) . '/' . $this->getUrl(3),
'value' => template::ico('download'),
'help' => 'Exporter',
]) ?>
</div>
</div>
<?php if ($module::$userHistory): ?>
<div class="row textAlignCenter">
<div class="col8">
<?php echo template::table([1, 6, 5], $module::$userHistory, ['Ordre', 'Dernière consultation de cette page', 'Titre de la page'], ['id' => 'dataTables']); ?>
</div>
</div>
<?php else: ?>
<?php echo template::speech('Aucun historique'); ?>
<?php endif; ?>

View File

@ -0,0 +1,22 @@
/**
* This file is part of Zwii.
*
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
/** NE PAS EFFACER
* admin.css
*/
table td {
text-align: left;
}

View File

@ -0,0 +1,44 @@
/**
* This file is part of Zwii.
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
$(document).ready((function () {
var dataX = <?php echo json_encode(array_map(function ($item) { return $item[0]; }, $module::$userGraph)); ?>;
var dataY = <?php echo json_encode(array_map(function ($item) { return $item[1];}, $module::$userGraph)); ?>;
var dataText = <?php echo json_encode(array_map(function ($item) { return $item[2];}, $module::$userGraph)); ?>;
var data = [{
x: dataX,
y: dataY,
text: dataText,
mode: 'markers', // Mode de tracé des points
type: 'scatter' // Type de graphe
}];
// Créer un objet layout et définir les propriétés du titre, des axes, etc.
var layout = {
title: 'Consultations par jour', // Titre du graphe
xaxis: {
title: 'Jours', // Titre de l'axe des abscisses
type: 'date' // Type de l'axe des abscisses
},
yaxis: {
title: 'Temps (en secondes)', // Titre de l'axe des ordonnées
type: 'linear' // Type de l'axe des ordonnées
}
};
// Créer et afficher le graphe dans l'élément <div>
Plotly.newPlot('graph', data, layout, {locale: 'fr-CH'});
}));

View File

@ -0,0 +1,54 @@
<div class="row">
<div class="col1">
<?php echo template::button('courseUserHistoryBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'course/users/' . $this->getUrl(2),
'value' => template::ico('left')
]); ?>
</div>
<div class="col1 offset10">
<?php echo template::button('userDeleteAll', [
'href' => helper::baseUrl() . 'course/userReportExport/' . $this->getUrl(2) . '/' . $this->getUrl(3),
'value' => template::ico('download'),
'help' => 'Exporter',
]) ?>
</div>
</div>
<div class="row">
<div class="col10 offset1">
<div id="graph">
</div>
</div>
</div>
<?php if ($module::$userReport): ?>
<div class="row">
<div class="col4 offset2">
<?php if ($this->getData(['course', $this->getUrl(2), 'access']) === self::COURSE_ACCESS_DATE): ?>
<p>Espace ouvert le :
<?php echo helper::dateUTF8('%d %B %Y %H:%M', $this->getData(['course', $this->getUrl(2), 'openingDate'])); ?>
</p>
<p>Espace fermé le :
<?php echo helper::dateUTF8('%d %B %Y %H:%M', $this->getData(['course', $this->getUrl(2), 'closingDate'])); ?>
</p>
<?php endif; ?>
</div>
<div class="col4">
<p>Commencé le :
<?php echo $module::$userStat['floor']; ?>
</p>
<p>Terminé le :
<?php echo $module::$userStat['top']; ?>
</p>
<p>Temps passé :
<?php echo $module::$userStat['time']; ?>
</p>
</div>
</div>
<div class="row textAlignCenter">
<div class="col8">
<?php echo template::table([6, 3, 3], $module::$userReport, ['Page', 'Début de Consultation', 'Temps consultation']); ?>
</div>
</div>
<?php else: ?>
<?php echo template::speech('Aucun historique'); ?>
<?php endif; ?>

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -21,15 +21,18 @@ $(document).ready((function () {
$(location).attr("href", _this.attr("href"))
}))
}));
$.fn.dataTable.moment( 'DD/MM/YYYY' );
$('#dataTables').DataTable({
language: {
url: "core/vendor/datatables/french.json"
},
order: [[3, 'desc']],
locale: 'fr',
stateSave: true,
"lengthMenu": [[10, 25, 50, 100, 299, -1], [10, 25, 50, 100, 200, "Tout"]],
"columnDefs": [
{
target: 5,
target: 6,
orderable: false,
searchable: false
}

View File

@ -2,13 +2,13 @@
<div class="col1">
<?php echo template::button('courseUserBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'course',
'href' => helper::baseUrl() . 'course/' . $this->getUrl(2),
'value' => template::ico('left')
]); ?>
</div>
<div class="col1 offset8">
<?php echo template::button('userDeleteAll', [
'href' => helper::baseUrl() . 'course/usersHistoryExport/' . $this->getUrl(2),
'href' => helper::baseUrl() . 'course/usersReportExport/' . $this->getUrl(2),
'value' => template::ico('download'),
'help' => 'Exporter',
]) ?>
@ -53,7 +53,7 @@
</div>
<?php echo template::formClose(); ?>
<?php if ($module::$courseUsers): ?>
<?php echo template::table([2, 2, 2, 2, 2, 1, 1], $module::$courseUsers, ['Id', 'Nom Prénom', 'Dernière page vue', 'Date - Heure', 'Étiquettes', 'Progression', ''], ['id' => 'dataTables']); ?>
<?php echo template::table([3, 4, 1, 1, 1, 1, 1], $module::$courseUsers, ['Nom Prénom', 'Dernière page vue', 'Date' , 'Heure', 'Étiquettes', 'Progression', ''], ['id' => 'dataTables']); ?>
<?php else: ?>
<?php echo template::speech('Aucun participant'); ?>
<?php endif; ?>

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -15,4 +15,8 @@
/** NE PAS EFFACER
* admin.css
*/
*/
tr {
cursor: pointer;
}

View File

@ -6,13 +6,20 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
$(document).ready((function () {
$('tr').click(function(){
// Cochez ou décochez la case à cocher dans cette ligne
$(this).find('input[type="checkbox"]').prop('checked', function(i, val){
return !val; // Inverse l'état actuel de la case à cocher
});
});
$('#courseUserAddSelectAll').on('click', function() {
$('.checkboxSelect').prop('checked', true);
saveCheckboxState();
@ -32,6 +39,8 @@ $(document).ready((function () {
url: "core/vendor/datatables/french.json"
},
locale: 'fr',
stateSave: true,
"lengthMenu": [[10, 25, 50, 100, 299, -1], [10, 25, 50, 100, 200, "Tout"]],
"columnDefs": [
{
target: 0,

View File

@ -7,19 +7,10 @@
'value' => template::ico('left')
]); ?>
</div>
<div class="col1 offset7">
<?php echo template::button('courseUserAddSelectAll', [
'value' => 'Tout'
]); ?>
</div>
<div class="col1">
<?php echo template::button('courseUserAddSelectNone', [
'value' => 'Aucun'
]); ?>
</div>
<div class="col2">
<div class="col2 offset9">
<?php echo template::submit('courseUsersAddSubmit', [
'value' => 'Inscrire'
'value' => 'Inscrire',
'ico' => 'plus',
]); ?>
</div>
</div>
@ -42,6 +33,18 @@
'selected' => isset($_POST['courseFilterLastName']) ? $_POST['courseFilterLastName'] : 'all',
]); ?>
</div>
<div class="col1 offset1 verticalAlignBottom">
<?php echo template::button('courseUserAddSelectAll', [
'value' => template::ico('square-check'),
'help' => 'Tout sélectionner'
]); ?>
</div>
<div class="col1 verticalAlignBottom">
<?php echo template::button('courseUserAddSelectNone', [
'value' => template::ico('square-check-empty'),
'help' => 'Tout désélectionner'
]); ?>
</div>
</div>
<?php if ($module::$courseUsers): ?>
<?php echo template::table([1, 2, 3, 3, 3], $module::$courseUsers, ['', 'Id', 'Prénom', 'Nom', 'Étiquettes'], ['id' => 'dataTables']); ?>

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -15,4 +15,12 @@
/** NE PAS EFFACER
* admin.css
*/
*/
#courseUsersDeleteSubmit {
background-color: rgba(217, 95, 78, 1);
}
tr {
cursor: pointer;
}

View File

@ -6,18 +6,25 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
$(document).ready((function () {
$('#courseUserDeleteSelectAll').on('click', function() {
$('tr').click(function () {
// Cochez ou décochez la case à cocher dans cette ligne
$(this).find('input[type="checkbox"]').prop('checked', function (i, val) {
return !val; // Inverse l'état actuel de la case à cocher
});
});
$('#courseUserDeleteSelectAll').on('click', function () {
$('.checkboxSelect').prop('checked', true);
saveCheckboxState();
});
$('#courseUserDeleteSelectNone').on('click', function() {
$('#courseUserDeleteSelectNone').on('click', function () {
$('.checkboxSelect').prop('checked', false);
saveCheckboxState();
});
@ -32,6 +39,7 @@ $(document).ready((function () {
url: "core/vendor/datatables/french.json"
},
locale: 'fr',
"lengthMenu": [[10, 25, 50, 100, 299, -1], [10, 25, 50, 100, 200, "Tout"]],
"columnDefs": [
{
target: 0,
@ -80,7 +88,7 @@ $(document).ready((function () {
// Function to restore checkbox state
function restoreCheckboxState() {
var checkboxState = JSON.parse(localStorage.getItem('checkboxState')) || {};
// console.log(checkboxState);
// console.log(checkboxState);
for (var checkboxId in checkboxState) {
if (checkboxState.hasOwnProperty(checkboxId)) {
var checked = checkboxState[checkboxId];

View File

@ -7,23 +7,14 @@
'value' => template::ico('left')
]); ?>
</div>
<div class="col1 offset7">
<?php echo template::button('courseUserDeleteSelectAll', [
'value' => 'Tout'
]); ?>
</div>
<div class="col1">
<?php echo template::button('courseUserDeleteSelectNone', [
'value' => 'Aucun'
]); ?>
</div>
<div class="col2">
<div class="col2 offset9">
<?php echo template::submit('courseUsersDeleteSubmit', [
'class' => 'buttonRed',
'value' => 'Désinscrire'
'ico' => 'minus',
'value' => 'Désinscrire',
]); ?>
</div>
</div>
</div>
<div class="row" id="Bfrtip">
<div class="col3">
<?php echo template::select('courseFilterGroup', $module::$courseGroups, [
@ -43,9 +34,21 @@
'selected' => isset($_POST['courseFilterLastName']) ? $_POST['courseFilterLastName'] : 'all',
]); ?>
</div>
<div class="col1 offset1 verticalAlignBottom">
<?php echo template::button('courseUserDeleteSelectAll', [
'value' => template::ico('square-check'),
'help' => 'Tout sélectionner'
]); ?>
</div>
<div class="col1 verticalAlignBottom">
<?php echo template::button('courseUserDeleteSelectNone', [
'value' => template::ico('square-check-empty'),
'help' => 'Tout désélectionner'
]); ?>
</div>
</div>
<?php if ($module::$courseUsers): ?>
<?php echo template::table([1, 2, 3, 3, 3], $module::$courseUsers, ['', 'Id', 'Prénom', 'Nom', 'Étiquettes'], ['id' => 'dataTables']); ?>
<?php echo template::table([1, 2, 3, 3, 3], $module::$courseUsers, ['', 'Id', 'Prénom', 'Nom', 'Étiquettes'], ['id' => 'dataTables']); ?>
<?php else: ?>
<?php echo template::speech('Aucun inscrit'); ?>
<?php endif; ?>

View File

@ -8,7 +8,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -78,7 +78,7 @@ class install extends common
$this->addOutput([
'display' => self::DISPLAY_LAYOUT_LIGHT,
'title' => helper::translate('Installation'),
'title' => helper::translate('ZwiiCampus installation'),
'view' => 'index'
]);
}
@ -158,9 +158,9 @@ class install extends common
);
// Sauvegarder la configuration du Proxy
$this->setData(['config', 'proxyType', $this->getInput('installProxyType')]);
$this->setData(['config', 'proxyUrl', $this->getInput('installProxyUrl')]);
$this->setData(['config', 'proxyPort', $this->getInput('installProxyPort', helper::FILTER_INT)]);
$this->setData(['config', 'proxyType', $this->getInput('installProxyType')], false);
$this->setData(['config', 'proxyUrl', $this->getInput('installProxyUrl')], false);
$this->setData(['config', 'proxyPort', $this->getInput('installProxyPort', helper::FILTER_INT)], false);
// Images exemples livrées dans tous les cas
try {
@ -194,11 +194,16 @@ class install extends common
mkdir(self::I18N_DIR);
}
// Créer le dossier de l'accueil dans les fichiers
if (is_dir(self::FILE_DIR . 'source/home') === false) {
mkdir(self::FILE_DIR . 'source/home');
}
// Créer la base de données des langues
$this->copyDir('core/module/install/ressource/i18n', self::I18N_DIR);
// Fixe l'adresse from pour les envois d'email
$this->setData(['config', 'smtp', 'from', 'no-reply@' . str_replace('www.', '', $_SERVER['HTTP_HOST'])]);
$this->setData(['config', 'smtp', 'from', 'no-reply@' . str_replace('www.', '', $_SERVER['HTTP_HOST'])], false);
// Valeurs en sortie
$this->addOutput([
@ -207,13 +212,14 @@ class install extends common
'state' => true
]);
}
// Force la sauvegarde
$this->saveDB('config');
// Affichage du formulaire
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_LAYOUT_LIGHT,
'title' => helper::translate('Zwii Campus Installation'),
'title' => helper::translate('ZwiiCampus Installation'),
'view' => 'postinstall'
]);
}
@ -248,14 +254,18 @@ class install extends common
$message = $success ? '' : 'Erreur de copie du fichier htaccess';
}
// Nettoyage des fichiers d'installation précédents
if (file_exists(self::TEMP_DIR . 'update.tar.gz') && $success) {
if ($success && file_exists(self::TEMP_DIR . 'update.tar.gz')) {
$success = unlink(self::TEMP_DIR . 'update.tar.gz');
$message = $success ? '' : 'Impossible d\'effacer la mise à jour précédente';
}
if (file_exists(self::TEMP_DIR . 'update.tar') && $success) {
if ($success && file_exists(self::TEMP_DIR . 'update.tar')) {
$success = unlink(self::TEMP_DIR . 'update.tar');
$message = $success ? '' : 'Impossible d\'effacer la mise à jour précédente';
}
// Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
@ -267,6 +277,8 @@ class install extends common
break;
// Téléchargement
case 2:
$success = true;
$message = '';
file_put_contents(self::TEMP_DIR . 'update.tar.gz', helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.tar.gz'));
$md5origin = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.md5');
$md5origin = explode(' ', $md5origin);
@ -277,27 +289,35 @@ class install extends common
$message = "";
} else {
$success = false;
$message = json_encode('Erreur de téléchargement ou de somme de contrôle', JSON_UNESCAPED_UNICODE);
$message = 'Erreur de téléchargement ou de somme de contrôle';
if (file_exists(self::TEMP_DIR . 'update.tar.gz')) {
unlink(self::TEMP_DIR . 'update.tar.gz');
http_response_code(500);
}
}
// Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
'content' => [
'success' => $success,
'data' => $message
'data' => json_encode($message, JSON_UNESCAPED_UNICODE)
]
]);
break;
// Installation
case 3:
$success = true;
$message = '';
// Check la réécriture d'URL avant d'écraser les fichiers
$rewrite = helper::checkRewrite();
if (helper::checkRewrite()) {
touch(self::DATA_DIR . '.rewrite');
}
// Décompression et installation
try {
// Décompression dans le dossier de fichier temporaires
@ -306,9 +326,11 @@ class install extends common
// Installation
$pharData->extractTo(__DIR__ . '/../../../', null, true);
} catch (Exception $e) {
$message = $e->getMessage();
$success = false;
http_response_code(500);
}
// Nettoyage du dossier
if (file_exists(self::TEMP_DIR . 'update.tar.gz')) {
unlink(self::TEMP_DIR . 'update.tar.gz');
@ -316,12 +338,16 @@ class install extends common
if (file_exists(self::TEMP_DIR . 'update.tar')) {
unlink(self::TEMP_DIR . 'update.tar');
}
// Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
'content' => [
'success' => $success,
'data' => $rewrite
'data' => json_encode($message, JSON_UNESCAPED_UNICODE)
]
]);
break;
@ -329,7 +355,6 @@ class install extends common
case 4:
$success = true;
$message = '';
$rewrite = $this->getInput('data');
/**
* Restaure le fichier htaccess
@ -350,7 +375,7 @@ class install extends common
/**
* Restaure la réécriture d'URL
*/
if ($rewrite === 'true') { // Ajout des lignes dans le .htaccess
if (file_exists(self::DATA_DIR . '.rewrite')) { // Ajout des lignes dans le .htaccess
$fileContent = file_get_contents('.htaccess');
$rewriteData = PHP_EOL .
'# URL rewriting' . PHP_EOL .
@ -363,10 +388,11 @@ class install extends common
'</IfModule>' . PHP_EOL .
'# URL rewriting' . PHP_EOL;
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
$success = file_put_contents(
$success = $this->secure_file_put_contents(
'.htaccess',
$fileContent
);
unlink(self::DATA_DIR . '.rewrite');
}
}
@ -378,7 +404,6 @@ class install extends common
$defaultLanguages = init::$defaultData['language'];
foreach ($installedLanguages as $key => $value) {
//var_dump( $defaultLanguages[$key]['date'] > $value['date'] );
if (
isset($defaultLanguages[$key]['date']) &&
$defaultLanguages[$key]['date'] > $value['date'] &&
@ -390,7 +415,10 @@ class install extends common
$this->setData(['language', $key, $defaultLanguages[$key]]);
}
}
// Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
@ -419,10 +447,13 @@ class install extends common
} else {
// Nouvelle version
self::$newVersion = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/version');
// Variable de version
if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) {
self::$updateButtonText = helper::translate('Mettre à jour');
self::$updateButtonText = helper::translate('Mise à jour');
}
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_LAYOUT_LIGHT,

View File

@ -18,7 +18,7 @@ class init extends common
'legalPageId' => 'none',
'searchPageId' => 'none',
'searchPageLabel' => 'Rechercher',
'sitemapPageLabel' => 'Plan du contenu',
'sitemapPageLabel' => 'Sommaire',
'legalPageLabel' => 'Mentions légales',
'metaDescription' => 'Zwii est un CMS sans base de données qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation.',
'title' => 'Votre site en quelques clics !',
@ -64,7 +64,7 @@ class init extends common
]
],
'core' => [
'dataVersion' => 1000,
'dataVersion' => 1700,
'lastBackup' => 0,
'lastClearTmp' => 0,
'lastAutoUpdate' => 0,
@ -240,6 +240,21 @@ class init extends common
'copycut' => false,
'chmod' => false
],
'course' => [
'tutor' => false,
'index' => false,
'manage' => false,
'users' => false,
'userHistory' => false,
'userReportExport' => false,
'usersAdd' => false,
'userDelete' => false,
'usersDelete' => false,
'edit' => false,
'backup' => false,
'restore' => false,
'reset' => false,
],
'folder' => [
'create' => false,
'delete' => false,
@ -247,7 +262,8 @@ class init extends common
'copycut' => false,
'chmod' => false,
'share' => false,
'path' => null,
'coursePath' => 'none',
'homePath' => 'none'
],
'page' => [
'add' => false,
@ -321,6 +337,21 @@ class init extends common
'copycut' => false,
'chmod' => false
],
'course' => [
'tutor' => false,
'index' => false,
'manage' => false,
'users' => false,
'userHistory' => false,
'userReportExport' => false,
'usersAdd' => false,
'userDelete' => false,
'usersDelete' => false,
'edit' => false,
'backup' => false,
'restore' => false,
'reset' => false,
],
'folder' => [
'create' => false,
'delete' => false,
@ -328,7 +359,8 @@ class init extends common
'copycut' => false,
'chmod' => false,
'share' => true,
'path' => './site/file/source/partage/',
'coursePath' => 'none',
'homePath' => '/site/file/source/partage/'
],
'page' => [
'add' => false,
@ -407,6 +439,21 @@ class init extends common
'copycut' => false,
'chmod' => false
],
'course' => [
'tutor' => true,
'index' => true,
'manage' => true,
'users' => true,
'userHistory' => true,
'userReportExport' => true,
'usersAdd' => true,
'userDelete' => false,
'usersDelete' => false,
'edit' => false,
'backup' => false,
'restore' => false,
'reset' => false,
],
'folder' => [
'create' => false,
'delete' => false,
@ -414,7 +461,8 @@ class init extends common
'copycut' => false,
'chmod' => false,
'share' => true,
'path' => './site/file/source/partage/',
'coursePath' => '',
'homePath' => '/site/file/source/partage/'
],
'page' => [
'add' => false,
@ -474,7 +522,7 @@ class init extends common
'name' => 'Rédacteur',
'readonly' => false,
'permanent' => false,
'comment' => 'Tous les droits d\'édition des contenus',
'comment' => 'Tous les droits d\'édition des espaces',
'filemanager' => true,
'file' => [
'download' => true,
@ -489,6 +537,21 @@ class init extends common
'copycut' => true,
'chmod' => true
],
'course' => [
'tutor' => false,
'index' => true,
'manage' => true,
'users' => true,
'userHistory' => true,
'userReportExport' => true,
'usersAdd' => true,
'userDelete' => true,
'usersDelete' => true,
'edit' => true,
'backup' => true,
'restore' => true,
'reset' => true,
],
'folder' => [
'create' => true,
'delete' => true,
@ -496,7 +559,8 @@ class init extends common
'copycut' => true,
'chmod' => true,
'share' => true,
'path' => './site/file/source/partage/',
'coursePath' => '',
'homePath' => '/site/file/source/partage/'
],
'page' => [
'add' => true,
@ -835,7 +899,8 @@ class init extends common
'activeColor' => 'rgba(255, 255, 255, 1)',
'activeTextColor' => 'rgba(255, 255, 255, 1)',
'radius' => '0px',
'memberBar' => false,
'memberBar' => true,
'selectSpace' => true,
'burgerLogo' => '',
'burgerContent' => 'title',
'width' => 'container'
@ -907,16 +972,16 @@ class init extends common
public static $siteContent = [
'accueil' => [
'content' => '<h2>Bienvenue sur cette nouvelle installation de Zwii Campus.</h2>
<p>Zwii Campus est un outil auteur destin&eacute; &agrave; mettre en ligne des contenus d\'enseignement pour des apprenants.</p>
<p>Les contenus d\'enseignement se pr&eacute;sentent comme des mini site Web. Le contenu des contenus est librement personnalisable, dans la plupart des cas on utilisera un menu lat&eacute;ral et les pages disposeront de boutons de navigation.</p>
<p>Chaque contenu disposent de modalit&eacute;s d\'ouverture :&nbsp;ouvert, ferm&eacute; et ouvert entre deux dates.</p>
<p>Zwii Campus est un outil auteur destin&eacute; &agrave; mettre en ligne des espaces d\'enseignement pour des apprenants.</p>
<p>Les espaces d\'enseignement se pr&eacute;sentent comme des mini site Web. Le contenu des espaces est librement personnalisable, dans la plupart des cas on utilisera un menu lat&eacute;ral et les pages disposeront de boutons de navigation.</p>
<p>Chaque espace dispose de modalit&eacute;s d\'ouverture :&nbsp;ouvert, ferm&eacute; et ouvert entre deux dates.</p>
<p>Les modalit&eacute;s d\'acc&egrave;s sont vari&eacute;es:</p>
<ul>
<li>anonyme (ouvert &agrave; tous sans avoir &agrave; disposer de compte d\'acc&egrave;s),</li>
<li>avec inscription libre pour les d&eacute;tenteurs d\'un compte d\'acc&egrave;s,</li>
<li>et avec une cl&eacute; d\'inscription pour les d&eacute;tenteurs d\'un compte d\'acc&egrave;s.</li>
</ul>
<p>Le parcours des apprenants est suivi : le pourcentage de progression et le d&eacute;tail de la consultation des pages est visible dans la gestion des contenus.</p>'
<p>Le parcours des apprenants est suivi : le pourcentage de progression et le d&eacute;tail de la consultation des pages est visible dans la gestion des espaces.</p>'
],
'contact' => [
'content' => '<p>Cette page contient un exemple de formulaire conçu à partir du module de génération de formulaires. Il est configuré pour envoyer les données saisies par mail aux administrateurs du site.</p>'

View File

@ -547,7 +547,7 @@
"Sauvegarde": "Backup",
"Sauvegarde automatique quotidienne du site": "Daily automatic backup of the site",
"Sauvegarde du thème dans le": "Backup of the theme in the",
"Sauvegarde générée avec succès.": "Successfully generated backup.",
"Sauvegarde générée avec succès": "Successfully generated backup.",
"Sauvegarder": "Backup",
"Sauvegarder et télécharger le module": "Save and download the module",
"Sauvegarder le module dans le gestionnaire de fichiers": "Save the module in the file manager",

View File

@ -547,7 +547,7 @@
"Sauvegarde": "Salvaguardad",
"Sauvegarde automatique quotidienne du site": "Copia de seguridad diaria automática del sitio",
"Sauvegarde du thème dans le": "Guardando tema en el",
"Sauvegarde générée avec succès.": "Copia de seguridad generada con éxito",
"Sauvegarde générée avec succès": "Copia de seguridad generada con éxito",
"Sauvegarder": "Para salvaguardar",
"Sauvegarder et télécharger le module": "Guardar y descargar módulo",
"Sauvegarder le module dans le gestionnaire de fichiers": "Guardar módulo en el administrador de archivos",

View File

@ -547,7 +547,7 @@
"Sauvegarde": "",
"Sauvegarde automatique quotidienne du site": "",
"Sauvegarde du thème dans le": "",
"Sauvegarde générée avec succès.": "",
"Sauvegarde générée avec succès": "",
"Sauvegarder": "",
"Sauvegarder et télécharger le module": "",
"Sauvegarder le module dans le gestionnaire de fichiers": "",

View File

@ -0,0 +1,18 @@
/**
* This file is part of Zwii.
*
* For full copyright and license information, please see the LICENSE
* file that was distributed with this source code.
*
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
/** NE PAS EFFACER
* admin.css
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -1,7 +1,7 @@
function step(i, data) {
var errors = ["<?php echo helper::translate('Préparation de la mise à jour'); ?>", "<?php echo helper::translate('Téléchargement et validation de l\'archive'); ?>", "<?php echo helper::translate('Installation'); ?>", "<?php echo helper::translate('Configuration'); ?>"];
$(".installUpdateProgressText").hide(), $(".installUpdateProgressText[data-id=" + i + "]").show();
$("body").css("cursor", "wait");
$.ajax({
@ -12,11 +12,6 @@ function step(i, data) {
data: data
},
success: function (result) {
// if (result.success != "1") { // Vérification de la propriété "success"
// Appel de la fonction de gestion d'erreur
// showError(i, result, errors);
// return;
//}
setTimeout((function () {
if (4 === i) {
$("#installUpdateSuccess").show();
@ -60,10 +55,13 @@ function showError(step, message, errors) {
const jsonData = JSON.parse(jsonString);
// Afficher les résultats
$("#installUpdateErrorMessage").html("<strong>Détails de l'erreur :</strong><br> " +
jsonData.data.replace(/^"(.*)"$/, '$1') +
"<br>" +
warningMessage.replace(/<[^p].*?>/g, ""));
if (jsonData) {
$("#installUpdateErrorMessage").html("<strong>Détails de l'erreur :</strong><br> " +
jsonData.data.replace(/^"(.*)"$/, '$1') +
"<br>" +
warningMessage.replace(/<[^p].*?>/g, ""));
}
} else {
// Vous pouvez également faire quelque chose d'autre ici, par exemple, afficher un message à l'utilisateur, etc.
$("#installUpdateErrorMessage").html(message);

View File

@ -5,7 +5,7 @@
<?php echo self::ZWII_VERSION; ?>
<?php echo helper::translate('vers'); ?>
&nbsp;
<?php echo $module::$newVersion; ?>.
<?php echo $module::$newVersion; ?>
</strong></p>
<p>
<?php echo helper::translate('Afin d\'assurer le bon fonctionnement de Zwii, veuillez ne pas fermer cette page avant la fin de l\'opération.'); ?>

View File

@ -8,7 +8,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -99,7 +99,7 @@ class language extends common
is_array($descripteur['language'][$lang])
) {
if ($this->setData(['language', $lang, $descripteur['language'][$lang]])) {
$success = file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($languageData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
$success = $this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($languageData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
$success = is_int($success) ? true : false;
}
}
@ -255,7 +255,7 @@ class language extends common
self::$languagesUiInstalled[$file] = [
template::flag($file, '20 %') . '&nbsp;' . self::$languages[$file],
$value['version'],
helper::dateUTF8('%d/%m/%Y', $value['date'], self::$siteContent),
helper::dateUTF8('%d/%m/%Y', $value['date'], self::$i18nUI),
//self::$i18nUI === $file ? helper::translate('Interface') : '',
'',
/*
@ -271,7 +271,7 @@ class language extends common
'class' => isset($storeUI[$file]['version']) && version_compare($installedUI[$file]['version'], $storeUI[$file]['version']) < 0 ? 'buttonGreen' : '',
'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file,
'value' => template::ico('update'),
'help' => 'Mettre à jour',
'help' => 'Mise à jour',
]),
template::button('translateContentLanguageUIDelete' . $file, [
'class' => 'translateDelete buttonRed' . (in_array($file, $usersUI) ? ' disabled' : ''),
@ -291,7 +291,7 @@ class language extends common
self::$languagesStore[$file] = [
template::flag($file, '20 %') . '&nbsp;' . self::$languages[$file],
$value['version'],
helper::dateUTF8('%d/%m/%Y', $value['date'], self::$siteContent),
helper::dateUTF8('%d/%m/%Y', $value['date'], self::$i18nUI),
'',
template::button('translateContentLanguageUIDownload' . $file, [
'class' => 'buttonGreen',
@ -435,7 +435,7 @@ class language extends common
// La locale est-elle celle de la langue de l'UI ?
if ($lang === self::$siteContent) {
self::$locales[$lang]['locale'] = $this->getData(['locale']);
self::$locales[$lang]['locale'] = $this->getData(['config']);
} else {
// Lire les locales sans passer par les méthodes
self::$locales[$lang] = json_decode(file_get_contents(self::DATA_DIR . $lang . '/locale.json'), true);

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -8,7 +8,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -9,7 +9,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -23,7 +23,8 @@ class page extends common
'edit' => self::GROUP_EDITOR,
'duplicate' => self::GROUP_EDITOR,
'jsEditor' => self::GROUP_EDITOR,
'cssEditor' => self::GROUP_EDITOR
'cssEditor' => self::GROUP_EDITOR,
'register' => self::GROUP_EDITOR,
];
public static $pagesNoParentId = [
'' => 'Aucune'
@ -68,10 +69,10 @@ class page extends common
public static $userProfils = [];
public static $navIconTemplate = [
'dir' => 'Petit triangle',
'open' => 'Grand triangle',
'big' => 'Flèche',
];
'dir' => 'Petit triangle',
'open' => 'Grand triangle',
'big' => 'Flèche',
];
public static $navIconPosition = [
'none' => 'Masqué',
@ -85,12 +86,23 @@ class page extends common
*/
public function duplicate()
{
// La session ne correspond pas au site ouvert dans cet onglet
if (
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
) {
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
exit();
}
// Adresse sans le token
$page = $this->getUrl(2);
// La page n'existe pas
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
$this->getData(['page', $page]) === null
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|| $this->getData(['page', $page]) === null
) {
// Valeurs en sortie
$this->addOutput([
@ -107,18 +119,20 @@ class page extends common
$page
]);
// Ecriture
$this->setData(['page', $pageId, $data]);
$this->setData(['page', $pageId, $data], false);
$notification = helper::translate('Page dupliquée');
// Duplication du module présent
if ($this->getData(['page', $page, 'moduleId'])) {
$data = $this->getData(['module', $page]);
$this->setData(['module', $pageId, $data]);
$this->setData(['module', $pageId, $data], false);
$notification = helper::translate('Page et module dupliqués');
}
// Force la sauvegarde
$this->saveDB('page');
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $pageId,
'redirect' => helper::baseUrl() . 'page/edit/' . $pageId . '/' . self::$siteContent,
'notification' => $notification,
'state' => true
]);
@ -131,7 +145,19 @@ class page extends common
*/
public function add()
{
if ($this->getUser('permission', __CLASS__, __FUNCTION__) !== true) {
// La session ne correspond pas au site ouvert dans cet onglet
if (
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
) {
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
exit();
}
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
@ -180,8 +206,8 @@ class page extends common
//file_put_contents(self::DATA_DIR . self::$siteContent . '/content/' . $pageId . '.html', '<p>Contenu de votre nouvelle page.</p>');
$this->setPage($pageId, '<p>Contenu de votre nouvelle page.</p>', self::$siteContent);
// Met à jour le sitemap
$this->updateSitemap();
// Ne met à jour le sitemap pour éviter un warning, de toute manière la nouvelle page doit être éditée.
// $this->updateSitemap();
// Valeurs en sortie
$this->addOutput([
@ -198,12 +224,24 @@ class page extends common
*/
public function delete()
{
// La session ne correspond pas au site ouvert dans cet onglet
if (
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
) {
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
exit();
}
// $url prend l'adresse sans le token
$page = $this->getUrl(2);
// La page n'existe pas
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
$this->getData(['page', $page]) === null
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|| $this->getData(['page', $page]) === null
) {
// Valeurs en sortie
$this->addOutput([
@ -214,8 +252,10 @@ class page extends common
elseif ($page === $this->homePageId()) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
'redirect' => helper::baseUrl() . $this->homePageId(),
'notification' => self::$siteContent === 'home'
? helper::translate('Suppression interdite, cette page est définie comme page d\'accueil du site')
: helper::translate('Suppression interdite, cette page est définie comme page d\'accueil d\'un espace')
]);
}
// Impossible de supprimer la page affectée
@ -223,7 +263,7 @@ class page extends common
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
]);
}
// Impossible de supprimer la page affectée
@ -231,7 +271,7 @@ class page extends common
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
]);
}
// Impossible de supprimer la page affectée
@ -239,7 +279,7 @@ class page extends common
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
]);
}
// Impossible de supprimer la page affectée
@ -247,7 +287,7 @@ class page extends common
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
]);
}
// Impossible de supprimer la page affectée
@ -255,14 +295,14 @@ class page extends common
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
]);
}
// Impossible de supprimer une page contenant des enfants
elseif ($this->getHierarchy($page, null)) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $page,
'redirect' => helper::baseUrl() . 'page/edit/' . $page . '/' . self::$siteContent,
'notification' => helper::translate('Impossible de supprimer une page contenant des pages enfants')
]);
}
@ -302,10 +342,24 @@ class page extends common
*/
public function edit()
{
// La session ne correspond pas au site ouvert dans cet onglet
if (
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
$this->getUrl(3) && $this->getUrl(3) != self::$siteContent
) {
$_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
exit();
}
// La page n'existe pas
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
$this->getData(['page', $this->getUrl(2)]) === null
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|| $this->getData(['page', $this->getUrl(2)]) === null
// Contrôle la présence de l'id d'espace uniquement si l'id est fourni afin de ne pas bloquer les modules non mis à jour
|| (
$this->getUrl(3)
&& $this->getUrl(3) != self::$siteContent
)
) {
// Valeurs en sortie
$this->addOutput([
@ -339,11 +393,11 @@ class page extends common
$pageId = helper::increment($pageId, self::$moduleIds);
// Met à jour les enfants
foreach ($this->getHierarchy($this->getUrl(2), null) as $childrenPageId) {
$this->setData(['page', $childrenPageId, 'parentPageId', $pageId]);
$this->setData(['page', $childrenPageId, 'parentPageId', $pageId], false);
}
// Change l'id de page dans les données des modules
if ($this->getData(['module', $this->getUrl(2)]) !== null) {
$this->setData(['module', $pageId, $this->getData(['module', $this->getUrl(2)])]);
$this->setData(['module', $pageId, $this->getData(['module', $this->getUrl(2)])], false);
$this->deleteData(['module', $this->getUrl(2)]);
// Renommer le dossier du module
$moduleId = $this->getData(['page', $this->getUrl(2), 'moduleId']);
@ -354,12 +408,39 @@ class page extends common
copy($modulesData[$moduleId]['dataDirectory'] . $this->getUrl(2), $modulesData[$moduleId]['dataDirectory'] . $pageId);
$this->deleteDir($modulesData[$moduleId]['dataDirectory'] . $this->getUrl(2));
// Mettre à jour le nom de la feuille de style
$this->setData(['module', $pageId, 'theme', 'style', $modulesData[$moduleId]['dataDirectory'] . $pageId]);
$this->setData(['module', $pageId, 'theme', 'style', $modulesData[$moduleId]['dataDirectory'] . $pageId], false);
}
// Sauvegarde la base manuellement
$this->saveDB('module');
}
// Met à jour les historiques des utilisateurs
foreach ($this->getData(['enrolment', self::$siteContent]) as $userId => $userData) {
// Vérifier si l'utilisateur a un historique
if (
isset($userData["history"])
&& isset($userData['history'][$this->getUrl(2)])
) {
// Remplacer l'ancienne ID par la nouvelle
$datas = $this->getData(['enrolment', self::$siteContent, $userId, 'history', $this->getUrl(2)]);
$this->setData(['enrolment', self::$siteContent, $userId, 'history', $pageId, $datas], false);
$this->deleteData(['enrolment', self::$siteContent, $userId, 'history', $this->getUrl(2)]);
}
// Mettre à jour la dernière page vue si nécessaire
if ($this->getData(['enrolment', self::$siteContent, $userId, 'lastPageView']) === $this->getUrl(2)) {
$this->setData(['enrolment', self::$siteContent, $userId, 'lastPageView', $pageId], false);
}
}
// Sauvegarde la base manuellement
$this->saveDB('enrolment');
// Met à jour la homePage si nécessaire
if ($this->getUrl(2) === $this->getData(['course', self::$siteContent, 'homePageId'])) {
$this->setData(['course', self::$siteContent, 'homePageId', $pageId]);
}
// Si la page correspond à la page d'accueil, change l'id dans la configuration du site
if ($this->getData(['config', 'homePageId']) === $this->getUrl(2)) {
$this->setData(['config', 'homePageId', $pageId]);
$this->setData(['config', 'homePageId', $pageId], false);
}
}
// Supprime les données du module en cas de changement de module
@ -375,20 +456,22 @@ class page extends common
}
// Traitement des pages spéciales affectées dans la config :
if ($this->getUrl(2) === $this->getData(['config', 'legalPageId'])) {
$this->setData(['config', 'legalPageId', $pageId]);
$this->setData(['config', 'legalPageId', $pageId], false);
}
if ($this->getUrl(2) === $this->getData(['config', 'searchPageId'])) {
$this->setData(['config', 'searchPageId', $pageId]);
$this->setData(['config', 'searchPageId', $pageId], false);
}
if ($this->getUrl(2) === $this->getData(['config', 'page404'])) {
$this->setData(['config', 'page404', $pageId]);
$this->setData(['config', 'page404', $pageId], false);
}
if ($this->getUrl(2) === $this->getData(['config', 'page403'])) {
$this->setData(['config', 'page403', $pageId]);
$this->setData(['config', 'page403', $pageId], false);
}
if ($this->getUrl(2) === $this->getData(['config', 'page302'])) {
$this->setData(['config', 'page302', $pageId]);
$this->setData(['config', 'page302', $pageId], false);
}
// Sauvegarde la base manuellement
$this->saveDB(module: 'config');
// Si la page est une page enfant, actualise les positions des autres enfants du parent, sinon actualise les pages sans parents
$lastPosition = 1;
$hierarchy = $this->getInput('pageEditParentPageId') ? $this->getHierarchy($this->getInput('pageEditParentPageId')) : array_keys($this->getHierarchy());
@ -407,11 +490,12 @@ class page extends common
$lastPosition++;
}
// Change la position
$this->setData(['page', $hierarchyPageId, 'position', $lastPosition]);
$this->setData(['page', $hierarchyPageId, 'position', $lastPosition], false);
// Incrémente pour la prochaine position
$lastPosition++;
}
}
if ($this->getinput('pageEditBlock') !== 'bar') {
$barLeft = $this->getinput('pageEditBarLeft');
$barRight = $this->getinput('pageEditBarRight');
@ -432,7 +516,7 @@ class page extends common
) {
foreach ($this->getHierarchy($pageId) as $parentId => $childId) {
if ($this->getData(['page', $childId, 'parentPageId']) === $pageId) {
$this->setData(['page', $childId, 'position', 0]);
$this->setData(['page', $childId, 'position', 0], false);
}
}
}
@ -441,17 +525,17 @@ class page extends common
if ($this->getinput('pageEditBlock') === 'bar') {
foreach ($this->getHierarchy() as $eachPageId => $parentId) {
if ($this->getData(['page', $eachPageId, 'barRight']) === $this->getUrl(2)) {
$this->setData(['page', $eachPageId, 'barRight', $pageId]);
$this->setData(['page', $eachPageId, 'barRight', $pageId], false);
}
if ($this->getData(['page', $eachPageId, 'barLeft']) === $this->getUrl(2)) {
$this->setData(['page', $eachPageId, 'barLeft', $pageId]);
$this->setData(['page', $eachPageId, 'barLeft', $pageId], false);
}
foreach ($parentId as $childId) {
if ($this->getData(['page', $childId, 'barRight']) === $this->getUrl(2)) {
$this->setData(['page', $childId, 'barRight', $pageId]);
$this->setData(['page', $childId, 'barRight', $pageId], false);
}
if ($this->getData(['page', $childId, 'barLeft']) === $this->getUrl(2)) {
$this->setData(['page', $childId, 'barLeft', $pageId]);
$this->setData(['page', $childId, 'barLeft', $pageId], false);
}
}
}
@ -538,7 +622,7 @@ class page extends common
}
}
// Construction du formulaire
// Met à jour le sitemap
$this->updateSitemap();
@ -602,14 +686,15 @@ class page extends common
$css = $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG);
// Enregistre le CSS
$this->setData([
'page', $this->getUrl(2),
'page',
$this->getUrl(2),
'css',
$css
]);
// Valeurs en sortie
$this->addOutput([
'notification' => helper::translate('Modifications enregistrées'),
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
'state' => true
]);
}
@ -636,14 +721,15 @@ class page extends common
$js = $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG);
// Enregistre le JS
$this->setData([
'page', $this->getUrl(2),
'page',
$this->getUrl(2),
'js',
$js
]);
// Valeurs en sortie
$this->addOutput([
'notification' => helper::translate('Modifications enregistrées'),
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
'state' => true
]);
}
@ -659,7 +745,7 @@ class page extends common
/**
* Retourne les informations sur les pages en omettant les clés CSS et JS qui occasionnent des bugs d'affichage dans l'éditeur de page
* @return array tableau associatif des pages dans le menu
* @return string tableau associatif des pages dans le menu
*/
public function getPageInfo()
{
@ -669,6 +755,27 @@ class page extends common
return $d;
}, $p);
return json_encode($d);
}
/**
* Stocke la variable dans les paramètres de l'utilisateur pour activer la tab à sa prochaine visite
* @return never
*/
public function register(): void
{
$this->setData([
'user',
$this->getUser('id'),
'view',
[
'page' => $this->getUrl(2),
'config' => $this->getData(['user', $this->getUser('id'), 'view', 'config']),
]
]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $this->getUrl(3) . '/' . self::$siteContent,
]);
}
}

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -3,7 +3,7 @@
<div class="col1">
<?php echo template::button('pageCssEditorBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2),
'href' => helper::baseUrl() . 'page/edit/' . $this->getUrl(2) . '/' . self::$siteContent,
'value' => template::ico('left')
]); ?>
</div>

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @authorFrédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
@ -67,16 +67,18 @@ $( document ).ready(function() {
/**
* Sélection des onglets
*/
var pageLayout = getCookie("pageLayout");
if (pageLayout == null) {
pageLayout = "content";
setCookie("pageLayout", "content");
var pageLayout = "<?php echo $this->getData(['user', $this->getUser('id'), 'view', 'page']);?>";
// Non défini, valeur par défaut
if (pageLayout == "") {
pageLayout = "content";
}
// Tout cacher
$("#pageEditContentContainer").hide();
$("#pageEditExtensionContainer").hide();
$("#pageEditPositionContainer").hide();
$("#pageEditLayoutContainer").hide();
$("#pageEditPermissionContainer").hide();
// Afficher la bonne tab
$("#pageEdit" + capitalizeFirstLetter(pageLayout) + "Container").show();
$("#pageEdit" + capitalizeFirstLetter(pageLayout) + "Button").addClass("activeButton");
@ -295,7 +297,6 @@ $( document ).ready(function() {
$("#PageEditPositionButton").removeClass("activeButton");
$("#pageEditLayoutButton").removeClass("activeButton");
$("#pageEditPermissionButton").removeClass("activeButton");
setCookie("pageLayout", "content");
});
$("#pageEditExtensionButton").on("click", function () {
$("#pageEditContentContainer").hide();
@ -308,7 +309,6 @@ $( document ).ready(function() {
$("#PageEditPositionButton").removeClass("activeButton");
$("#pageEditLayoutButton").removeClass("activeButton");
$("#pageEditPermissionButton").removeClass("activeButton");
setCookie("pageLayout", "extension");
});
$("#PageEditPositionButton").on("click", function () {
$("#pageEditContentContainer").hide();
@ -321,7 +321,6 @@ $( document ).ready(function() {
$("#PageEditPositionButton").addClass("activeButton");
$("#pageEditLayoutButton").removeClass("activeButton");
$("#pageEditPermissionButton").removeClass("activeButton");
setCookie("pageLayout", "position");
});
$("#pageEditLayoutButton").on("click", function () {
$("#pageEditContentContainer").hide();
@ -334,7 +333,6 @@ $( document ).ready(function() {
$("#PageEditPositionButton").removeClass("activeButton");
$("#pageEditLayoutButton").addClass("activeButton");
$("#pageEditPermissionButton").removeClass("activeButton");
setCookie("pageLayout", "layout");
});
$("#pageEditPermissionButton").on("click", function () {
$("#pageEditContentContainer").hide();
@ -347,7 +345,6 @@ $( document ).ready(function() {
$("#pageEditPositionButton").removeClass("activeButton");
$("#pageEditLayoutButton").removeClass("activeButton");
$("#pageEditPermissionButton").addClass("activeButton");
setCookie("pageLayout", "permission");
});
/**
@ -722,30 +719,6 @@ function buildPagesList(extraPosition) {
positionDOM.val(positionSelected);
};
/**
* Cookies
*/
function setCookie(name, value, days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/; samesite=lax";
}
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1, c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
}
return null;
}
// Define function to capitalize the first letter of a string
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);

View File

@ -1,4 +1,6 @@
<?php echo template::formOpen('pageEditForm'); ?>
<!-- Variable transmise à TinyMCE -->
<div id="zwii_site_content" data-variable="<?php echo htmlspecialchars(isset($_SESSION['ZWII_SITE_CONTENT']) ? $_SESSION['ZWII_SITE_CONTENT'] : 'home'); ?>"></div>
<div class="row">
<div class="col1">
<?php echo template::button('configModulesBack', [
@ -7,26 +9,17 @@
'value' => template::ico('left')
]); ?>
</div>
<div class="col1">
<?php /**echo template::button('pageEditHelp', [
'href' => 'https://doc.zwiicms.fr/edition-des-pages',
'target' => '_blank',
'value' => template::ico('help'),
'class' => 'buttonHelp',
'help' => 'Consulter l\'aide en ligne'
]); */?>
</div>
<div class="col1 offset6">
<div class="col1 offset7">
<?php echo template::button('pageEditDelete', [
'class' => 'buttonRed',
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(2),
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(2) . '/' . self::$siteContent,
'value' => template::ico('trash'),
'help' => 'Effacer la page'
]); ?>
</div>
<div class="col1">
<?php echo template::button('pageEditDuplicate', [
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2),
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2) . '/' . self::$siteContent,
'value' => template::ico('clone'),
'help' => 'Dupliquer la page'
]); ?>
@ -41,23 +34,28 @@
<div class="tab">
<?php echo template::button('pageEditContentButton', [
'value' => 'Contenu',
'class' => 'buttonTab'
'class' => 'buttonTab',
'href' => helper::baseUrl() . 'page/register/content/' . $this->geturl(2)
]); ?>
<?php echo template::button('PageEditPositionButton', [
<?php echo template::button('pageEditPositionButton', [
'value' => 'Menu',
'class' => 'buttonTab'
'class' => 'buttonTab',
'href' => helper::baseUrl() . 'page/register/position/' . $this->geturl(2)
]); ?>
<?php echo template::button('pageEditExtensionButton', [
'value' => 'Extension',
'class' => 'buttonTab'
'class' => 'buttonTab',
'href' => helper::baseUrl() . 'page/register/extension/' . $this->geturl(2)
]); ?>
<?php echo template::button('pageEditLayoutButton', [
'value' => 'Mise en page',
'class' => 'buttonTab'
'class' => 'buttonTab',
'href' => helper::baseUrl() . 'page/register/layout/' . $this->geturl(2)
]); ?>
<?php echo template::button('pageEditPermissionButton', [
'value' => 'Permission',
'class' => 'buttonTab'
'class' => 'buttonTab',
'href' => helper::baseUrl() . 'page/register/permission/' . $this->geturl(2)
]); ?>
</div>
@ -67,11 +65,6 @@
<div class="block">
<h4>
<?php echo helper::translate('Titres'); ?>
<!--<span id="infoHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/informations-generales" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>-->
</h4>
<div class="row">
<div class="col8">
@ -120,11 +113,6 @@
<div class="block">
<h4>
<?php echo helper::translate('Emplacement dans le menu'); ?>
<!--<span id="positionHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/emplacement-dans-le-menu" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>-->
</h4>
<div class="blockContainer">
<div class="row">
@ -176,11 +164,6 @@
<div class="block">
<h4>
<?php echo helper::translate('Options avancées'); ?>
<!--<span id="advancedHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/options-d-emplacement-avancee" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>-->
</h4>
<div class="blockContainer">
<div class="row">
@ -195,7 +178,8 @@
'help' => 'Sélectionnez une image ou une icône de petite dimension',
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
'label' => 'Icône',
'value' => $this->getData(['page', $this->getUrl(2), 'iconUrl'])
'value' => $this->getData(['page', $this->getUrl(2), 'iconUrl']),
'folder' => $this->getData(['page', $this->getUrl(2), 'iconUrl']) ? dirname($this->getData(['page', $this->getUrl(2), 'iconUrl'])) : '',
]); ?>
</div>
</div>
@ -292,11 +276,6 @@
<div class="block">
<h4>
<?php echo helper::translate('Mise en page'); ?>
<!--<span id="layoutHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/mise-en-page-2" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>-->
</h4>
<div class="blockContainer">
<div class="row">
@ -372,11 +351,6 @@
<div class="block">
<h4>
<?php echo helper::translate('Permission et référencement'); ?>
<!--<span id="seoHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/permission-et-referencement" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>-->
</h4>
<div class="blockContainer">
<div class="row">
@ -424,5 +398,4 @@
</div>
</div>
</div>
<?php echo template::formClose(); ?>

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/

Some files were not shown because too many files have changed in this diff Show More