Compare commits

..

1093 Commits

Author SHA1 Message Date
d9cc10e109 Merge branch '13500' 2024-12-23 15:54:37 +01:00
041c23ed2a Branche 13 2024-12-23 15:44:35 +01:00
e0fb90d207 Filtrage champ de saisie clé 2024-12-23 15:33:05 +01:00
3af3dcd681 2018-2025 2024-12-23 15:24:11 +01:00
dfc0ff7cd0 Messages de redirection 2024-12-23 15:21:30 +01:00
71bc687ad6 change 2024-12-21 22:49:01 +01:00
3ef6d5b1e7 13.5 Configuration du site, la page ne se recharge plus après un changement d'onglet.
Le dernier onglet vu avant un submit est mémorisé.
2024-12-21 22:46:56 +01:00
a1c7457a1d 13.5 bouton d'édition actif d'une page dont le module a été supprimé par FTP
Mise à jour du change
2024-12-21 21:56:24 +01:00
d2d390d75c Merge branch '13500' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS into 13500 2024-12-20 22:06:30 +01:00
1205065ddc changes 2024-12-20 22:06:11 +01:00
a7cc18230b changes 2024-12-20 22:03:06 +01:00
0caf5ba9fd Edition de la traduction 2024-12-20 21:58:23 +01:00
d19814f220 Revert "Gallery 4.3 sans le vendor tablednd"
This reverts commit c977608f0d.
2024-12-20 21:44:02 +01:00
c977608f0d Gallery 4.3 sans le vendor tablednd 2024-12-20 21:40:00 +01:00
13e0a09e70 Supprime flatpickr dans les vendors 2024-12-20 21:35:53 +01:00
020e72931b 15300 Bug mise à jour des fichiers de langues 2024-12-20 17:41:23 +01:00
8ee10b4d9a Supprimer site/i18n/fr_FR.json 2024-12-20 17:30:02 +01:00
6d59524517 Supprimer site/i18n/es.json 2024-12-20 17:29:59 +01:00
d2cd0ec203 Supprimer site/i18n/en_EN.json 2024-12-20 17:29:54 +01:00
0015e151d0 Supprimer site/i18n/pt_PT.json 2024-12-20 17:29:44 +01:00
3d2bd2140c Supprimer site/i18n/it.json 2024-12-20 17:29:40 +01:00
8a54453636 Supprimer site/i18n/fr_FR.json 2024-12-20 17:29:36 +01:00
0deaed7a4b Supprimer site/i18n/es.json 2024-12-20 17:29:32 +01:00
14b65767fc Supprimer site/i18n/en_EN.json 2024-12-20 17:29:28 +01:00
6507172bae Supprimer site/i18n/de.json 2024-12-20 17:29:18 +01:00
3895f8357e Nom de bouton 2024-12-20 17:28:32 +01:00
f0951d4a60 DOuble authentification et fichiers de langues 2024-12-19 22:07:05 +01:00
173d7f779c 13500 Amélioration double authentification + mise à jour des fichiers de langue 2024-12-19 22:06:12 +01:00
6515f21350 Merge branch '13400' 2024-12-18 16:55:44 +01:00
1f71dc768f libellés et absence de double authentification si compte inférieur au seuil 2024-12-16 21:40:07 +01:00
7c4bd0baba 13400 fichiers de langues 2024-12-12 18:58:34 +01:00
bd576a06c2 allemand et anglais 2024-12-12 09:40:44 +01:00
7ddaefee57 Fichier de langues inclus correction en de et es 2024-12-10 16:52:15 +01:00
150f1b7cae Chaine initiale 2024-12-10 16:17:07 +01:00
3de997b93e 13.5 Mémorisation dans la configuration de la langue sélectionnée par défaut. 2024-12-10 16:05:26 +01:00
a37d587281 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS 2024-12-09 21:22:49 +01:00
85940755cb Langue sélectionnée à l'installation quand le bouton back est cliqué 2024-12-09 21:16:01 +01:00
ee4a27982d Langue sélectionnée à l'installation quand le bouton back est cliqué 2024-12-09 21:14:19 +01:00
4980b7048f 13.5 Avertissement double authentification
Thème login et auth
2024-12-07 18:10:54 +01:00
abcad7ea77 méthode inputfile attribut fldr 2024-12-05 18:59:30 +01:00
2d2bca5e23 Amélioration de la méthode de backup 2024-12-05 18:11:03 +01:00
114dcad072 Blog 8.1 2024-12-05 13:12:29 +01:00
d6b04a0bb2 Bug install module données 2024-12-04 22:13:25 +01:00
7840b56dbd Revert "bug installation WIP"
This reverts commit fd6ceed527.
2024-12-04 21:49:05 +01:00
fd6ceed527 bug installation WIP 2024-12-04 14:57:03 +01:00
5c0b6baf95 Merge branch 'doubleauth' 2024-12-04 14:10:29 +01:00
d81ccb81e7 13500 changes 2024-12-04 14:05:09 +01:00
fb30c6495a Server LightSpeed 2024-11-28 20:31:49 +01:00
550259e8ea 13.5.00 et non 13.6.00 2024-11-27 19:38:18 +01:00
e736057533 Revert "13.6.00 bug mémorisation update"
This reverts commit 4ecace2b42.
2024-11-27 16:30:28 +01:00
4ecace2b42 13.6.00 bug mémorisation update 2024-11-27 14:26:11 +01:00
bad1c108ab 13.6.00 double authentification 2024-11-27 12:13:29 +01:00
2ba03c2453 Temps de validité à implémenter dans la configuration 2024-11-16 08:38:39 +01:00
fb439395e7 config authkey WIP 2024-11-14 21:18:50 +01:00
34475f945d manque l'option dans config 2024-11-14 18:35:53 +01:00
823e1cfd0e news 6 bug date 2024-10-16 11:53:31 +02:00
c0e6781dda news 6 option show pseudo 2024-10-15 15:19:38 +02:00
341e002ef2 Option signature de l'auteur 2024-10-15 14:40:13 +02:00
a87d04ef5f Blog 6 fix option bouton 2024-10-14 22:18:59 +02:00
11656c72ca Optimisation setData 2024-10-12 11:16:46 +02:00
72ee7c9ab6 News 6 supprime les tirets 2024-10-12 09:15:27 +02:00
483ebd64fe News 6.0 ajout des options date et heure 2024-10-12 08:46:05 +02:00
1a6fadf976 supprime console.log 2024-10-12 08:15:38 +02:00
9b3c7707f0 supprime un console log 2024-10-12 08:07:58 +02:00
261ef2f312 Blog 8 options d'affichage smarts 2024-10-12 08:06:49 +02:00
0abb336850 Blog 8.00 ajoute les options d'affichage de la date et de l'heure 2024-10-11 11:34:13 +02:00
82b55210d8 13.5.00 fix subword 2024-10-10 20:02:26 +02:00
41f36ef5e6 13.5.00 fix subword 2024-10-10 19:57:27 +02:00
71dfbff8d7 Blog 7.12 2024-10-09 20:49:27 +02:00
1c57e8dd1d 13.5.00 Blog 7.12 2024-10-08 15:23:58 +02:00
625308b74b fix update store 2024-10-03 12:04:53 +02:00
466e557c1d bug changement de mot de passe changes 2024-10-02 19:03:37 +02:00
121013a48a 13500 Bug changement de mot de passe 2024-10-02 19:02:37 +02:00
1fcc5f92a8 version 13.5.00 2024-10-02 12:54:19 +02:00
1c8e2038f6 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS 2024-10-02 12:17:35 +02:00
29b0a28173 13500 2024-10-02 12:17:31 +02:00
bd6d5f0128 13500 2024-10-02 12:15:53 +02:00
6bbd622a98 Importe les dernières modifs
Merge branch 'master' into common_global
2024-09-30 19:18:52 +02:00
d39bf7bc86 Refactor 2024-09-30 19:15:38 +02:00
ffd80cde21 Version 13.4.01 2024-09-30 19:05:37 +02:00
65e2dc8dff branche de base 134 2024-09-30 18:59:55 +02:00
e52c25ad0b Commente les tests de perf 2024-09-30 18:53:24 +02:00
55c7791efa init 2024-09-30 18:47:20 +02:00
ec2fc0ab4f branche 134 !! 2024-09-30 15:40:23 +02:00
16d4d16950 Bug de connexion lorsque le site à situé à la racine 2024-09-30 15:32:55 +02:00
b7be76a7e4 Auto update traite les status 401 et 403 2024-09-30 14:59:32 +02:00
d6072c8591 Erreur page de reconnexion 2024-09-30 14:55:31 +02:00
23d2631fd7 Common cache optimization 2024-09-29 23:20:47 +02:00
06b3690d48 Fix common construct to improve perf 2024-09-29 21:22:52 +02:00
3c32b3650e Optimisation postinstall creation unique des pages 2024-09-29 19:34:10 +02:00
101bae34e8 FIX bug avec secure_put_contents
Install optimisation config
2024-09-29 18:53:42 +02:00
f7d53906e2 Changes 2024-09-29 16:17:30 +02:00
bdc9e40627 Supprime le log 2024-09-29 16:12:40 +02:00
d5dfdca9d2 Numéro de la version 2024-09-29 16:04:41 +02:00
ce6c4929a0 changes 2024-09-29 16:00:49 +02:00
c3ac31de69 rebase 2024-09-29 15:58:56 +02:00
24e1238e50 Position des boutons dans la config et précise la cible de trace secure. 2024-09-29 15:56:54 +02:00
281e578f4d Config, double rafraissement, rien à voir avec les process 2024-09-29 15:56:54 +02:00
1a88ae05e6 ajoute les traceurs 2024-09-29 15:56:54 +02:00
df0c579af0 Supprime les save excessifs 2024-09-29 15:56:54 +02:00
a25dbc6bd2 Corrections Rémi 2024-09-29 15:56:54 +02:00
8e1c8a5ba5 13.4.00.test7 évite la création d'un user vide au logout 2024-09-29 15:56:54 +02:00
cce2983347 changes 13307 2024-09-29 15:56:53 +02:00
6c2bed771c 13.4.00.test6 prend en compte la déconnexion à la mise à jour 2024-09-29 15:56:53 +02:00
ae265ba5e7 gestion erreur simplifiée 2024-09-29 15:56:53 +02:00
909c79559b Revert "vide le tampon"
This reverts commit 568b79e854.
2024-09-29 15:56:33 +02:00
97c8573de8 vide le tampon 2024-09-29 15:56:33 +02:00
6274d2c1ff ajoute un die 2024-09-29 15:56:33 +02:00
409b7edb94 Traitement de l'erreur étape 4 2024-09-29 15:56:33 +02:00
6b82b3af83 13.4.00.test5 modification install en test 2024-09-29 15:55:38 +02:00
3013f33b35 13.4.00.test4 inverse la position des icones users et config 2024-09-29 15:55:38 +02:00
77fbb45c71 Fix layouts non initialisés 2024-09-29 15:55:38 +02:00
2a0849e49a Suppression du cookie configLayout 2024-09-29 15:55:38 +02:00
ac8e713935 Suppression du cookie pageLayouts 2024-09-29 15:55:38 +02:00
118dfc79b3 Corrige un bug de déco après édition du compte 2024-09-29 15:55:03 +02:00
6727752a2d Corrige l'affichage des boutons de navigation dans les vues des modules 2024-09-29 15:55:03 +02:00
75a6a093ed 13.4.00.test3 la clé auth n'a pas été déclarée 2024-09-29 15:55:02 +02:00
922cba9f5a Chemin du cookie de session 2024-09-29 15:55:02 +02:00
35d0b2aa3c modification du cookie de consentement 2024-09-29 15:55:02 +02:00
776afaff03 13.4.00.test1 icone plugin rouge si module mis à jour 2024-09-29 15:55:02 +02:00
1c46900156 Actualiser README.md 2024-09-29 15:55:02 +02:00
08a2264709 Remplace le cookie lastposition et affecte l'id de site pour prendren en compte le domaine et le chemin 2024-09-29 15:54:37 +02:00
f7db1bf20f Bouton de génération du sitemap 2024-09-29 15:54:37 +02:00
ffd14a8734 Autorise les moteurs sauf les bots 2024-09-29 15:54:37 +02:00
161c1bcb80 version 2024-09-29 15:54:36 +02:00
02514ff446 changes 2024-09-29 15:54:07 +02:00
fdce67d101 changes 2024-09-29 15:54:07 +02:00
8d1cbc6b88 config RFM thumb 2024-09-29 15:54:06 +02:00
b73f8a1c28 RFM default thumb size 640 2024-09-29 15:54:06 +02:00
00a0c3d795 changes 2024-09-29 15:54:06 +02:00
6b8d769e43 méthode authentification 2024-09-29 15:54:06 +02:00
10b79c586b slider 7.2 voir changelog 2024-09-29 15:54:06 +02:00
3c3579a29d changes 2024-09-29 15:54:06 +02:00
017f02afc4 changes 2024-09-29 15:54:06 +02:00
df235541d1 13400 changes 2024-09-29 15:54:06 +02:00
a456047969 13.4.00 sélecteur de fichier amélioré 2024-09-29 15:53:25 +02:00
ac48e61264 Revert plugin 2024-09-29 15:53:01 +02:00
604bf2db77 correction url catalogue 2024-09-29 15:53:01 +02:00
4055d3e68a csrf key sur 64 octets 2024-09-29 15:50:08 +02:00
393722038b slider 7.2 voir changelog 2024-09-29 15:50:08 +02:00
54c90bec11 changes 2024-09-29 15:49:03 +02:00
039ee80db4 changes 2024-09-29 15:49:03 +02:00
9f30f356cb datables.net filtrage des éléments, nombre d'éléments et position sur l'écran 2024-09-29 15:49:02 +02:00
fd10883652 13400 changes 2024-09-29 15:49:02 +02:00
6805111c47 13.4.00 sélecteur de fichier amélioré 2024-09-29 15:49:02 +02:00
86ce4a75b4 Position des boutons dans la config et précise la cible de trace secure. 2024-09-28 19:04:40 +02:00
03932db20d Config, double rafraissement, rien à voir avec les process 2024-09-28 18:49:29 +02:00
d3f247f6fb ajoute les traceurs 2024-09-28 18:45:48 +02:00
c5af0fb37c Supprime les save excessifs 2024-09-28 18:42:41 +02:00
9532be0cdc Corrections Rémi 2024-09-28 18:02:47 +02:00
e0748c2eb6 13.4.00.test7 évite la création d'un user vide au logout 2024-09-26 19:59:39 +02:00
5811836238 changes 13307 2024-09-25 22:08:25 +02:00
92b3854516 version 13307 2024-09-25 22:07:52 +02:00
e85801db50 13307 2024-09-25 22:02:34 +02:00
53dd6a82e6 tient compte de la déconnexion pdt update 2024-09-25 22:00:58 +02:00
75b230b2ed 13.4.00.test6 prend en compte la déconnexion à la mise à jour 2024-09-25 21:57:08 +02:00
47a5ddb442 gestion erreur simplifiée 2024-09-25 21:41:08 +02:00
d0f779bb9b Revert "vide le tampon"
This reverts commit 568b79e854.
2024-09-25 21:38:01 +02:00
568b79e854 vide le tampon 2024-09-25 21:34:26 +02:00
06bbeb0d2e ajoute un die 2024-09-25 21:25:40 +02:00
75bb94b9a7 Traitement de l'erreur étape 4 2024-09-25 21:13:04 +02:00
dfd0f1ad2a 13.4.00.test5 modification install en test 2024-09-25 17:01:25 +02:00
7a4b1589af 13.4.00.test4 inverse la position des icones users et config 2024-09-19 10:52:11 +02:00
da9d8d9d62 Fix layouts non initialisés 2024-09-19 09:53:52 +02:00
e3bc6ce1d3 Suppression du cookie configLayout 2024-09-18 19:34:04 +02:00
ecd0f5827a Suppression du cookie pageLayouts 2024-09-18 19:01:47 +02:00
c8be7f84a4 Corrige un bug de déco après édition du compte 2024-09-17 19:18:26 +02:00
826e6264eb Corrige l'affichage des boutons de navigation dans les vues des modules 2024-09-17 18:27:02 +02:00
cc0b6edb34 13.4.00.test3 la clé auth n'a pas été déclarée 2024-09-16 22:57:04 +02:00
0e564a24c9 Chemin du cookie de session 2024-09-16 21:20:52 +02:00
7da12be242 modification du cookie de consentement 2024-09-15 19:00:53 +02:00
095e317f3b 13.4.00.test1 icone plugin rouge si module mis à jour 2024-09-15 17:53:23 +02:00
67eeef26a0 Actualiser README.md 2024-09-11 15:25:47 +02:00
2273812b2d Remplace le cookie lastposition et affecte l'id de site pour prendren en compte le domaine et le chemin 2024-09-08 14:59:09 +02:00
4842e3f62b Bouton de génération du sitemap 2024-09-07 14:27:05 +02:00
01c69f0712 Autorise les moteurs sauf les bots 2024-09-07 14:11:01 +02:00
baa5b762e2 version 2024-09-07 09:59:57 +02:00
76cd034fd3 changes 2024-09-07 09:57:42 +02:00
a929fb3482 readme ! 2024-09-07 08:53:07 +02:00
5ea3e12e26 changes 2024-09-07 08:29:53 +02:00
141a22b6ff config RFM thumb 2024-09-07 08:17:35 +02:00
3f1d19f53e RFM default thumb size 640 2024-09-07 08:10:03 +02:00
fcfb3ea677 changes 2024-09-06 19:01:10 +02:00
dfceb941db changes 2024-09-06 19:00:49 +02:00
9db6e5ac13 changes 2024-09-06 18:52:45 +02:00
aceb94da3e changes 2024-09-06 18:52:17 +02:00
12c7682a26 Merge branch 'authKey' 2024-09-06 18:49:18 +02:00
5d282a4cc4 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS 2024-09-06 18:42:16 +02:00
a8bf3ec857 csrf key sur 64 octets 2024-09-06 18:42:03 +02:00
bb9573a82f slider 7.2 voir changelog 2024-09-06 18:42:03 +02:00
15534ba9fa changes 2024-09-06 18:42:03 +02:00
6aecf5e796 changes 2024-09-06 18:42:03 +02:00
25f81af87b datables.net filtrage des éléments, nombre d'éléments et position sur l'écran 2024-09-06 18:42:03 +02:00
c78b43f7b0 Warning à la création d'une nouvelle page 2024-09-06 18:42:02 +02:00
6daeb9e474 13400 changes 2024-09-06 18:42:02 +02:00
5986e8a378 Revert plugin 2024-09-06 18:42:02 +02:00
14068d24a8 13.4.00 sélecteur de fichier amélioré 2024-09-06 18:42:02 +02:00
dd7ee7f2ef correction url catalogue 2024-09-06 18:42:02 +02:00
0f1bd2377e 13.3.06 Login, connexion persistante 2024-09-06 18:42:02 +02:00
5326b94c04 disable save to json pretty print 2024-09-06 18:42:02 +02:00
17f8fb3b58 13.3.06 fix bug mot clé [MODULE] absent 2024-09-06 18:42:02 +02:00
ceca7b10b5 13.3.10 Bug bouton effacement 2024-09-06 18:42:02 +02:00
89c0ae5ead slider 7.1 2024-09-06 18:42:01 +02:00
89be290465 13.3.06 couleurs des balises h1, h3 et A dans le slider 2024-09-06 18:42:01 +02:00
3c3b122fe4 typo changes 2024-09-06 18:42:01 +02:00
61369e7ad1 Merge branch '13306' into authKey 2024-09-06 18:36:47 +02:00
2c31e1aefc 13.3.06 bug de sécurité profil rfm 2024-09-06 18:34:46 +02:00
eb28a76636 méthode authentification 2024-09-06 17:32:29 +02:00
86afa350fa csrf key sur 64 octets 2024-09-06 17:17:34 +02:00
6864132afc slider 7.2 voir changelog 2024-09-06 16:17:10 +02:00
49ab83efd3 changes 2024-09-06 09:34:15 +02:00
27d7b07239 changes 2024-09-06 08:37:17 +02:00
48ee5c5e1b datables.net filtrage des éléments, nombre d'éléments et position sur l'écran 2024-09-06 08:35:35 +02:00
be87e4c740 13400 changes 2024-09-05 11:24:23 +02:00
7f6d010b9c 13.4.00 sélecteur de fichier amélioré 2024-09-05 11:02:01 +02:00
62437c8fac Warning à la création d'une nouvelle page 2024-08-29 06:45:40 +02:00
2d3b999d27 Revert plugin 2024-08-28 21:17:12 +02:00
72655e6673 correction url catalogue 2024-08-28 20:56:16 +02:00
de0749b51b 13.3.06 Login, connexion persistante 2024-08-24 17:29:17 +02:00
3598ab2954 disable save to json pretty print 2024-08-24 15:04:29 +02:00
67d94bce61 13.3.06 fix bug mot clé [MODULE] absent 2024-08-24 07:18:32 +02:00
fa158effc3 13.3.10 Bug bouton effacement 2024-08-23 21:18:37 +02:00
3e3781bc28 slider 7.1 2024-08-22 05:33:10 +02:00
bc70f39ba5 13.3.06 couleurs des balises h1, h3 et A dans le slider 2024-08-22 05:31:27 +02:00
998eb3b8a1 typo changes 2024-08-21 10:20:33 +02:00
8fd4d2f9bc slide 7.0 2024-08-19 16:44:08 +02:00
f04bc17e28 Texte alternatif 2024-08-19 16:01:23 +02:00
ca0561d97c Fix slider button padding 2024-08-19 15:55:47 +02:00
2251d34122 Étiquette 2024-08-19 15:46:45 +02:00
eb832f42e5 Slides corrections 2024-08-19 10:33:38 +02:00
83b4103788 13.3.05 Bugs module Sliders 2024-08-19 10:11:29 +02:00
1b9c65189d Changes 2024-08-15 18:12:13 +02:00
c2281b93ef changes 2024-08-15 18:01:52 +02:00
1b3601ce87 Corrige le filtre FILTER_FLOAT: pour la géolocalisation 2024-08-15 17:55:11 +02:00
78905834bd pas de mois ni de numéro de semaine 2024-08-14 09:21:32 +02:00
c270546a9b Bug de filtre 2024-08-14 09:11:06 +02:00
ad15e8b827 A tester 2024-08-14 09:09:26 +02:00
f84bcbb878 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS 2024-08-13 21:38:25 +02:00
62d4d8243a typo 2024-08-13 21:37:19 +02:00
3e238af50a 13.3.05 correction des filtres pour agenda 2024-08-13 21:34:34 +02:00
54a0add941 13.3.06 correction des filtres pour agenda 2024-08-13 21:33:01 +02:00
d84f94817b 13.3.06 Mise à jour module blog 2024-08-01 19:17:29 +02:00
2939545c8c 13.3.06 mise à jour module News 2024-07-30 21:16:26 +02:00
c4dc05a4c1 13.3.06 mise à jour du module News 2024-07-30 21:14:59 +02:00
87b763ddae Corrige la génération des miniatures au format avif et webp 2024-07-28 18:05:09 +02:00
c745711a2e 13.3.04 2024-07-27 09:36:05 +02:00
49c8f567e6 changes 2024-06-10 18:22:36 +02:00
2a1b5e2900 Vérification de la réécriture 2024-06-09 02:51:52 +02:00
f2ab357654 changes 2024-06-08 08:23:53 +02:00
8ad199ee3d Page de configuration des modules inactives 2024-06-07 20:47:18 +02:00
6ddadfd8e5 Chargement lassif des images 2024-06-07 09:57:26 +02:00
cee8b784a4 changes 2024-06-07 09:48:48 +02:00
f8e2dd5fab Corrige le bug de FF 2024-06-07 09:47:22 +02:00
20a4cc45d7 Revert "Test problème TinyMCE avec Firefox"
This reverts commit 090a4318b3.
2024-06-07 09:44:00 +02:00
8db6367cba Corrige la détection de serveur 2024-06-07 09:42:59 +02:00
090a4318b3 Test problème TinyMCE avec Firefox 2024-06-07 09:34:39 +02:00
d17fa93bb7 Layout d'édition : supprime tous les boutons de gestion de page comme pour les pages avec module 2024-06-07 09:31:22 +02:00
f030c2f064 Merge branch '13303' of https://forge.chapril.org/ZwiiCMS-TEAM/ZwiiCMS into 13303 2024-06-04 22:29:23 +02:00
323cea2e0b Fusion de deux commits 2024-06-04 22:28:30 +02:00
f81fad1c49 message 2024-06-04 22:23:21 +02:00
ad3e9aba65 Lorsque des éléments inutiles sont ajoutés à l'adresse d'une page, une erreur 403 est levée. 2024-06-04 22:21:05 +02:00
b035efb710 Bug d'URL WIP 2024-06-02 15:30:12 +02:00
ffc373e68f - 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:08:19 +02:00
e42f0bd538 Lignes vides en trop dans htaccess 2024-06-02 14:40:34 +02:00
b86f7fbd4a Htaccess avec anti slash dans tous les cas 2024-06-02 14:34:56 +02:00
96b12bf0d4 htaccess avec la suppression du slash final hors rewriting 2024-06-02 14:31:08 +02:00
97e50f245c 13.3.03 deux corrections 2024-06-01 21:19:56 +02:00
9d32fa2b86 13.3.02 2024-05-14 13:13:56 +02:00
5937915d21 changes 2024-05-08 18:49:36 +02:00
ca15d8f362 13.3.01 2024-05-08 18:42:10 +02:00
f097111d70 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS 2024-05-06 18:18:16 +02:00
177541bef3 Version 2024-05-06 18:18:07 +02:00
3f2a33a7fe Nom de la variable de session 2024-05-06 16:18:35 +02:00
cd9c62b3a3 Version 2024-05-06 15:46:32 +02:00
4a2d59e4b8 changes 2024-04-23 17:50:46 +02:00
c702c41fed Init 2024-04-23 17:42:00 +02:00
b3e3ead5ac self devient common 2024-04-23 17:15:20 +02:00
9bfa8280fd 13.2.02 warning blog vide 2024-04-22 15:35:33 +02:00
55b4e7335d old layout 2024-04-22 14:20:05 +02:00
f7c2aab390 Revert "13.2.01 section par main"
This reverts commit fc69015448.
2024-04-22 14:17:21 +02:00
cdab4659a6 Revert "13.2.01 supprime la balise section"
This reverts commit 9e656294a6.
2024-04-22 14:17:11 +02:00
fc69015448 13.2.01 section par main 2024-04-22 10:56:51 +02:00
9e656294a6 13.2.01 supprime la balise section 2024-04-21 15:55:11 +02:00
8e91faf2d2 13.2.01 2024-04-18 07:56:11 +02:00
36c8619b63 alignement de boutons 2024-04-17 16:42:01 +02:00
d77afce37b Bug génération des pages TinyMCE 2024-04-17 16:27:22 +02:00
bca34949a9 secure_file_contents 2024-04-10 11:58:17 +02:00
07baed8713 13200 secure_file_put_contents and new jsondb json db save 2024-04-09 17:23:26 +02:00
6687c324e5 13.2.00 flock sur le fichier principal (PB sous win) 2024-04-06 09:10:49 +02:00
03d1dacb88 détruit le fichier de verouillage créé par secureFilePutContent 2024-04-05 18:21:51 +02:00
77d8296642 add secureFilePutContents 2024-04-05 17:16:08 +02:00
999370646b 13.2.00 fonction secureFilePutContents 2024-04-05 16:49:08 +02:00
d8f4af660f supprime le verrou inutile 2024-04-05 16:34:01 +02:00
5f146bfbdc 13.2.00 json save 2024-04-05 09:20:34 +02:00
950ba8cc9d 13.1.09 supprime un test dans jsondb 2024-04-03 12:56:06 +02:00
2448e50793 changes 2024-03-30 09:27:49 +01:00
5e29699563 jsondb stoppe après une erreur de chargement 2024-03-30 09:16:31 +01:00
b78fc84a89 13.1.08 search 3.1 2024-03-30 09:11:18 +01:00
665c8dea6d Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-TEAM/ZwiiCMS 2024-03-29 21:47:18 +01:00
159297e421 13.1.08 Bug de page parente avec permission 2024-03-29 21:47:04 +01:00
fc502a1c64 bug de page parente avec permission 2024-03-29 21:47:04 +01:00
457c8e0f66 13.1.08 Bug de page parente avec permission 2024-03-29 21:41:49 +01:00
660398bad7 bug de page parente avec permission 2024-03-29 21:40:55 +01:00
fad19249db Revert "test filter_id slash"
This reverts commit f18d4eee1d.
2024-03-29 19:18:17 +01:00
060aa9e4d5 Squashed commit of the following:
commit 9052247e53
Merge: df06b1f7 f18d4eee
Author: Fred Tempez <frederic.tempez@outlook.com>
Date:   Sat Mar 23 15:36:43 2024 +0100

    Merge commit 'f18d4eee1d1cd9500a30d47d05bea1f773d787af' into HEAD

commit df06b1f7ba
Merge: 8d324f9c fd511229
Author: Fred Tempez <frederic.tempez@outlook.com>
Date:   Sat Mar 23 15:36:02 2024 +0100

    Merge commit 'fd511229181cca42029257d29b0407e5ca598dc9' into HEAD

commit 8d324f9c79
Author: Fred Tempez <frederic.tempez@outlook.com>
Date:   Sat Mar 23 15:33:52 2024 +0100

    Revert "Merge commit 'f924a2b2b3a8a6c53ce050da64e57ac76d388872'"

    This reverts commit b8c0b47faf, reversing
    changes made to f5f04c90d9.
2024-03-23 15:39:22 +01:00
9052247e53 Merge commit 'f18d4eee1d1cd9500a30d47d05bea1f773d787af' into HEAD 2024-03-23 15:36:43 +01:00
df06b1f7ba Merge commit 'fd511229181cca42029257d29b0407e5ca598dc9' into HEAD 2024-03-23 15:36:02 +01:00
8d324f9c79 Revert "Merge commit 'f924a2b2b3a8a6c53ce050da64e57ac76d388872'"
This reverts commit b8c0b47faf, reversing
changes made to f5f04c90d9.
2024-03-23 15:33:52 +01:00
f18d4eee1d test filter_id slash 2024-03-21 15:42:17 +01:00
fd51122918 Mise à jour RSS Feed 2024-03-21 13:26:42 +01:00
15bd0400ea Merge commit '1147b5c5e1fff513cea77da6c0db5a7d2fa3b8a5' 2024-03-18 18:24:26 +01:00
1147b5c5e1 update roling backup 2024-03-18 17:50:54 +01:00
2cbd3d5923 Update rolling backup 2024-03-18 17:40:56 +01:00
11753b4476 add data.key to git ignore 2024-03-18 17:30:35 +01:00
f2a6d35351 change key 2024-03-18 08:51:51 +01:00
c4a23de744 Contrôle de clé 2024-03-18 08:42:36 +01:00
a47cbe49fe Débordements 2024-03-17 21:09:37 +01:00
5f5815cbd9 clean auto backup 2024-03-17 20:49:15 +01:00
e811660d7c 13.1.08 miseà jour automatisée 2024-03-17 12:53:04 +01:00
10083e7ee8 Folder Alignements 2024-03-17 09:13:32 +01:00
d89455d86a Alignement des dates 2024-03-17 09:08:08 +01:00
5e7c9597cd Format de date 2024-03-17 08:07:54 +01:00
49180ab4ed Dossiers dépliés 2024-03-16 08:36:52 +01:00
c4fc466876 config deux options 2024-03-15 21:14:49 +01:00
75203d6e8e config options 2024-03-15 20:13:58 +01:00
f61c2a977a config options 2024-03-15 20:10:06 +01:00
a02ce894c8 13.1.08 changes 2024-03-14 20:36:30 +01:00
2d92bd3963 Merge commit '2a8563ce9ae300b0ffcbab8dd11f8c4bc1cd5d46' 2024-03-14 19:21:31 +01:00
b8c0b47faf Merge commit 'f924a2b2b3a8a6c53ce050da64e57ac76d388872' 2024-03-14 19:20:20 +01:00
2a8563ce9a json vérif 2024-03-14 19:14:13 +01:00
f924a2b2b3 stop on json data error 2024-03-14 19:09:00 +01:00
5846c111fe CSS okay 2024-03-14 15:46:31 +01:00
f86f38d8b0 Fix folder and icons 2024-03-14 14:30:49 +01:00
68d0aaff84 Okay mais probleme de surimpressions 2024-03-14 13:33:37 +01:00
f5f04c90d9 fix user path select 2024-03-14 10:28:42 +01:00
d8525bf123 fix user path select 2024-03-14 10:28:27 +01:00
25d6192e0e folder css okay 2024-03-14 08:50:23 +01:00
90a5a8a96a folder config wip 2024-03-13 18:45:06 +01:00
69852c82bc folder 2024-03-13 16:56:33 +01:00
f3ae03a133 shareFolder 2024-03-13 16:28:19 +01:00
9b5cc38c94 sharefolder WIP 2024-03-12 18:35:44 +01:00
890cf97127 13.1.08 Sauvegarde de l'état des sélecteurs 2024-03-12 13:59:57 +01:00
87a1f2cd18 13107 change 2024-03-06 16:59:52 +01:00
50fc319afd 13.1.07 Corrige une erreur de tri dans RFM dépréciation return usort 2024-02-22 14:34:54 +01:00
a2f53e1e58 Slider 6.4 2024-02-15 14:34:50 +01:00
e6b9cb16b5 13.1.06 slider 6.3 + changes 2024-02-14 15:43:08 +01:00
6f2447533c 13.1.06 fix user add tag 2024-02-11 18:53:57 +01:00
6f946b32ac changes 2024-02-10 20:16:57 +01:00
33e2dca864 13.1.05 version et changes 2024-02-10 20:16:01 +01:00
a890a70beb branche v13 2024-02-10 20:09:16 +01:00
e92c709796 13.1.05 Corrige la fonction deleteValue de la classe dot 2024-02-10 19:48:35 +01:00
bcf75ebfbd changes 2024-02-10 17:24:31 +01:00
c8a6a21f9c 13.1.04 Changes 2024-02-10 17:20:05 +01:00
a176556081 13.1.04 Fix bug dot class 2024-02-10 17:13:35 +01:00
949373b39e Changes 2024-02-06 20:21:13 +01:00
e26beac06c 13104 Protection supplémentaire dans jsonDB 2024-02-06 20:08:40 +01:00
4bfc75288f 13.1.04 Evite la redirection vers une page d'erreur après un login 2024-02-05 20:40:12 +01:00
d1e4c9761f 13.1.04 Journalise l'erreur de mise à jour 2024-02-03 18:59:39 +01:00
dbafb6f4bb Merge tag '13.1.04' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS into 13104 2024-02-03 18:44:55 +01:00
7ad8e3ea05 13.1.04 feuille de style absente de l'index de l'installation 2024-02-03 18:44:15 +01:00
e142f961d9 "Mettre à jour" devient "Mise à jour" 2024-02-03 09:49:30 +01:00
5c97b5cea6 "Mettre à jour" devient "Mise à jour" 2024-02-03 09:35:52 +01:00
d21cfcba78 13.1.04
Changes
Nettoyage des commentaires
2024-02-03 08:27:07 +01:00
c9300e5979 13.01.04 Version et change 2024-02-03 08:08:44 +01:00
8cefdd027d 13.1.04 Bascule en banche de test
Update : checkwrite by file
2024-02-03 08:02:32 +01:00
c3ade0fe0f 13.1.04 new gitignore 2024-02-02 18:03:24 +01:00
d3284c67d8 new gitignore 2024-02-02 17:57:10 +01:00
6b3085ef27 13.1.04 Evite une notice quand la capture Open Graph est indéfinie 2024-02-02 17:47:01 +01:00
748e6d0873 13.1.04 Supprime un point terminal 2024-02-02 17:39:33 +01:00
a9abe8aaa1 update, erreur à l'étape 3 sans message : Erreur de parsing javascript 2024-02-01 18:57:38 +01:00
1fbf91a9cb changes 2024-01-31 18:03:43 +01:00
9485ebe4cb Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS 2024-01-31 18:02:02 +01:00
88e7cb8761 warning user forgot 2024-01-31 18:01:43 +01:00
857a6ff808 Opérateur booléen nouvelle version sans le type 2024-01-31 14:36:23 +01:00
2d6bbcec9e User Edit Désactive l'édition des tags pour les membres 2024-01-27 16:32:16 +01:00
748bb3befb Url relatives 2024-01-27 16:24:47 +01:00
29d6b1c758 changes 2024-01-26 16:35:19 +01:00
696ca111b7 13103 Bug Date siteContent 2024-01-26 16:34:01 +01:00
a8381b4c18 13103 changes 2024-01-19 15:14:36 +01:00
0895abc30b Double variable Blog date 2024-01-18 19:19:50 +01:00
3539c3b04e warning user forgot 2024-01-18 18:33:12 +01:00
77aa46f753 Markdown in TinyMCE 2024-01-18 15:31:37 +01:00
42ef876963 Changes 2024-01-17 18:35:53 +01:00
3bfcaa4187 Thème fonte Améliore le code discrimant les fontes utilisées et prend en compte le thème admin 2024-01-17 18:27:21 +01:00
5a5e9dc72c Version et changes 2024-01-15 20:22:00 +01:00
4606d987b2 2024 2024-01-14 19:31:28 +01:00
b403816c88 Bug sitemap date format 2024-01-13 13:33:57 +01:00
470c017184 layout pour les memebres simples uniquement 2024-01-08 14:56:32 +01:00
0720db7b17 User edit profil select current value 2024-01-08 14:42:19 +01:00
1a61f34c19 changes 2024-01-07 19:53:30 +01:00
94eda284ed 13.1.02 fix add user language + changes 2024-01-07 16:18:44 +01:00
9ae67cd2f3 Sauvegarde des fontes installées 2024-01-06 23:17:45 +01:00
b6b5461241 fonte nettoyage des majuscules et des espaces dans l'id de la fonte 2024-01-06 16:19:31 +01:00
9fac118004 fonte installée ou importée 2024-01-06 16:04:15 +01:00
92c7384816 Fix mauvais message fonte en ligne 2024-01-06 15:48:43 +01:00
9be5dab828 changes 2024-01-06 09:29:48 +01:00
c6ae372429 Bug fonte delete 2024-01-06 09:26:40 +01:00
22e0b71012 Bug ajout de fonte 2024-01-05 20:49:23 +01:00
f0bec949bb charge les fontes avant tout + fontedit readonly 2024-01-05 20:30:43 +01:00
0d42ca0740 Fonte edit id disabled 2024-01-05 00:17:39 +01:00
18228b1b8e Fix pb de chemin pour les rédacteurs avec droit RFM 2024-01-04 23:54:40 +01:00
824ab8401a Bug chemin profil 2-2 2024-01-04 22:03:26 +01:00
7249abc649 File cloud download icon 2024-01-04 16:46:19 +01:00
5336720809 Supprime un point final 2024-01-03 16:33:19 +01:00
3a7e4e8db6 Fonte : datatables
supprime image map
2024-01-03 00:12:33 +01:00
51cc6b41a7 13.1.02 fontes 2024-01-03 00:03:36 +01:00
38b3a72c92 Changes 2023-12-30 21:41:23 +01:00
fb79bce39c move autoload 2023-12-24 14:30:12 +01:00
2c6b29747a Numéro de version 2023-12-20 19:14:23 +01:00
fd28afdd80 nettoyage getPermission 2023-12-20 17:37:07 +01:00
032a150b11 Blog et news uniformisation 2023-12-20 13:43:32 +01:00
c34e249cd0 blog changes 2023-12-20 13:02:48 +01:00
953ba662e8 7.4 bouton de retour 2023-12-20 13:00:50 +01:00
e79ef549d6 News col hors du test 2023-12-20 12:54:31 +01:00
5459aae163 News tiret et espaces 2023-12-20 12:47:39 +01:00
a3145fbd00 news 5.3 2023-12-19 19:20:20 +01:00
bd04f94c76 news : Un espace manquant 2023-12-19 19:19:46 +01:00
74da56e58d News 5.3 option du bouton de retour et contrôle des options de mise à jour 2023-12-19 19:09:13 +01:00
b26e7dcb7d Dans config lien vers identité du site 2023-12-19 18:32:28 +01:00
3cee46072b Espace avant le ? 2023-12-19 17:30:28 +01:00
b590f91534 Corrige les droits rfm pour les membres et plus 2023-12-14 14:43:51 +01:00
10e6822ad5 changes 2023-12-14 13:55:56 +01:00
9944a192e2 Fix doublon 2023-12-14 10:33:17 +01:00
8ad50b10dd Fix doublon 2023-12-14 10:31:33 +01:00
ee90649833 Corrige savelog 2023-12-14 09:29:04 +01:00
a4601da9e0 datatables user buttons 2023-12-09 18:01:49 +01:00
b1fcd4ecc8 paragraphe sous le bloc 2023-12-07 14:22:00 +01:00
e110eba5d8 RFM Support markdown 2023-12-07 14:02:52 +01:00
30e602adc2 13101 supprime le choix du thème à l'installation 2023-12-05 12:36:10 +01:00
1989d642fc changes 2023-12-05 11:07:08 +01:00
1a3413f702 user pagination 2023-12-03 19:54:21 +01:00
b61d78dbaa Protection des profils utlisés 2023-12-01 16:25:45 +01:00
a0dca415b5 fix profil edit permanent 2023-12-01 15:45:59 +01:00
88fd7e5d49 fix edit profil 2023-12-01 15:20:24 +01:00
0253e55de2 changes 2023-12-01 10:15:48 +01:00
bff6911bb4 Encore changes 2023-12-01 10:11:09 +01:00
4542f9f9b2 changes 2023-12-01 10:10:28 +01:00
323ff59b41 Version 13.1.00 2023-12-01 10:06:46 +01:00
590d36ede2 Étiquettes 2023-11-30 14:29:48 +01:00
a7cc6ee6d0 count valide rôles 2023-11-30 14:26:19 +01:00
ad1edcf9a2 incorpore datatables.net 2023-11-30 13:52:22 +01:00
eeb96186c1 users : Filtre et import 2023-11-30 13:30:10 +01:00
2e839715b5 small size screen header cover 2023-11-29 18:07:21 +01:00
548fd25756 Merge branch 'master' into 13009 2023-11-29 14:12:01 +01:00
ff2fbcddef changes 2023-11-29 14:10:36 +01:00
022bc9ce7b met à jour le site map à l'ouverture de l'édition 2023-11-29 13:52:39 +01:00
cbe5dc9376 back error pages 2023-11-25 22:36:31 +01:00
de564c31a0 permissions 13009 2023-11-25 21:52:23 +01:00
8927026ee4 back to home icon 2023-11-21 12:00:42 +01:00
3cda662220 template select 2023-11-21 11:56:37 +01:00
f9f55be851 Profil de l'admin manquant à l'installation 2023-11-15 14:10:02 +01:00
05da19288e Uniformisation variable de contenu avec LMS 2023-11-15 10:28:26 +01:00
d2efd48aea Petites corrections 2023-11-15 09:35:40 +01:00
3028fc13cd Changes 13.0.09 2023-11-15 09:29:16 +01:00
14bc21f3d5 slider 6.2 sécurité de profil 2023-11-15 09:23:41 +01:00
b23b1f2e06 RFM Dialog Deprecated 2023-11-14 15:49:52 +01:00
7a75eb3472 tinymce gen page title 2023-11-14 15:39:38 +01:00
2cff4db256 changes 2023-11-12 18:28:01 +01:00
666b564215 fix bug sitemap 13008 2023-11-12 18:23:52 +01:00
f46b7ea0e4 Tinymce toolbar 2023-11-11 17:55:18 +01:00
b2134f1841 site map empty site 2023-11-09 14:42:34 +01:00
7b76ab131f bug sitemap empty site 2023-11-09 14:41:33 +01:00
0b7c7678bd tinymce toolbar 2023-11-09 13:52:00 +01:00
b967a09aa5 tinymce tool bar 2023-11-09 13:49:22 +01:00
ca1ee90f52 reset error message 2023-11-09 10:56:51 +01:00
65b62c7b5a user reset error notification 2023-11-09 10:43:13 +01:00
4176043958 Forçage de mot de passe si vide + redirection après reset 2023-11-09 09:51:52 +01:00
28927ad747 Tiny Tool bar 2023-11-08 18:45:03 +01:00
92d0618907 tinymce add fullscreen 2023-11-08 18:17:50 +01:00
a9f3e1ba26 user forgot not displaying unknown user 2023-11-08 17:48:02 +01:00
e0ba8a81fe forçage de mot de passe 2023-11-08 09:50:39 +01:00
ad9a1120f4 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS 2023-11-08 09:05:07 +01:00
8619b49d19 submit 2023-11-08 09:05:01 +01:00
409e10fad1 changes 2023-11-07 21:49:39 +01:00
a7b4ea2d15 user forçage mot de passe par admin 2023-11-07 21:48:37 +01:00
cd0d35279e login reset submit size 2023-11-07 19:19:26 +01:00
f25b1a1154 Traduction des sélecteurs de tables 2023-11-07 12:02:28 +01:00
bf2ddaef9f Profil Charge les dialgues des modules 2023-11-07 11:25:41 +01:00
ca732f3ca6 Terme profil carrousel 2023-11-07 11:11:06 +01:00
9ffdfd25d0 Termes profils 2023-11-07 11:04:58 +01:00
aadcb23282 Terms and layout form profil 2023-11-07 10:59:08 +01:00
bc817b750e Layout profil gallery 2023-11-07 10:13:52 +01:00
2e76d9d305 Termes de profils gallery 2023-11-07 10:10:20 +01:00
9300ab9640 News et Blog termes de la gestion des profils avec traductions 2023-11-07 08:47:55 +01:00
3753808b98 13.0.07 changes 2023-11-06 21:26:16 +01:00
446ad40f96 TinyMCE deux barres d'outils 2023-11-06 21:24:08 +01:00
fb18127346 Pb de profil News 2023-11-03 17:59:55 +01:00
26623db2b7 Adapte le message lors de la mise à jour 2023-11-03 11:41:59 +01:00
1a27befb75 Enlève les mentions ZwiiCMS de l'installation et de la mise à jour 2023-11-03 11:26:43 +01:00
e2e261e01b changes 2023-11-03 10:46:17 +01:00
713b5ebb96 fix store unavailable 2023-11-03 10:42:00 +01:00
7ab84f63c9 fix plugin backup to filemanager
Changes
2023-11-02 20:41:27 +01:00
79efa1f1a9 fix blog enum 2023-11-02 15:09:19 +01:00
1570d71470 slider 6.1 2023-11-02 15:07:29 +01:00
da03bcfa5b Repo update name 2023-10-28 23:36:06 +02:00
eca93bc3af Date de version des fichiers de langue 2023-10-26 11:36:05 +02:00
fbfb97bf14 version core 2023-10-26 11:00:43 +02:00
67452ceb8d Merge commit 'abf920ea364f9061513ae1a73ddab32f61b4659b' 2023-10-26 10:59:44 +02:00
abf920ea36 cconfiguration 2023-10-26 10:52:09 +02:00
9390809f6b Erreur de notification configuration du site 2023-10-26 09:40:22 +02:00
a5737b7553 13007 ordre des boutons de login 2023-10-22 12:03:13 +02:00
8fca6e2485 change typo 2023-10-20 17:15:55 +02:00
1702bcef88 change 13006 2023-10-20 17:13:21 +02:00
ef4c0cdd45 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS 2023-10-20 17:11:58 +02:00
4dbd5292bc 13005 fix warning var nextPage previous Page 2023-10-20 17:10:46 +02:00
2784ad2209 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS 2023-10-20 17:10:00 +02:00
19a60d9e76 corrige le fonction signature blog 7.2 2023-10-20 17:09:51 +02:00
73223780a1 fix admin color button 2023-10-20 17:09:51 +02:00
fc8b05efca 13005 fix warning var nextPage previous Page 2023-10-20 17:07:47 +02:00
13f236ea03 Supprime les largeurs d'écran en pourcentages 2023-10-17 21:49:43 +02:00
8372ee2ad2 corrige le fonction signature blog 7.2 2023-10-14 15:04:52 +02:00
d1efca6560 fix admin color button 2023-10-14 14:35:26 +02:00
78b05a211d version 2023-10-13 14:11:02 +02:00
fff6c3b086 filter admin 2023-10-12 19:25:20 +02:00
7878f972e5 filtre des profils admin 2023-10-12 19:03:40 +02:00
74f33031a8 changes captcha 2023-10-12 18:38:13 +02:00
eeb2f78770 move signature() into core 2023-10-12 17:49:12 +02:00
f24bd9a4b9 update admin theme width as site 2023-10-11 21:42:20 +02:00
251d98ea03 changes.md 2023-10-11 21:13:49 +02:00
c0963f90bd Fix virgule en trop 2023-10-11 21:11:58 +02:00
de41c5ac01 default send adress 2023-10-11 21:10:26 +02:00
6794db3719 default form localhost 2023-10-11 21:07:34 +02:00
5bba67c169 default theme width 960px 2023-10-11 21:02:27 +02:00
95ac9e7d28 Fix TinyMCE header h4 2023-10-10 22:05:29 +02:00
4d0a09cad0 admin width size 2023-10-09 20:32:12 +02:00
bad28659df filtre des membres 2023-10-09 19:38:35 +02:00
c21986a97e Install tel qu'avant 2023-10-06 17:33:54 +02:00
5ed49819ca changes 2023-10-06 13:36:27 +02:00
5660620685 Fix version readme 2023-10-06 13:30:58 +02:00
6c39349989 fix user edit comment 2023-10-06 09:52:38 +02:00
eea5e43149 fix profil empty path 2023-10-06 09:15:50 +02:00
a96bee2873 fix parofil add empty path 2023-10-06 09:15:21 +02:00
961fcb2ecd Fix sécurité profil filmaanager path empty 2023-10-06 09:09:43 +02:00
34aa4f4c25 fix user edit 2023-10-05 18:58:09 +02:00
17d1e7e4b4 fix user import template 2023-10-05 11:29:20 +02:00
a74f92a0a9 Position du bouton Submit dans la fenêtre de restauration 2023-10-05 10:53:35 +02:00
d160b5df52 Fix DateUTF8 Locale 2023-10-03 17:39:02 +02:00
26d55460fb changes 2023-09-30 13:41:42 +02:00
05106a0d18 branche adresse 2023-09-30 13:40:14 +02:00
0724114e96 fix checknewversion 2023-09-22 18:07:25 +02:00
4b7826b078 Fix checkNewVersion 2023-09-22 18:06:58 +02:00
497a51ea18 13004 supp gestion erreur étape 4 2023-09-22 15:50:06 +02:00
d682636992 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS 2023-09-22 15:00:44 +02:00
2e556c175a changes 2023-09-22 15:00:17 +02:00
90d8f0b129 - Module blog Version 7.1 : permission lors de la validation d'un formulaire 2023-09-22 14:53:42 +02:00
b9e0e0db39 Module form 4.1 : corrige un email non envoyé après validation d'un formulaire. 2023-09-22 14:45:26 +02:00
f9a1982b16 couleur des liens 2023-09-20 18:36:29 +02:00
d5b52e78fc Supprimer les dossiers inutiles des modules 2023-09-20 18:25:37 +02:00
0cb4a00ca2 changes 2023-09-20 18:10:14 +02:00
036469232a Bug forgot password + changes 2023-09-20 18:08:38 +02:00
d7cdad6b6e déplacement de bloc 2023-09-14 21:18:23 +02:00
003fedcef5 Bouton édition des langues pour les admin 2023-09-14 21:14:43 +02:00
1d083f5f19 Déplacement du bouton langues à droite du sélecteur toujours affiché 2023-09-13 18:25:05 +02:00
2758ec5f1b Supprimer la gestion des données des modules 2023-09-13 17:48:59 +02:00
edc7a0b323 Enumération des modules 2023-09-13 17:45:27 +02:00
952bb60404 Libellé de l'erreur de module PHP 2023-09-13 17:30:25 +02:00
baffca39e6 Init 13003 2023-09-12 22:24:12 +02:00
a7a45b3c1c Nettoyage des appels direct à csrf()
Bug avec l'import de données de modules à corriger
2023-09-12 22:22:36 +02:00
d914c6f613 13002 bug bdd fonte 2023-09-08 20:51:35 +02:00
31910f6e94 13002 2023-09-08 20:49:11 +02:00
e2bd95780b typo 2023-09-05 09:08:24 +02:00
150ea0c02f Module 2.1 bug d'édition 2023-09-04 18:07:31 +02:00
1a07031e2a core version 2023-09-04 17:58:04 +02:00
da3e98e474 Icone devant les pages enfants 2023-09-03 19:01:42 +02:00
8363fdead5 chnages 2023-09-03 14:25:56 +02:00
af3345bdd2 change pour nav 2023-09-02 21:19:07 +02:00
7654446466 Supprimer l'aperçu du thème du site 2023-09-02 21:17:52 +02:00
21113f8ffd traductions nav button 2023-08-30 22:34:39 +02:00
036e18ba53 traductions nav 2023-08-30 22:29:17 +02:00
1d8836f230 Intégration module nav dans core 2023-08-30 20:02:23 +02:00
4d0af131cb Tinymce liens 2023-08-30 11:07:19 +02:00
16c0c466f6 tinymce relative url convert to true 2023-08-30 10:31:43 +02:00
047f107f66 Après édition de page retour à la page et non à l'accueil 2023-08-30 10:28:20 +02:00
5768638a2e tinymce colors 2023-08-30 10:09:44 +02:00
55c3badb40 enum navigation 2023-08-29 20:11:22 +02:00
63ef8f8f34 Déplace navButton 2023-08-29 19:52:11 +02:00
bf83bd85d2 Nav classe pour le positionnement 2023-08-29 19:03:45 +02:00
3da45bdacd Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-TEAM/ZwiiCMS 2023-08-29 10:33:13 +02:00
fa3cc1bfa3 Simplification TinyMCE 2023-08-29 10:32:47 +02:00
1c9b42fc42 module navigation + icones 2023-08-28 11:04:53 +02:00
c4a4aeb1f3 slide secured 2023-08-28 11:02:38 +02:00
a2e1f16a86 supprimer le module download de la distribution 2023-08-28 08:56:45 +02:00
8651581fb5 remove from core 2023-08-27 23:14:25 +02:00
ba171115cd update language okay 2023-08-27 23:13:48 +02:00
0f1b4b3a85 test core update lang 2023-08-27 23:02:31 +02:00
7e2672bd46 update language in core 2023-08-27 23:00:00 +02:00
75ee6d3691 test update language in config 2023-08-27 22:56:07 +02:00
49e0379cfd test update language on update 2023-08-27 22:51:44 +02:00
7684f8eb89 supprimer le test de mise à jour de langues 2023-08-27 22:43:20 +02:00
f87e0677aa Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-TEAM/ZwiiCMS 2023-08-27 18:16:32 +02:00
aee11cb237 Renomme le fichier et le dossier fonts dans data 2023-08-27 18:14:42 +02:00
9029a94be1 Supprime le message d'erreur sur la réécriture à l'étape 4 2023-08-27 18:14:15 +02:00
87c5ba2024 Bug affectation checkwrite 2023-08-27 17:46:20 +02:00
a5018c438b 13.0.00 2023-08-27 17:11:58 +02:00
8560e967c2 build 19 2023-08-20 16:03:49 +02:00
0f67af5f11 Mise à jour de traductions 2023-08-20 15:57:01 +02:00
d226331f19 Avertissement sur suppression de profil 2023-08-20 15:23:35 +02:00
fc5630f3aa Meta image 2023-08-18 08:53:17 +02:00
ea7c39bf14 Merge branch '13000' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS into 13000 2023-08-14 17:51:57 +02:00
b85c5e392b build 18 2023-08-14 17:48:57 +02:00
5ff93c45d6 Encore container light + update étape 4 2023-08-14 17:48:21 +02:00
0d09fee84c Update étape 4 2023-08-14 17:28:40 +02:00
2e3769971b Merge branch '13000' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS into 13000 2023-08-14 14:09:15 +02:00
e4d1ab4440 Input light container 2023-08-14 14:09:02 +02:00
b5c92a6a1d Build 17 2023-08-14 12:12:36 +02:00
9cbe14fd8f Traduction Poids 2023-08-14 09:32:09 +02:00
955935f0ce Indications coloreés sur la conformité de l'image open graph 2023-08-14 00:49:23 +02:00
eb92745950 Revert "Share folder"
This reverts commit 7f92710ec2.
2023-08-13 08:02:43 +02:00
f9369cee0e Revert "Mise à jour site/file"
This reverts commit 02e66468f2.
2023-08-13 08:02:38 +02:00
ccafb3e8e4 Merge branch '13000' of https://forge.chapril.org/ZwiiCMS-TEAM/ZwiiCMS into 13000 2023-08-12 21:49:19 +02:00
7f92710ec2 Share folder 2023-08-12 21:49:08 +02:00
02e66468f2 Mise à jour site/file 2023-08-12 21:43:02 +02:00
a667b0370d Remplace l'api opengraph par un sélecteur 2023-08-12 21:34:38 +02:00
ce1c3a852a build 16 2023-08-11 22:31:49 +02:00
19de4af4e7 Merge branch '13000' of https://forge.chapril.org/ZwiiCMS-TEAM/ZwiiCMS into 13000 2023-08-11 22:29:49 +02:00
a21517ed2e Libellé permissions 2023-08-11 22:29:47 +02:00
02ceb0e0bd Animations des options de commentaires et de catégories 2023-08-11 22:28:31 +02:00
ca341f6f6c Profil position des champs edit et add 2023-08-09 20:19:06 +02:00
b2a73203ed Introduit le tableau de bord sans le publier 2023-08-08 20:55:42 +02:00
0fd9ff177e Suppression de la variable accessExclude 2023-08-08 19:44:17 +02:00
cc90fc2273 Traduction des données des profils, nom et commentaire 2023-08-08 18:15:16 +02:00
07aa29e4bc Libellés des profils par défaut et traductions 2023-08-08 18:04:39 +02:00
64ae2817a0 aide sélecteur de profil 2023-08-08 17:46:05 +02:00
724ade6971 Edition impossible du profil de rang 1 2023-08-08 17:44:44 +02:00
e4717f0e6d deshboard 2023-08-07 20:28:38 +02:00
da1d28da2a tri du tableau des modules 2023-08-07 20:28:27 +02:00
f2948915b8 rien de spécial 2023-08-07 20:28:09 +02:00
7b6922cfe0 Supprimer multilingue 2023-08-07 20:08:48 +02:00
c76b4c3f30 build 14 2023-08-06 22:37:17 +02:00
9fda66c29a bug copie de langues 2023-08-06 22:31:44 +02:00
781d9a5e24 bug de branche 2023-08-06 22:14:25 +02:00
6fdc6020a0 correct timestamp 2023-08-06 22:05:22 +02:00
ad23734411 Restaure les fichiers de langues 2023-08-06 21:58:07 +02:00
e48f3e2334 Modules nettoyés 2023-08-06 21:55:13 +02:00
c6019faa0e build 13 2023-08-06 11:22:41 +02:00
20cab1770b supprimer un écho 2023-08-06 11:21:08 +02:00
58db7a75fa Language : branche v13 2023-08-06 11:17:36 +02:00
b40ab119c4 NOuvelles traductions 2023-08-05 18:02:18 +02:00
9b474de209 download 2023-08-05 17:18:32 +02:00
0ce3c1f131 Traduction de profil 2023-08-05 17:16:18 +02:00
97ec7d756b couleur de bannière light forcée 2023-08-05 16:25:27 +02:00
0a13e35413 Balise sémantique main 2023-08-05 16:20:19 +02:00
112579c9d2 .12 ordre des profils 2023-08-05 14:50:20 +02:00
d2e3dfe700 Ordre des profils 2023-08-05 14:50:05 +02:00
b13a5a5043 Constante MAX_PROFILS 2023-08-02 22:25:07 +02:00
be53996c7f build 13 2023-08-01 20:56:20 +02:00
3bea31ea12 Vérifie si les dossiers existent avant d'appeler deleteDir() 2023-08-01 20:51:28 +02:00
3e1aed8641 Support images avif si la fonction est disponible 2023-08-01 20:37:23 +02:00
27bb3de75c Console.log 2023-07-31 20:24:04 +02:00
040785408c v13 2023-07-31 20:21:36 +02:00
ef25c9c153 branche de test 2023-07-31 20:12:10 +02:00
6823ce3dc8 Réorganise étape 4 2023-07-31 20:06:15 +02:00
78f7a1c063 update mauvais etape d'erreur (retour erreur ajax) 2023-07-31 14:59:00 +02:00
fe3f767697 Attribut alt pour les RS du pied de page build 10 2023-07-31 14:45:22 +02:00
7398ceb5ef 0.9 Login, couleur de la bannière d'erreur 2023-07-31 14:13:26 +02:00
ebbf7d2e41 Exclure i18n htaccess du pre check 2023-07-31 11:17:00 +02:00
35cfb1a78f bug de mise à jour depuis 11 2023-07-29 17:18:33 +02:00
e5aa333b13 libellé 2023-07-29 14:52:14 +02:00
1dfbb9361f autre test avec le curseur en wait mais dans jquery 2023-07-28 16:14:49 +02:00
06fd8a15d8 gestion curseur en test 2023-07-28 16:07:33 +02:00
efe74087f7 build .8 2023-07-28 15:01:48 +02:00
9dd7efeeb6 build .08 2023-07-28 15:01:36 +02:00
22687433fa supprimer l'echo 2023-07-28 15:00:38 +02:00
c1396000d0 Décommente l'appel de la mise à jour 2023-07-28 14:44:06 +02:00
f67da9bd13 Installe le profil dans toutes les langues installées 2023-07-28 14:43:48 +02:00
6c55881789 Mise à jour des profils dans les pages 2023-07-28 11:14:13 +02:00
da03e95be9 Routage tient compte du profil 2023-07-28 11:13:51 +02:00
fa4fb40872 Les pages gèrent les profils 2023-07-28 11:13:31 +02:00
03504a6402 N'utilise pas de constante 2023-07-28 11:12:58 +02:00
0ca6c2913a déplacer le chargement de la mise à jour et ajoute le routage avec le profil 2023-07-28 10:58:42 +02:00
840b962d55 nettoyage de libellés 2023-07-28 10:55:33 +02:00
3bc31b9d73 user edit permanent sauf si position 1 2023-07-27 09:34:55 +02:00
7168174c39 ajout et édition de profil, propriété permanent 2023-07-27 08:01:10 +02:00
2944363e29 version 2023-07-26 17:19:03 +02:00
0e2295a8aa Les profils permanents ne sont pas effacables 2023-07-26 17:17:39 +02:00
ead8d63525 default avec propriété de profil delete 2023-07-26 16:58:32 +02:00
50bce3d8c5 div manquant 2023-07-26 14:52:15 +02:00
5eb277f501 build 6 2023-07-25 19:37:00 +02:00
cde775bded defaultData 2023-07-25 19:34:55 +02:00
2d9e6d211c remove extract 2023-07-25 19:32:46 +02:00
d133346e84 i18n slider 2023-07-25 19:32:11 +02:00
f1d5871957 slider 2023-07-25 19:21:29 +02:00
c70d1e083a Suppression de libellés 2023-07-25 19:14:59 +02:00
ff42c6a433 nouvelles chaines 2023-07-25 19:05:14 +02:00
4b7d80aced échec 2023-07-25 16:13:10 +02:00
e8b76b774b Merge branch '13000' of https://forge.chapril.org/ZwiiCMS-TEAM/ZwiiCMS into 13000 2023-07-25 16:07:15 +02:00
5632f91d34 erreur de texte 2023-07-25 16:05:36 +02:00
a09ae7bfce erreur de texte 2023-07-25 16:05:03 +02:00
6c75eba8f2 doublons 2023-07-25 11:20:38 +02:00
c8d83033a7 éditeur 2023-07-25 11:12:35 +02:00
88333ef673 Form 4 pb de date 2023-07-25 11:07:55 +02:00
53c62a2301 13.0.00.5 2023-07-25 10:15:30 +02:00
047013d031 Libellé de module 2023-07-25 10:08:14 +02:00
733ef26509 Aide dans tinymce 2023-07-25 10:05:02 +02:00
813d78d9b4 rectificatifs de libellés blog et download 2023-07-25 09:45:02 +02:00
1c20abd750 une ligne vide ajoutée 2023-07-24 21:26:24 +02:00
016a809022 module Carrousel 2023-07-24 21:18:56 +02:00
3e53329646 build 4 2023-07-24 18:36:48 +02:00
c0e3a0c96e Supprime un test 2023-07-24 18:32:41 +02:00
7d26d202e2 Accent 2023-07-24 18:31:43 +02:00
9b59393ad2 download bug + la validation de l'édition d'un profil revient à la page de saisie 2023-07-24 18:30:10 +02:00
6ac06f669b Permission : liste de modules non fixes 2023-07-24 18:22:24 +02:00
2e81467326 download, des bugs 2023-07-24 18:21:44 +02:00
ccec25d46b typo 2023-07-24 18:01:11 +02:00
1387bfae25 Download mise en forme 2023-07-24 18:00:25 +02:00
f1ab4f3c80 download changes 2023-07-24 17:35:02 +02:00
8cac9eae8b download
- ajout du module pour les tests mise aux - normes php 8.2 et
- ajout des contrôles de profil. Setup devient option
2023-07-24 17:34:46 +02:00
ecf0df8d5d gallery caractère en trop 2023-07-24 17:31:59 +02:00
f64fdce167 changes 2023-07-24 13:23:45 +02:00
68baee6d33 version 2023-07-24 13:14:13 +02:00
ee03f49920 La langue est initialisée à la création 2023-07-24 13:13:28 +02:00
46a3d36986 message d'erreur avec l'étape 2023-07-24 11:32:58 +02:00
ca3d331719 update : ordre des messages 2023-07-24 11:25:26 +02:00
a485913372 config position des boutons 2023-07-23 22:21:33 +02:00
de58ddcd07 bug des langues non installées 2023-07-23 22:17:04 +02:00
a6b9e55a34 installation bug avec une langue qui n'existe pas dans la distribution 2023-07-23 21:57:19 +02:00
09a8d2c626 language to translate 2023-07-23 21:41:24 +02:00
accc950511 13.0.00.2 2023-07-23 18:55:17 +02:00
2d9d8faa3d Génére des erreurs 500 en cas d'erreur 2023-07-23 18:51:35 +02:00
c0a02874f8 génére une erreur 500 à l'étape 2 2023-07-23 18:41:15 +02:00
82786c6937 Détailler l'étape 2 + effacer fichier tar et tar.gz 2023-07-23 18:33:10 +02:00
a5af8068ef amélioration js 2023-07-23 18:23:33 +02:00
c03ccd2cf7 étape 2 2023-07-22 22:46:38 +02:00
ceae2be327 bug 2023-07-22 22:44:49 +02:00
b86bf1d7c0 amélioration étape 2 2023-07-22 22:43:53 +02:00
170c8a6be3 test install 2023-07-22 22:38:55 +02:00
2c6ab43006 succes false dans install 2023-07-22 22:25:36 +02:00
1a6d98d8a1 update corrigé et affichant des messages corrects 2023-07-22 22:22:40 +02:00
359193f1a6 controle la longueur du message dans le traotement de l'erreur pendant une mis eà jour 2023-07-22 21:15:47 +02:00
aadd51f4d6 changes 2023-07-22 21:13:55 +02:00
d4a3d67693 désactive l'appel de l'erreur dans success 2023-07-22 19:21:07 +02:00
b84b3b4dde console.log errors et filtrage de la taille de la longueur du message 2023-07-22 19:18:03 +02:00
6c2534df81 exclure les icones 2023-07-22 19:02:10 +02:00
b4f9ac45a7 test attributezwiico lors de l'installation 2023-07-22 18:45:23 +02:00
29d696bdb4 mis en console des erreurs 2023-07-22 18:29:44 +02:00
2127d5ca16 Désactive les couleurs définies dans le thème pour la fenêtre light 2023-07-22 18:11:45 +02:00
f34acde600 couleur d'arrière plan pour la fenêtre admin 2023-07-22 17:38:13 +02:00
eb54510036 unset light container backgrounbd color 2023-07-22 17:29:00 +02:00
65003dcc98 messages d'erreur traduits dans l'installateur 2023-07-22 17:21:17 +02:00
479c13a994 $message vide 2023-07-22 16:57:34 +02:00
48a88e212c meage erroné 2023-07-22 10:04:07 +02:00
a58a65b5cf consoloe.log dans le js de l'installation et changes.md 2023-07-22 10:02:40 +02:00
e18e149b9b simplification retour de message et de succes étape 4 update 2023-07-22 09:56:56 +02:00
c28b0590c2 Update étape 3 n'envoie plus de message texte 2023-07-22 09:54:26 +02:00
88ead8b16b argument null 2023-07-22 09:45:23 +02:00
8b6ef5f03f Permissions intégrées aux codes des modules 2023-07-21 21:53:46 +02:00
efa82f4a9c Les permissions des modules sont intégrées au code du module. 2023-07-21 21:48:41 +02:00
81448227f9 changes 2023-07-19 19:39:23 +02:00
c6f3a2e83d Groupe MODERATOR, compatibilité avec les anciens modules 2023-07-19 18:57:58 +02:00
d7e4e424a2 langues 2023-07-19 18:09:40 +02:00
fec70444ee deleteDir 2023-07-19 18:07:12 +02:00
529f86c873 renommer module/translate en module/language 2023-07-19 18:03:00 +02:00
724c9fe521 bug d'e téléchargement d'une langue 2023-07-19 17:56:19 +02:00
6cf511e6b7 désactive l'auto récupération des dialogues 2023-07-19 17:56:03 +02:00
79cc6137ad authorizations 2023-07-19 17:17:16 +02:00
b7655ec501 Libellés et traductions du profil 2023-07-19 10:30:41 +02:00
587bb0fab2 variable de session inexistante 2023-07-19 09:32:36 +02:00
86550e62ff libellé 2023-07-19 09:28:26 +02:00
1d165e8b71 ZwiiCMS Installation *+ fichiers de langue 2023-07-18 22:35:41 +02:00
e242d7ecab Correction paramètres null dans getHierarchy et effacement des données de session et de cookies relatif aux langues lors de la réinstallation 2023-07-18 22:26:07 +02:00
d13b01791b Encore initData et une amélioration du contenu des pages par défault en anglais et en espagnol 2023-07-18 22:09:28 +02:00
7e7d1f1f43 Amélioration de defaultdata 2023-07-18 18:50:19 +02:00
ef7cd70c5f nouveau initData 2023-07-18 16:04:45 +02:00
106387fab8 Initialisation WIP 2023-07-18 11:19:53 +02:00
8bf2d89906 warning à l'installation 2023-07-18 11:14:22 +02:00
54de5c4258 Améliore l'installation en évitant les erreurs de chargement 2023-07-18 00:16:39 +02:00
f4c386daf2 virgule dans sendmail 2023-07-16 18:47:50 +02:00
89f21660c3 bug install 2023-07-16 18:14:19 +02:00
5e2687bd44 Affichage correct des commentaires liés aux profils 2023-07-07 19:03:41 +02:00
690f8f1739 Rédacteur 2023-07-06 17:31:16 +02:00
13af9832f7 Merge branch '13000' of https://forge.chapril.org/ZwiiCMS-TEAM/ZwiiCMS into 13000 2023-07-06 17:05:08 +02:00
5eb78c0ed9 accent manquant 2023-07-06 17:04:54 +02:00
92c8c0a653 Groupe MODERATOR devient EDITOR 2023-07-05 18:04:42 +02:00
a1096af3de Mise à jour des membres le profil vaut 0 pour les types membres et moderateurs 2023-07-05 18:00:20 +02:00
0fe4c582a1 Le profil des memebrs sans profil (bannis, visiteurs et admin, vaut 0) 2023-07-05 17:58:01 +02:00
f915c591fa mise à jour des membres depuis versions précédentes 2023-07-05 17:57:18 +02:00
9f6202e639 Check Modules 2023-07-05 17:34:55 +02:00
433342c2a8 numéros de version 2023-07-04 19:31:34 +02:00
b72f16cb52 Bug sauvegarde plugins 2023-07-04 19:27:49 +02:00
befbd1438d update enums 2023-07-04 19:27:22 +02:00
18f00cbe3c Durcissselment des contrôles 2023-07-04 19:03:27 +02:00
38ed0dc1aa Fix bugs pages 2023-07-03 19:49:39 +02:00
2cabb31734 Ajoute le nom du profil dans la liste des utilisateurs 2023-07-01 19:18:40 +02:00
3af3db940c Fix show filemanager icon 2023-07-01 19:04:39 +02:00
dabc0a4c2e Permissions sur le bouton mon compte 2023-06-30 09:26:41 +02:00
ac0a51a8b5 Erreur de booléen 2023-06-30 09:15:15 +02:00
ebf143002c Erreur de booléen 2023-06-30 09:09:39 +02:00
08e8c3fa2c Force obtention des permissions à chaque isPost 2023-06-29 17:01:27 +02:00
101da263fd Implémentation des sécurités à tester 2023-06-29 10:30:12 +02:00
b7d1f9e1f1 Check permission on delete 2023-06-29 09:43:31 +02:00
a22dc8b5ce Libellé du compte user 2023-06-29 09:34:33 +02:00
9fad0cdcc8 restaure le fichier router 2023-06-28 22:41:57 +02:00
1271185c5d Profil droit sur l'édition du compte 2023-06-28 22:34:37 +02:00
5fdcfdd7bd NOuveau modèle de profil qui commence à 1 et non 0 2023-06-28 18:12:37 +02:00
22dea7f64f Ajoute l'effacement de profil 2023-06-28 17:52:13 +02:00
23c015f696 Module delete supprimer le checkcsrf et change l'appel de la fonction profil 2023-06-28 17:51:48 +02:00
0ac0e9398b blog 6.9 2023-06-28 10:25:48 +02:00
5c87a74d7b Message Action interdite 2023-06-20 20:35:26 +02:00
8c8fd91c7e Formatage 2023-06-20 20:25:19 +02:00
54b858056f csrf translate 2023-06-20 20:21:45 +02:00
f262b661e9 Csrf Theme reset 2023-06-20 20:15:55 +02:00
adf0ac8f80 Page duplicate 2023-06-20 20:04:30 +02:00
3b8a2d5b03 Nettoyage session dans GET 2023-06-20 19:58:29 +02:00
f19afc81ed Nettoyage des sessions dans GET 2023-06-20 19:57:27 +02:00
982cf3bb9f supprimer echo 2023-06-20 19:44:46 +02:00
7cec74d5e3 Version 13000 2023-06-20 19:33:13 +02:00
30227c9362 checkcsrf 2023-06-20 17:58:58 +02:00
886ed303be La validation des options du blog ferme l'écran 2023-06-20 17:42:20 +02:00
3f43830154 Encore changes 2023-06-19 20:05:45 +02:00
229d521502 Exposition du code de session 2023-06-19 19:46:00 +02:00
0cd487f211 Libellés d'options 2023-06-18 17:35:54 +02:00
6214f6a363 Interdiction des suppressions depuis le module en sus du routage 2023-06-18 17:33:26 +02:00
95b7d1f74e Libellés et corrections d'erreurs dont accès implicite à la configuration sauf news et redirection 2023-06-18 16:57:11 +02:00
0b06e12ef9 Check profil edit save and add 2023-06-18 14:52:14 +02:00
fb2624bf7a déplace update en fin de constructeur de core 2023-06-13 20:59:10 +02:00
a38097391d remaniement de script d'installation 2023-06-13 20:58:39 +02:00
7b3e4cc67d textes personnalisés pour l'accueil 2023-06-13 20:58:17 +02:00
d0854b9302 Bug installation module non corrigé 2023-06-12 21:46:47 +02:00
240a3afd9e nettoyage 2023-06-12 21:44:24 +02:00
8aeddf77c1 Formulaire d'installation 2023-06-12 21:13:33 +02:00
1306097cab Bug initialisation des pages 2023-06-12 21:08:33 +02:00
a5b8a44c52 Encore les classes 2023-06-12 18:38:41 +02:00
6e4b2bab77 Simplification appel des classes 2023-06-12 18:15:46 +02:00
3b77620511 Blog 6.8 2023-06-12 11:45:03 +02:00
5b82100c30 profils des deux derniers modules 2023-06-12 11:13:57 +02:00
7d950f7f2c Profil module form 2023-06-10 17:21:16 +02:00
21fee2dbb1 Supprime des fonctions inutiles 2023-06-10 17:14:26 +02:00
b7fbf1f96f Animation pour l'ajout de profil 2023-06-10 17:06:08 +02:00
c2d531872d Profil gallery 2023-06-10 16:58:05 +02:00
48de07f997 Etat des checkbox liés à l'édition d'une page et aux modules dans l'édition et l'ajout 2023-06-05 18:31:16 +02:00
cca7530631 news profil 2023-06-01 20:08:11 +02:00
7aa6625e08 blog edit et add var 2023-05-31 20:44:47 +02:00
02a1870642 blog profil 2023-05-31 19:30:39 +02:00
ac2b29628d Blog 6.7 2023-05-30 21:06:26 +02:00
1dba8f3eb8 $suffix 2023-05-29 18:49:50 +02:00
de84e3471b Edit and Add to test profil 2023-05-29 18:43:30 +02:00
7c7c36a5e6 user comment okay 2023-05-29 09:18:32 +02:00
44581b4682 add afficher le commentaire de profil dans l'ajout d'un user 2023-05-23 20:47:27 +02:00
2fe0a8e7b1 commentaire des profils en cours 2023-05-21 18:04:32 +02:00
81d8eb54d0 pas de gestion des page spour les membres 2023-05-21 17:56:18 +02:00
663dfd12ec Filtrage page depuis moderateur
Groupe fixe en édition
2023-05-21 17:38:38 +02:00
9c44759f96 Editer et ajouter page permission 2023-05-14 22:59:24 +02:00
327bf0ddb6 Filtrage par profil 2023-05-14 22:38:18 +02:00
55f8e592c8 permission routage en test 2023-05-13 23:36:02 +02:00
56d7dbedfc Permissions des pages dans la barre 2023-05-13 23:19:55 +02:00
9b07bcf38e default de profil 2023-05-13 23:19:30 +02:00
94af270ca6 traitement de l'action en test 2023-05-13 23:16:09 +02:00
91b93bd220 actions inutiles 2023-05-13 23:15:51 +02:00
4af57f42b7 12400 getPermission 2023-05-11 19:31:20 +02:00
b4f5546a5f Structure des champs 2023-05-11 19:13:36 +02:00
cb909e41de libellés et liste de dossiers 2023-05-11 19:07:34 +02:00
faac5a6c43 erreru de clé chmod 2023-05-11 19:07:16 +02:00
06d5b30544 Liste des chemins d'accès 2023-05-11 18:46:46 +02:00
c57b0e26e5 jquery pour désactiver les sélecteurs de filemanager 2023-05-11 18:33:25 +02:00
ab46dd9ab2 Add profil 2023-05-10 16:58:56 +02:00
f2636c87d8 Profil RFM 2023-05-10 16:50:02 +02:00
4901cb9052 12311 2023-05-10 09:43:20 +02:00
a46848922f Merge branch 'master' into 12400 2023-05-09 23:44:51 +02:00
50a8b3a712 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-TEAM/ZwiiCMS 2023-05-09 20:52:16 +02:00
650fd20e0c webshell 2023-05-09 20:23:04 +02:00
23709679f2 webshell 2023-05-09 20:19:03 +02:00
d7069c8da8 webshell 2023-05-09 20:18:26 +02:00
19f1685d8a Config RFM à tester 2023-05-09 16:38:26 +02:00
71fd25f02c configuration RFM à tester 2023-05-09 16:34:45 +02:00
fde15d6946 Merge branch '12311' into 12400 2023-05-09 15:19:10 +02:00
857fa447a1 12311 Création d'un langue par un visiteur 2023-05-09 15:03:56 +02:00
4b34c1664d Merge branch 'master' into 12400 2023-05-09 14:56:01 +02:00
35a74f02b6 changes 2023-05-09 14:29:42 +02:00
c71d68aae6 changes 2023-05-09 14:17:56 +02:00
02fb491f9b Désactive TUI Image éditeur 2023-05-09 09:13:00 +02:00
9baf47f86c Restore ajax_call 2023-05-09 09:04:17 +02:00
2048562006 Edition user sélection langue par défaut 2023-05-09 09:01:26 +02:00
b408c9d192 config RFM WIP 2023-05-09 08:58:57 +02:00
2ce3efb4fb add and edit profil WIP 2023-05-06 19:52:33 +02:00
da2c0b6440 add Okay 2023-05-03 22:59:15 +02:00
2a87b98d9a Forçage sauvegarde JSON object 2023-05-03 19:47:37 +02:00
aa2d5f0f06 Merge branch '12310' into 12400 2023-05-03 00:34:01 +02:00
8d5e8ccbd3 Mise à jour RFM
Dialog.php
Vulnérabilité dans ajax_call.php
2023-05-03 00:32:41 +02:00
21a903b1e5 Ajout du profil d'un membre 2023-05-02 23:37:51 +02:00
ef8c10fae7 Merge branch 'master' into 12400 2023-04-28 22:09:10 +02:00
2842005297 12309 changes bug recherche 2023-04-28 22:07:41 +02:00
3bcff4b86f bug avec le module de recherche 2023-04-28 22:05:21 +02:00
6c877ed334 defaultdata update version 2023-04-28 19:05:14 +02:00
b7f7c3d1db changes 2023-04-28 18:55:27 +02:00
d98d986d4f 12.3.09 2023-04-27 09:31:19 +02:00
85789361f2 Merge branch '12309' into 12400 2023-04-26 22:57:30 +02:00
05c9e7aa9a changes 2023-04-26 22:55:58 +02:00
b54e5815ee 12309 Motorisé par est traduit 2023-04-26 22:54:33 +02:00
367e43d773 Merge branch '12309' into 12400 2023-04-26 22:11:18 +02:00
329c7a3ad4 Langues fichier 2023-04-26 21:51:35 +02:00
dde705805a 12309 test 01 2023-04-26 21:40:09 +02:00
9977fb8c3e destruction de session 2023-04-25 11:07:38 +02:00
465a9c5e03 un seul locale 2023-04-24 22:34:24 +02:00
4decb9b5d7 Merge branch '12309' into 12400 2023-04-24 22:30:41 +02:00
f235a65fe7 Nettoyage des anciennes installations 2023-04-24 22:28:53 +02:00
c4b2ebeea7 Merge branch '12309' into 12400 2023-04-24 21:57:23 +02:00
760907a67a Détruit la session au logout 2023-04-24 21:56:45 +02:00
c775d71642 Merge branch '12309' into 12400 2023-04-24 21:43:08 +02:00
bab9b3d9bc Défaut installation site fr 2023-04-24 21:40:48 +02:00
1a0f6b1721 Merge branch '12309' into 12400 2023-04-24 21:26:47 +02:00
4d0a1fd80b changes 2023-04-24 21:24:58 +02:00
c332460074 12.3.09 2023-04-24 21:24:41 +02:00
d47290df01 Changes 2023-04-24 20:47:32 +02:00
24550749b7 12309 Changement de la langue de site par défaut 2023-04-24 20:46:14 +02:00
63bb78a0fd Traduction 2023-04-24 19:56:15 +02:00
7111fdb532 Corrige le bug des modules orphelins non filtrés 2023-04-24 19:45:57 +02:00
cfac4034a3 12400 logs 2023-04-23 18:51:37 +02:00
fb43aed601 Merge branch 'master' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS 2023-04-23 18:00:13 +02:00
ce0faaf556 typo 2023-04-23 18:00:02 +02:00
7dfae68bb9 Merge branch '12308' into 12400 2023-04-23 07:50:14 +02:00
5fdb0c8ff5 Régénere la session à l'installation et au login 2023-04-23 07:39:40 +02:00
87024d284a Merge branch '12308' into 12400 2023-04-22 18:51:32 +02:00
28e8af3f1f Mise à jour : création du fichier .default dans la langue de site 2023-04-22 18:49:02 +02:00
e6ae059bfb 12308 2023-04-22 18:25:35 +02:00
35bba82fb0 update default languages versions 2023-04-22 15:53:30 +02:00
6a4fc3154b Merge branch '12308' into 12400 2023-04-22 15:51:56 +02:00
d39d8e7979 12308 langues du 22/4 2023-04-22 15:49:35 +02:00
b05ced6f0a Suppirme des tests inutiles 2023-04-22 15:38:39 +02:00
18058ed8ce Merge branch '12308' into 12400 2023-04-22 09:55:46 +02:00
eacb278566 12308 langue de site par défaut dans le menu translate 2023-04-22 09:53:04 +02:00
735057f4dd changes, ajout de default dans le lisez-moi et la structure des fichiers 2023-04-21 17:54:24 +02:00
5685fde159 Merge branch '12308' into 12400 2023-04-21 17:26:01 +02:00
08fd9894c6 12308 bug de la langue non sélectionnée 2023-04-21 17:25:24 +02:00
d97fe3316b 12308 bug de la langue non sélectionnée 2023-04-21 17:25:08 +02:00
b9998df747 Merge branch '12308' into 12400 2023-04-19 19:52:56 +02:00
1544b07132 12308 fix aucun module et langue non installée 2023-04-19 19:47:01 +02:00
388395f5e4 merge 12308 2023-04-18 20:42:51 +02:00
0895e51a0a Merge branch '12308' into 12400 2023-04-18 20:42:37 +02:00
fde15d4ae2 12308 pb de restauration de la langue fr par défaut 2023-04-18 20:37:15 +02:00
41070f809c Motorisé par 2023-04-17 20:44:36 +02:00
73556a40bb merge 12308 completed 2023-04-15 19:26:18 +02:00
820cc6c0b0 merge 2023-04-15 19:20:27 +02:00
d2be706829 Merge branch '12308' into 12400 2023-04-15 19:20:13 +02:00
d417ee0ce5 Initilaisation sessions de langue 2023-04-15 19:09:36 +02:00
a90f616423 12308 optimisation récupération données user 2023-04-15 19:03:28 +02:00
fc6729acfa changes 2023-04-15 13:41:21 +02:00
cac0c14ecd Merge branch '12308' into 12400 2023-04-15 13:34:01 +02:00
2b804a01dc Footer 2023-04-15 13:33:23 +02:00
48b5e2e63f Fenêtre de connexion de la langue du contenu 2023-04-15 13:06:20 +02:00
8a2faec55a body 2023-04-15 08:06:26 +02:00
02e8b77498 Theme et menu reverif ok 2023-04-15 07:51:45 +02:00
8ecaeaf4e7 Them footer WIP 2023-04-14 17:05:46 +02:00
e18aa2c49c theme site 2023-04-14 16:08:58 +02:00
575f0ec2b3 Theme body 2023-04-14 15:55:53 +02:00
5b7fcb7b3d Theme menu okay 2023-04-14 15:53:33 +02:00
6e94dd9cd9 12308 Thme bannière et menu 2023-04-14 15:40:26 +02:00
e985817582 theme menu WIP 2023-04-14 13:56:43 +02:00
8f61c40e13 Theme header 2023-04-14 12:57:24 +02:00
aaf35147b9 initData ok 2023-04-14 11:33:07 +02:00
ee295cf7dc initData presque ok 2023-04-14 10:11:13 +02:00
0d6d43381c nouveau initData 2023-04-14 09:00:15 +02:00
a66bc7d948 initData à terminer 2023-04-14 07:32:23 +02:00
c405994451 Installation d'un site à tester en espagnol 2023-04-13 15:45:02 +02:00
9ede4c38f2 Translate WIP 2023-04-13 11:09:53 +02:00
d98963fe9c maj des langues après une mise à jour. 2023-04-13 11:01:38 +02:00
6a85cae5ad Nettoyage translate 2023-04-13 10:50:00 +02:00
090f367da0 Merge branch '12308' into 12400 2023-04-13 10:28:52 +02:00
96f027d310 12308 check langue de contenu 2023-04-13 10:27:38 +02:00
aded5d5192 12308 confirmation suppression langue 2023-04-13 10:07:18 +02:00
eea007a037 Nettoyage okay 2023-04-13 07:25:07 +02:00
314db3505c 12308 install par session 2023-04-12 21:54:07 +02:00
095cab701a 12308 ZWII_UI and Install 2023-04-12 21:38:12 +02:00
b30a0037fc 12308 changes 2023-04-12 18:48:04 +02:00
5ee34dded5 12308 Session de langue sans console 2023-04-12 18:36:08 +02:00
be6649038e 12308 Session de langue 2023-04-12 18:35:46 +02:00
0e5f77daa5 $_SESSION WIP 2023-04-12 18:13:57 +02:00
17d4e7f3be Session WIP 2023-04-12 15:29:21 +02:00
52f25fe231 12308 Déplacement test 404 langue non sélectionnée 2023-04-12 15:02:35 +02:00
714396cbad Merge branch 'master' into 12400 2023-04-12 14:57:31 +02:00
cd2755dd5d typo 2023-04-11 19:15:29 +02:00
fb97570b96 redirection pour éviter une 404 d'une autre langue 2023-04-11 19:02:44 +02:00
25b9844197 Merge branch '12307' into 12400 2023-04-11 16:23:48 +02:00
a5ab6b772a 12307 lien vers une page d'une autre langue 2023-04-11 15:07:38 +02:00
b0f064dac4 changes password 2023-04-11 14:55:07 +02:00
c5fad6075c Caractères spéciaux dans le mot de passe 2023-04-11 14:53:39 +02:00
12e885796c core change 2023-04-11 13:17:55 +02:00
45eb9de2fc Form change 2023-04-11 13:15:37 +02:00
6eb9c37cad Forme change 2023-04-11 13:14:01 +02:00
b5911f609a form 3.9 pages orphelines dans la redirection 2023-04-11 13:08:40 +02:00
4e6f05fd29 changes + 404 sur langue étrangère 2023-04-11 11:54:21 +02:00
0b7ae77cfe Bug install okay 2023-04-11 09:42:11 +02:00
e718ff69f4 core test 2023-04-11 09:38:20 +02:00
0c5f14b8d8 Version 2023-04-11 09:36:31 +02:00
ca8ad39143 12306 erreur de retour lors de la mise à jour 2023-04-11 09:33:32 +02:00
7531973551 Fix install 2023-04-11 07:13:33 +02:00
6c008363cd 12306 2023-04-10 17:29:22 +02:00
0a566df789 Signe equalité 2023-04-10 17:25:21 +02:00
525250f39a 12306 complément de traduction 2023-04-10 17:03:24 +02:00
8d8d35a540 Fonts pluriel 2023-04-04 18:56:41 +02:00
63d02f358c Bugs d'installation avec les BDD au singulier WIP 2023-04-04 16:59:05 +02:00
d364b11012 Edit group Profil TEST 2023-03-31 17:02:56 +02:00
a5743ca323 Edition d'un profil 2023-03-31 14:36:19 +02:00
a87431fc9c Merge branch '12305' into 12400 2023-03-31 09:13:41 +02:00
5cd61d8d1a 12305 2023-03-31 09:12:19 +02:00
3aa5cd285b Merge branch '12305' into 12400 2023-03-31 07:18:49 +02:00
9d1fcbfd20 Bug paramètres de la localisation 2023-03-31 07:17:56 +02:00
f32d318cf6 Typo 2023-03-30 11:26:11 +02:00
70b500443f Gestion des permissions 2023-03-29 19:28:03 +02:00
a65e8dcd63 slash dans les donénes par défaut 2023-03-29 14:49:54 +02:00
8ac66696cb La gestion des groupes devient permissions.
Les groupes étant immuables.
2023-03-29 14:48:09 +02:00
3d579cb689 Stocker numéro de version 2023-03-29 10:21:07 +02:00
bb779bdb97 Stocker numéro de version 2023-03-29 10:20:40 +02:00
dbd9d2bf34 Déplace le nettoyage des langues 2023-03-29 10:19:56 +02:00
937c36ca6d admin code 3 2023-03-29 10:17:32 +02:00
b57a83e9cf Barre de membre au-delà avant admin 2023-03-28 15:18:43 +02:00
2e7931970d Nom du groupe dans l'édition 2023-03-28 15:03:17 +02:00
e0fe61ccc7 RFM pour les membres
'fontes' au lieu de 'fonte'
2023-03-28 14:51:46 +02:00
6ee961f618 Groupe Edit share folder 2023-03-28 13:43:42 +02:00
c13f01899b merge error 2023-03-28 13:21:16 +02:00
8194ef7c67 Merge branch '12400' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS into 12400 2023-03-28 13:20:32 +02:00
c4fd214e04 Merge branch '12304' into 12400 2023-03-28 13:18:55 +02:00
4845ef0074 no debug 2023-03-28 13:13:04 +02:00
862ae313f4 Mail secure to test 2023-03-28 13:12:47 +02:00
cdc2594bba Merge branch '12304' into 12400 2023-03-27 19:02:41 +02:00
b255d0fddf 12304 nouveaux RS 2023-03-27 15:11:07 +02:00
83ecbdb75b 12304 changes 2023-03-27 13:14:20 +02:00
aef19a9e9c Envoi email : encodage titre du site 2023-03-27 11:47:46 +02:00
0cd7a54904 Cryptage SMTP 2023-03-27 11:34:22 +02:00
53b78bf61d Mail auth WIP 2023-03-26 16:22:02 +02:00
ca87ee2d3b Inversion de la minification des script inline 2023-03-26 14:14:21 +02:00
91112037e9 Bug d'actualisation du sitemap 2023-03-26 09:31:42 +02:00
74684864f0 form 3.8 entité HTMl non décodée 2023-03-25 18:24:16 +01:00
471d28e4fe Mail UTF-8 en majuscules 2023-03-25 09:57:45 +01:00
85de808044 Blog 6.6 layout 2023-03-24 16:56:04 +01:00
ae494b8d66 Blog 6.6 traduction + changes 2023-03-24 09:08:15 +01:00
d4d88cfdeb Blog Read More 2023-03-24 08:48:30 +01:00
c85f208837 Lire la suite WIP 2023-03-23 07:56:45 +01:00
65a12d0e25 Blog 6.6 position RSS CSS 2023-03-23 07:49:52 +01:00
169a30f449 Blog position RSS 2023-03-23 07:43:23 +01:00
f6ec7dccd5 Init 12304 2023-03-22 17:50:45 +01:00
39e27d5082 path select WIP 2023-03-22 17:46:08 +01:00
95c8b7a975 Merge branch '12303' into 12400 2023-03-21 15:51:07 +01:00
162bf27617 Changement de branche, changes.md 2023-03-21 15:50:28 +01:00
832e0b535f Encode des messages d'erreur lors de l'installation 2023-03-21 15:48:42 +01:00
84aa2b719c Merge branch '12303' into 12400 2023-03-21 15:32:03 +01:00
47c98e25e4 Merge branch '12303-temp' into 12303-valid 2023-03-20 19:10:32 +01:00
f9c866dadb Deux lignes pour les JS 2023-03-20 14:46:46 +01:00
3a74afcb18 New 12303 2023-03-20 13:38:50 +01:00
cffbdc2928 Merge branch '12303' into 12400 2023-03-20 12:04:55 +01:00
a5bd94fe6e Jquery entités 2023-03-20 11:56:17 +01:00
afcccc2354 entité html 2023-03-20 11:44:29 +01:00
19c6c403d7 JS entités 2023-03-20 11:41:20 +01:00
df88e5a195 Script inline 2023-03-20 11:31:53 +01:00
0bf76c3778 Merge branch '12303' into 12400 2023-03-20 10:10:46 +01:00
c8ea16040e Bug double quotes 2023-03-20 09:56:05 +01:00
653f9a6842 Merge branch '12303' into 12400 2023-03-19 10:11:55 +01:00
6973442e4a changes 2023-03-19 10:11:14 +01:00
a451421ecd Merge branch '12303' into 12400 2023-03-19 10:00:57 +01:00
61379d2db1 Règle le problème des champs CSS et JS commentés 2023-03-19 09:59:11 +01:00
3da3bf63fc Permissions du groupe sur RFM 2023-03-17 15:55:15 +01:00
4b7611f830 SMTP test in progress 2023-03-17 13:58:38 +01:00
41e654c142 Error message 2023-03-17 08:48:54 +01:00
dc5484aa0a message 2023-03-17 08:44:19 +01:00
cc990de539 error message 2023-03-17 08:39:38 +01:00
5d81b3d244 update avec messages 2023-03-16 15:56:19 +01:00
e8075dbbc8 mode test 2023-03-16 15:17:58 +01:00
7e426cfb5d init 2023-03-16 15:13:52 +01:00
abcf4c3a70 user WIP 2023-03-16 11:38:46 +01:00
903c4e703c pretty print 2023-03-16 11:38:39 +01:00
9f8f9fd786 Supprime des echos 2023-03-15 18:08:15 +01:00
ac13356737 init 2023-03-15 17:53:49 +01:00
abd64c2a9b Merge branch 'master' into 12400 2023-03-14 15:08:40 +01:00
78b9374d2b Merge branch 'master' into 12400 2023-03-14 14:50:23 +01:00
26ad49dd85 Merge branch '12300' into 12400 2023-03-11 18:49:40 +01:00
a3ceda9653 Merge branch '12300' into 12400 2023-03-11 17:14:55 +01:00
52e025746a groupEdit WIP 2023-03-10 17:23:05 +01:00
7dce2beb3b groupEdit WIP 2023-03-10 16:49:49 +01:00
6641556084 preupdate database 2023-03-10 15:52:09 +01:00
2455ec0f28 fix database pre check 2023-03-10 15:49:14 +01:00
6e9f30719b rename database 2023-03-10 15:21:53 +01:00
ead284fff7 Edit group WIP 2023-03-10 15:02:49 +01:00
bb932110dc Merge branch '12300' into 12400 2023-03-10 14:13:49 +01:00
1746ff7919 Merge branch '12300' into 12400 2023-03-10 14:11:36 +01:00
5edb042dd3 Merge branch '12300' into 12400 2023-03-10 11:35:16 +01:00
6b12d9746f Merge branch '12300' into 12400 2023-03-10 11:29:55 +01:00
487d21b696 Merge branch '12300' into 12400 2023-03-10 10:20:58 +01:00
58671aeea9 Création du groupe 2023-03-10 10:19:22 +01:00
e0ac420cd4 Merge branch '12300' into 12400 2023-03-10 08:51:49 +01:00
e74b515366 Merge branch '12300' into 12400 2023-03-09 08:07:51 +01:00
21c6250214 merge 12300 2023-03-08 16:06:53 +01:00
a0f4929a57 Merge branch '12300' into 12400 2023-03-08 16:06:36 +01:00
84f8544210 icone alt 2023-03-07 16:44:11 +01:00
e21933cd93 Merge branch '12300' into 12400 2023-03-07 14:55:18 +01:00
9b73143b2c Merge branch '12300' into 12400 2023-03-07 11:01:29 +01:00
a5593535a0 Merge branch '12300' into 12400 2023-03-06 17:39:09 +01:00
b2c25db925 Merge branch '12300' into 12400 2023-03-06 15:24:11 +01:00
822a71b264 Merge branch '12300' into 12400 2023-03-05 17:03:07 +01:00
e601461101 Merge branch '12300' into 12400 2023-03-05 16:28:44 +01:00
29d4d2d7ac Merge branch '12300' into 12400 2023-03-03 21:16:21 +01:00
0449dd7936 Merge branch '12300' into 12400 2023-03-02 14:47:48 +01:00
137d901078 Merge branch '12300' into 12400 2023-03-02 14:27:40 +01:00
15d98f43a7 12400 group WIP 2023-03-01 16:11:36 +01:00
1d158a3fde Databases language et font 2023-03-01 15:50:41 +01:00
395 changed files with 17887 additions and 6131 deletions

4
.gitignore vendored
View File

@ -4,8 +4,10 @@ site/data/*
site/tmp/* site/tmp/*
site/backup/* site/backup/*
site/file/* site/file/*
site/i18n/*.json
.DS_Store .DS_Store
core/vendor/tinymce/link_list.json core/vendor/tinymce/link_list.json
robots.txt robots.txt
sitemap.xml sitemap.xml
.gitignore
core/module/config/tool/data.key
site/i18n/*.json

View File

@ -32,5 +32,16 @@ Options -Indexes
Options -MultiViews Options -MultiViews
</IfModule> </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 ! # ne pas supprimer la ligne URL rewriting !
# URL rewriting # URL rewriting

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
# ZwiiCMS 12.3.02 # ZwiiCMS 13.5.00
Zwii est un CMS sans base de données (flat-file) qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation. Zwii est un CMS sans base de données (flat-file) qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation.
@ -15,14 +15,13 @@ ZwiiCMS a été créé par un développeur de talent, [Rémi Jean](https://remij
Cette œuvre est mise à disposition sous licence Attribution - Pas d'utilisation Commerciale - Pas de Modification 4.0 International. Cette œuvre est mise à disposition sous licence Attribution - Pas d'utilisation Commerciale - Pas de Modification 4.0 International.
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. 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.
## Téléchargement de ZwiiCMS ## Téléchargement de ZwiiCMS
Pour télécharger la dernière version publiée, rendez-vous : Pour télécharger la dernière version publiée, rendez-vous :
- sur [la page des mises à jour](https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS/releases) * sur [la page des mises à jour](https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS/releases)
- ou sur [la page de téléchargement du site](https://zwiicms.fr/telechargement) * ou sur [la page de téléchargement du site](https://zwiicms.fr/telechargement)
## Installation ## Installation
@ -30,7 +29,6 @@ Décompressez l'archive de Zwii et téléversez son contenu à la racine de votr
Vous trouverez de plus amples explications, en particulier pour une installation chez Free, dans la rubrique "Téléchargements" du forum. Vous trouverez de plus amples explications, en particulier pour une installation chez Free, dans la rubrique "Téléchargements" du forum.
## Procédures de mise à jour ## Procédures de mise à jour
A l'occasion de l'installation d'une verion majeure, il est recommandé de réaliser une copie de sauvegarde. A l'occasion de l'installation d'une verion majeure, il est recommandé de réaliser une copie de sauvegarde.
@ -47,7 +45,6 @@ A l'occasion de l'installation d'une verion majeure, il est recommandé de réal
* Décompressez la nouvelle version sur votre ordinateur. * Décompressez la nouvelle version sur votre ordinateur.
* Transférez son contenu sur votre serveur en activant le remplacement des fichiers. * Transférez son contenu sur votre serveur en activant le remplacement des fichiers.
## Arborescence générale ## Arborescence générale
*Légende : [R] Répertoire - [F] Fichier* *Légende : [R] Répertoire - [F] Fichier*
@ -76,11 +73,12 @@ A l'occasion de l'installation d'une verion majeure, il est recommandé de réal
[F] page.json Données des pages [F] page.json Données des pages
[F] module.json Données des modules de pages [F] module.json Données des modules de pages
[F] local.json Données du site propres à la langue [F] local.json Données du site propres à la langue
[F] .default Indicateur de la langue de site par défaut
[R] content Dossier des contenus de page [R] content Dossier des contenus de page
[F] accueil.html Exemple contenu de la page d'accueil [F] accueil.html Exemple contenu de la page d'accueil
[R] fonts Dossier contenant les fontes installées [R] font Dossier contenant les fontes installées
[F] fonts.html Fichier contenant les appels des fontes à charger sur cdnFonts [F] font.html Fichier contenant les appels des fontes à charger sur cdnFonts
[F] fonts.css Fichier contenant la feuille de style liée aux polices de caractères locales [F] font.css Fichier contenant la feuille de style liée aux polices de caractères locales
[F] fontes.woff Fichiers locaux des fontes (woff, etc..) [F] fontes.woff Fichiers locaux des fontes (woff, etc..)
[R] modules Personnalisation des modules ou données propres [R] modules Personnalisation des modules ou données propres
[F] admin.css Thème des pages d'administration [F] admin.css Thème des pages d'administration
@ -89,9 +87,10 @@ A l'occasion de l'installation d'une verion majeure, il est recommandé de réal
[F] config.json Configuration du site [F] config.json Configuration du site
[F] core.json Configuration du noyau [F] core.json Configuration du noyau
[F] custom.css Feuille de style de la personnalisation avancée [F] custom.css Feuille de style de la personnalisation avancée
[F] fonts.json Descripteur des fontes personnalisées [F] font.json Descripteur des fontes personnalisées
[F] journal.log Journalisation des actions [F] journal.log Journalisation des activités
[F] languages.json Configuration des langues de l'interface [F] language.json Langues de l'interface
[F] profil.json Profils des utilisateurs
[F] theme.css Thème du site [F] theme.css Thème du site
[F] theme.json Données du site [F] theme.json Données du site
[F] user.json Données des utilisateurs [F] user.json Données des utilisateurs

View File

@ -1,4 +1,4 @@
# ZwiiCMS 12.3.02 # ZwiiCMS 13.5.00
Zwii is a database-less (flat-file) CMS that allows you to easily create and manage a web site without any programming knowledge. Zwii is a database-less (flat-file) CMS that allows you to easily create and manage a web site without any programming knowledge.
@ -15,14 +15,13 @@ ZwiiCMS was created by a talented developer, [Rémi Jean](https://remijean.fr/).
This work is licensed under the Attribution-Noncommercial-No Derivative Works 4.0 International License. This work is licensed under the Attribution-Noncommercial-No Derivative Works 4.0 International License.
To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/4.0/ or write to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. To view a copy of this license, visit <http://creativecommons.org/licenses/by-nc-nd/4.0/> or write to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
## Downloading ZwiiCMS ## Downloading ZwiiCMS
To download the latest released version, go to : To download the latest released version, go to :
- [the Updates page](https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS/releases) * [the Updates page](https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS/releases)
- or at [the site download page](https://zwiicms.fr/telechargement) * or at [the site download page](https://zwiicms.fr/download)
## Installation ## Installation
@ -30,7 +29,6 @@ Unzip the Zwii archive and upload its contents to the root of your server or to
You will find more explanations, in particular for an installation at Free, in the "Downloads" section of the forum. You will find more explanations, in particular for an installation at Free, in the "Downloads" section of the forum.
## Update procedures ## Update procedures
When installing a major version, it is recommended to make a backup copy. When installing a major version, it is recommended to make a backup copy.
@ -47,7 +45,6 @@ When installing a major version, it is recommended to make a backup copy.
* Unzip the new version on your computer. * Unzip the new version on your computer.
* Transfer its content to your server by activating the file replacement. * Transfer its content to your server by activating the file replacement.
## General tree structure ## General tree structure
*Legend: [D] Directory - [FILE] File *Legend: [D] Directory - [FILE] File
@ -77,6 +74,7 @@ text
[FILE] page.json Page data [FILE] page.json Page data
[FILE] module.json Page module data [FILE] module.json Page module data
[FILE] local.json Language-specific site data [FILE] local.json Language-specific site data
[FILE] .default Unique file of default site language
[DIR] content Folder of page contents [DIR] content Folder of page contents
[FILE] home.html Sample home page content [FILE] home.html Sample home page content
[DIR] fonts Folder containing the installed fonts [DIR] fonts Folder containing the installed fonts
@ -90,12 +88,13 @@ text
[FILE] config.json Site configuration [FILE] config.json Site configuration
[FILE] core.json Core configuration [FILE] core.json Core configuration
[FILE] custom.css Advanced customization stylesheet [FILE] custom.css Advanced customization stylesheet
[FILE] fonts.json Custom font descriptor [FILE] font.json Custom font descriptor
[FILE] journal.log Action logging [FILE] journal.log Activities logging
[FILE] languages.json Interface database languages [FILE] language.json Interface languages database
[FILE] profil.json Users profiles database
[FILE] theme.css Site theme [FILE] theme.css Site theme
[FILE] theme.json Site data [FILE] theme.json Site database
[FILE] user.json User data [FILE] user.json User database
[FILE] .backup Marker for file backup if present [FILE] .backup Marker for file backup if present
[DIR] file File manager upload directory [DIR] file File manager upload directory
[DIR] source Various resources [DIR] source Various resources

View File

@ -2,8 +2,11 @@
class autoload { class autoload {
public static function autoloader () { public static function autoloader () {
require_once 'core/core.php';
require_once 'core/class/router.class.php';
require_once 'core/class/helper.class.php'; require_once 'core/class/helper.class.php';
require_once 'core/class/template.class.php'; require_once 'core/class/template.class.php';
require_once 'core/class/layout.class.php';
require_once 'core/class/sitemap/Runtime.class.php'; require_once 'core/class/sitemap/Runtime.class.php';
require_once 'core/class/sitemap/FileSystem.class.php'; require_once 'core/class/sitemap/FileSystem.class.php';
require_once 'core/class/sitemap/SitemapGenerator.class.php'; require_once 'core/class/sitemap/SitemapGenerator.class.php';

View File

@ -8,7 +8,7 @@ class helper
/** Filtres personnalisés */ /** Filtres personnalisés */
const FILTER_BOOLEAN = 1; 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_FLOAT = 3;
const FILTER_ID = 4; const FILTER_ID = 4;
const FILTER_INT = 5; const FILTER_INT = 5;
@ -16,8 +16,14 @@ class helper
const FILTER_PASSWORD = 7; const FILTER_PASSWORD = 7;
const FILTER_STRING_LONG = 8; const FILTER_STRING_LONG = 8;
const FILTER_STRING_SHORT = 9; 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_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
/** /**
@ -26,22 +32,6 @@ class helper
public static function translate($text) public static function translate($text)
{ {
/*
*
$target = 'redirection';
$url = $_SERVER['QUERY_STRING'];
$module = explode('/', $url);
if ( $module[0] === $target)
{
// La traduction existe déjà dans le core
if (array_key_exists($text, core::$dialog) === false && !empty($text)) {
$dialogues = json_decode(file_get_contents('module/' . $target . '/i18n/fr_FR.json' ), true);
$data = array_merge($dialogues,[$text => '']);
file_put_contents ('module/' . $target . '/i18n/fr_FR.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
}
}
*/
// La traduction existe déjà dans le core // La traduction existe déjà dans le core
/* /*
@ -59,40 +49,41 @@ class helper
* Date au format time() * Date au format time()
* $format strftime * $format strftime
*/ */
public static function dateUTF8($format, $date) public static function dateUTF8($format, $date, $locale = 'fr_FR')
{ {
require_once 'core/class/strftime/php-8.1-strftime.class.php'; require_once 'core/class/strftime/php-8.1-strftime.class.php';
return mb_convert_encoding(\PHP81_BC\strftime($format, $date), 'UTF-8', mb_list_encodings()); return mb_convert_encoding(\PHP81_BC\strftime($format, $date, $locale), 'UTF-8', mb_list_encodings());
} }
/** /**
* Fonction pour assurer la traduction des messages * Fonction pour assurer la traduction des messages
*/ */
public static function googleTranslate($to, $text){ public static function googleTranslate($to, $text)
{
if (!file_exists('site/i18n/' . $to . '.json')) { if (!file_exists('site/i18n/' . $to . '.json')) {
file_put_contents ('site/i18n/' . $to . '.json', json_encode([])); file_put_contents('site/i18n/' . $to . '.json', json_encode([]));
} }
if (!empty($text)) { if (!empty($text)) {
//Lecture des données en ligne //Lecture des données en ligne
$data = json_decode(file_get_contents('site/i18n/' . $to . '.json'), true); $data = json_decode(file_get_contents('site/i18n/' . $to . '.json'), true);
// Mode traduction // Mode traduction
if ($to !== 'fr_FR') { if ($to !== 'fr_FR') {
$arrayjson = json_decode(file_get_contents('https://clients5.google.com/translate_a/t?client=dict-chrome-ex&sl=auto&tl=' . $to . '&q=' . rawurlencode($text)),true); $arrayjson = json_decode(file_get_contents('https://clients5.google.com/translate_a/t?client=dict-chrome-ex&sl=auto&tl=' . $to . '&q=' . rawurlencode($text)), true);
$response = $arrayjson[0][0]; $response = $arrayjson[0][0];
// Captation // Captation
if ($data !== '') { if ($data !== '') {
if (array_key_exists($text, $data) ) { if (array_key_exists($text, $data)) {
$data[$text] = $response; $data[$text] = $response;
} else { } else {
$data = array_merge($data,[$text => $response]); $data = array_merge($data, [$text => $response]);
} }
} }
// Mode alimentation des chaines // Mode alimentation des chaines
} else { } else {
// Créer la variable // Créer la variable
$data = array_merge($data,[$text => '']); $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));
} }
} }
@ -206,14 +197,20 @@ class helper
public static function autoBackup($folder, $filter = ['backup', 'tmp']) public static function autoBackup($folder, $filter = ['backup', 'tmp'])
{ {
// Creation du ZIP // Création du nom de fichier ZIP
$baseName = str_replace('/', '', helper::baseUrl(false, false)); $baseName = str_replace('/', '', helper::baseUrl(false, false));
$baseName = empty($baseName) ? 'ZwiiCMS' : $baseName; $baseName = empty($baseName) ? 'ZwiiCMS' : $baseName;
$fileName = $baseName . '-backup-' . date('Y-m-d-H-i-s', time()) . '.zip'; $fileName = $baseName . '-backup-' . date('Y-m-d-H-i-s') . '.zip';
// Initialisation de l'archive ZIP
$zip = new ZipArchive(); $zip = new ZipArchive();
$zip->open($folder . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE); if ($zip->open($folder . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
return false; // Retourne false si l'ouverture échoue
}
$directory = 'site/'; $directory = 'site/';
//$filter = array('backup','tmp','file');
// Récupération des fichiers et des dossiers
$files = new RecursiveIteratorIterator( $files = new RecursiveIteratorIterator(
new RecursiveCallbackFilterIterator( new RecursiveCallbackFilterIterator(
new RecursiveDirectoryIterator( new RecursiveDirectoryIterator(
@ -221,23 +218,30 @@ class helper
RecursiveDirectoryIterator::SKIP_DOTS RecursiveDirectoryIterator::SKIP_DOTS
), ),
function ($fileInfo, $key, $iterator) use ($filter) { function ($fileInfo, $key, $iterator) use ($filter) {
return $fileInfo->isFile() || !in_array($fileInfo->getBaseName(), $filter); // Inclure les fichiers ou les répertoires non filtrés
return $fileInfo->isFile() || ($fileInfo->isDir() && !in_array($fileInfo->getBaseName(), $filter));
} }
) )
); );
foreach ($files as $name => $file) {
// Ajout des fichiers à l'archive
foreach ($files as $file) {
if (!$file->isDir()) { if (!$file->isDir()) {
$filePath = $file->getRealPath(); $filePath = $file->getRealPath();
$relativePath = substr($filePath, strlen(realpath($directory)) + 1); $relativePath = str_replace(DIRECTORY_SEPARATOR, '/', substr($filePath, strlen(realpath($directory)) + 1));
$zip->addFile($filePath, $relativePath); $zip->addFile($filePath, $relativePath);
} }
} }
// Fermeture de l'archive ZIP
$zip->close(); $zip->close();
return ($fileName);
return $fileName;
} }
/** /**
* Retourne la liste des modules installés dans un tableau composé * Retourne la liste des modules installés dans un tableau composé
* du nom réel * du nom réel
@ -352,18 +356,25 @@ class helper
public static function checkRewrite() public static function checkRewrite()
{ {
// N'interroge que le serveur Apache // N'interroge que le serveur Apache
if (strpos($_SERVER["SERVER_SOFTWARE"], 'Apache') > 0) { if ((helper::checkServerSoftware() === false)) {
self::$rewriteStatus === false; self::$rewriteStatus = false;
} elseif (self::$rewriteStatus === null) { } else {
// Ouvre et scinde le fichier .htaccess // Ouvre et scinde le fichier .htaccess
$htaccess = explode('# URL rewriting', file_get_contents('.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 // 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') !== false);
self::$rewriteStatus = (strpos($htaccess[1], 'RewriteEngine on') > 0) ? true : false;
} }
return self::$rewriteStatus; return self::$rewriteStatus;
} }
/**
* Retourne vrai ou faux selon que le serveur est comptatible avec htaccess
* @return bool
*/
public static function checkServerSoftware() {
return (stripos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false || stripos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false);
}
/** /**
* Renvoie le numéro de version de Zwii est en ligne * Renvoie le numéro de version de Zwii est en ligne
* @return string * @return string
@ -381,11 +392,11 @@ class helper
public static function checkNewVersion($channel) public static function checkNewVersion($channel)
{ {
$version = helper::getOnlineVersion($channel); $version = helper::getOnlineVersion($channel);
$update = false;
if (!empty($version)) { if (!empty($version)) {
return ((version_compare(common::ZWII_VERSION, $version)) === -1); $update = version_compare(common::ZWII_VERSION, $version) == -1;
} else {
return false;
} }
return $update;
} }
@ -418,8 +429,8 @@ class helper
*/ */
public static function deleteCookie($cookieKey) public static function deleteCookie($cookieKey)
{ {
unset($_COOKIE[$cookieKey]);
setcookie($cookieKey, '', time() - 3600, helper::baseUrl(false, false), '', false, true); setcookie($cookieKey, '', time() - 3600, helper::baseUrl(false, false), '', false, true);
unset($_COOKIE[$cookieKey]);
} }
/** /**
@ -442,16 +453,19 @@ class helper
$text = (int) $date->format('U'); $text = (int) $date->format('U');
break; break;
case self::FILTER_FLOAT: 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; $text = (float) $text;
break; break;
case self::FILTER_ID: case self::FILTER_ID:
$text = mb_strtolower($text, 'UTF-8'); $text = mb_strtolower($text, 'UTF-8');
$text = strip_tags(str_replace( $text = strip_tags(
str_replace(
explode(',', 'á,à,â,ä,ã,å,ç,é,è,ê,ë,í,ì,î,ï,ñ,ó,ò,ô,ö,õ,ú,ù,û,ü,ý,ÿ,\',", '), explode(',', 'á,à,â,ä,ã,å,ç,é,è,ê,ë,í,ì,î,ï,ñ,ó,ò,ô,ö,õ,ú,ù,û,ü,ý,ÿ,\',", '),
explode(',', 'a,a,a,a,a,a,c,e,e,e,e,i,i,i,i,n,o,o,o,o,o,u,u,u,u,y,y,-,-,-'), explode(',', 'a,a,a,a,a,a,c,e,e,e,e,i,i,i,i,n,o,o,o,o,o,u,u,u,u,y,y,-,-,-'),
$text $text
)); )
);
$text = preg_replace('/([^a-z0-9-])/', '', $text); $text = preg_replace('/([^a-z0-9-])/', '', $text);
// Supprime les emoji // Supprime les emoji
$text = preg_replace('/[[:^print:]]/', '', $text); $text = preg_replace('/[[:^print:]]/', '', $text);
@ -487,6 +501,11 @@ class helper
case self::FILTER_URL: case self::FILTER_URL:
$text = filter_var($text, FILTER_SANITIZE_URL); $text = filter_var($text, FILTER_SANITIZE_URL);
break; break;
case self::FILTER_DATE:
$text = date('Y-m-d', $text);
break;
case self::FILTER_TIME:
$text = date('H:i', $text);
} }
return $text; return $text;
} }
@ -539,6 +558,10 @@ class helper
$css = preg_replace(['(( )+{)', '({( )+)'], '{', $css); $css = preg_replace(['(( )+{)', '({( )+)'], '{', $css);
$css = preg_replace(['(( )+})', '(}( )+)', '(;( )*})'], '}', $css); $css = preg_replace(['(( )+})', '(}( )+)', '(;( )*})'], '}', $css);
$css = preg_replace(['(;( )+)', '(( )+;)'], ';', $css); $css = preg_replace(['(;( )+)', '(( )+;)'], ';', $css);
// Convertir les codes entités
$css = htmlspecialchars_decode($css);
// Supprime les balises HTML
$css = strip_tags($css);
// Retourne le css minifié // Retourne le css minifié
return $css; return $css;
} }
@ -567,7 +590,7 @@ class helper
* @param null|int $sufix Suffixe de l'url * @param null|int $sufix Suffixe de l'url
* @return array * @return array
*/ */
public static function pagination($array, $url, $item, $sufix = null) public static function pagination($array, $url, $item, $suffix = null)
{ {
// Scinde l'url // Scinde l'url
$url = explode('/', $url); $url = explode('/', $url);
@ -591,7 +614,7 @@ class helper
if ($nbPage > 1) { if ($nbPage > 1) {
for ($i = 1; $i <= $nbPage; $i++) { for ($i = 1; $i <= $nbPage; $i++) {
$disabled = ($i === $currentPage) ? ' class="disabled"' : false; $disabled = ($i === $currentPage) ? ' class="disabled"' : false;
$pages .= '<a href="' . helper::baseUrl() . $urlCurrent . '/' . $i . $sufix . '"' . $disabled . '>' . $i . '</a>'; $pages .= '<a href="' . helper::baseUrl() . $urlCurrent . '/' . $i . $suffix . '"' . $disabled . '>' . $i . '</a>';
} }
$pages = '<div class="pagination">' . $pages . '</div>'; $pages = '<div class="pagination">' . $pages . '</div>';
} }
@ -671,35 +694,57 @@ class helper
public static function subword($text, $start, $length) public static function subword($text, $start, $length)
{ {
$text = trim($text); $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, $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; return $text;
} }
/** /**
* Cryptage * Cryptage
* @param string $key la clé d'encryptage * @param string $key la clé d'encryptage
* @param string $payload la chaine à coder * @param string $string la chaine à coder
* @return string * @return string
*/ */
public static function encrypt($key, $payload) public static function encrypt($string, $key)
{ {
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('aes-256-cbc')); $encrypted = openssl_encrypt($string, "AES-256-CBC", $key, 0, substr(md5($key), 0, 16));
$encrypted = openssl_encrypt($payload, 'aes-256-cbc', $key, 0, $iv); return base64_encode($encrypted);
return base64_encode($encrypted . '::' . $iv);
} }
/** /**
* Décryptage * Décryptage
* @param string $key la clé d'encryptage * @param string $key la clé d'encryptage
* @param string $garble la chaine à décoder * @param string $string la chaine à décoder
* @return string * @return string
*/ */
public static function decrypt($key, $garble) public static function decrypt($string, $key)
{ {
list($encrypted_data, $iv) = explode('::', base64_decode($garble), 2); $decrypted = openssl_decrypt(base64_decode($string), "AES-256-CBC", $key, 0, substr(md5($key), 0, 16));
return openssl_decrypt($encrypted_data, 'aes-256-cbc', $key, 0, $iv); return $decrypted;
} }
} }

View File

@ -141,7 +141,7 @@ class Dot implements \ArrayAccess, \Iterator, \Countable
} elseif (is_array($key)) { } elseif (is_array($key)) {
// Iterate array of paths // Iterate array of paths
foreach ($key as $k) { foreach ($key as $k) {
self::delete($k); self::deleteValue($array, $k);
} }
} }
} }

View File

@ -18,6 +18,12 @@ class JsonDb extends \Prowebcraft\Dot
protected $db = ''; protected $db = '';
protected $data = null; protected $data = null;
protected $config = []; protected $config = [];
// Tentative d'encodage après échec
const MAX_JSON_ENCODE_ATTEMPTS = 5;
// Tentative d'écriture après échec
const MAX_FILE_WRITE_ATTEMPTS = 5;
// Délais entre deux tentaives
const RETRY_DELAY_SECONDS = 1;
public function __construct($config = []) public function __construct($config = [])
{ {
@ -115,16 +121,16 @@ class JsonDb extends \Prowebcraft\Dot
protected function loadData($reload = false) protected function loadData($reload = false)
{ {
if ($this->data === null || $reload) { if ($this->data === null || $reload) {
$this->db = $this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name']; $this->db = $this->config['dir'] . $this->config['name'];
if (!file_exists($this->db)) { if (!file_exists($this->db)) {
return null; // Rebuild database manage by CMS return null; // Rebuild database manage by CMS
} else { } else {
if ($this->config['backup']) { if ($this->config['backup']) {
try { try {
//todo make backup of database
copy($this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'], $this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'] . '.backup'); copy($this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'], $this->config['dir'] . DIRECTORY_SEPARATOR . $this->config['name'] . '.backup');
} catch (\Exception $e) { } catch (\Exception $e) {
error_log('Erreur de chargement : ' . $e);
exit('Erreur de chargement : ' . $e);
} }
} }
} }
@ -142,22 +148,44 @@ class JsonDb extends \Prowebcraft\Dot
*/ */
public function save() public function save()
{ {
$v = json_encode($this->data, JSON_UNESCAPED_UNICODE | LOCK_EX); // Encode les données au format JSON avec les options spécifiées
$l = strlen($v); //$encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT);
$t = 0; $encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT);
while ($t < 5) {
$w = file_put_contents($this->db, $v); // Multi user get a locker // Vérifie la longueur de la chaîne JSON encodée
if ($w == $l) { $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; break;
} }
$try++;
// Incrémente le compteur de tentatives
$attempt++;
// Attente
sleep(1); sleep(1);
} }
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

@ -55,9 +55,9 @@ class layout extends common
* Formate le contenu de la page selon les gabarits * Formate le contenu de la page selon les gabarits
* @param Page par defaut * @param Page par defaut
*/ */
public function showSection() public function showMain()
{ {
echo '<section>'; echo '<main><section>';
// Récupérer la config de la page courante // Récupérer la config de la page courante
$blocks = is_null($this->getData(['page', $this->getUrl(0), 'block'])) ? '12' : $this->getData(['page', $this->getUrl(0), 'block']); $blocks = is_null($this->getData(['page', $this->getUrl(0), 'block'])) ? '12' : $this->getData(['page', $this->getUrl(0), 'block']);
$blocks = explode('-', $blocks); $blocks = explode('-', $blocks);
@ -82,19 +82,33 @@ class layout extends common
$content = 'col' . $blocks[1]; $content = 'col' . $blocks[1];
$blockright = 'col' . $blocks[2]; $blockright = 'col' . $blocks[2];
} }
// Page pleine pour la configuration des modules et l'édition des pages sauf l'affichage d'un article de blog // 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']; $pattern = ['config', 'edit', 'add', 'comment', 'data', 'option', 'theme', 'comment', 'article', 'data', 'gallery', 'update', 'users', 'validate'];
if ( if (
(sizeof($blocks) === 1 || (sizeof($blocks) === 1 ||
in_array($this->getUrl(1), $pattern)) in_array($this->getUrl(1), $pattern))
) { // Pleine page en mode configuration ) { // Pleine page en mode configuration
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(); $this->showContent();
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 { } else {
echo '<div class="row siteContainer">'; echo '<div class="row siteContainer">';
/** /**
* Barre gauche * Barre gauche
*/ */
if ($blockleft !== "") { if ($blockleft !== '') {
echo '<div class="' . $blockleft . '" id="contentLeft"><aside>'; echo '<div class="' . $blockleft . '" id="contentLeft"><aside>';
// Détermine si le menu est présent // Détermine si le menu est présent
if ($this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'displayMenu']) === 'none') { if ($this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'displayMenu']) === 'none') {
@ -117,12 +131,14 @@ class layout extends common
* Contenu de page * Contenu de page
*/ */
echo '<div class="' . $content . '" id="contentSite">'; echo '<div class="' . $content . '" id="contentSite">';
$this->showNavButtons('top');
$this->showContent(); $this->showContent();
$this->showNavButtons('bottom');
echo '</div>'; echo '</div>';
/** /**
* Barre droite * Barre droite
*/ */
if ($blockright !== "") { if ($blockright !== '') {
echo '<div class="' . $blockright . '" id="contentRight"><aside>'; echo '<div class="' . $blockright . '" id="contentRight"><aside>';
// Détermine si le menu est présent // Détermine si le menu est présent
if ($this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'displayMenu']) === 'none') { if ($this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'displayMenu']) === 'none') {
@ -143,7 +159,7 @@ class layout extends common
} }
echo '</div>'; echo '</div>';
} }
echo '</section>'; echo '</section></main>';
} }
/** /**
@ -280,7 +296,8 @@ class layout extends common
// Affichage de motorisé par // Affichage de motorisé par
$items .= '<span id="footerDisplayCopyright" '; $items .= '<span id="footerDisplayCopyright" ';
$items .= $this->getData(['theme', 'footer', 'displayCopyright']) === false ? 'class="displayNone"' : ''; $items .= $this->getData(['theme', 'footer', 'displayCopyright']) === false ? 'class="displayNone"' : '';
$items .= '>Motorisé&nbsp;par&nbsp;</span>'; $label = empty($this->getData(['locale', 'poweredPageLabel'])) ? 'Motorisé par' : $this->getData(['locale', 'poweredPageLabel']);
$items .= '><wbr>&nbsp;' . $label . '&nbsp;</span>';
// Toujours afficher le nom du CMS // Toujours afficher le nom du CMS
$items .= '<span id="footerZwiiCMS">'; $items .= '<span id="footerZwiiCMS">';
$items .= '<a href="https://zwiicms.fr/" onclick="window.open(this.href);return false" >ZwiiCMS</a>'; $items .= '<a href="https://zwiicms.fr/" onclick="window.open(this.href);return false" >ZwiiCMS</a>';
@ -316,12 +333,12 @@ class layout extends common
$items .= '<span id="footerDisplayCookie"'; $items .= '<span id="footerDisplayCookie"';
$items .= ($this->getData(['config', 'cookieConsent']) === true && $this->getData(['theme', 'footer', 'displayCookie']) === true) ? '>' : ' class="displayNone" >'; $items .= ($this->getData(['config', 'cookieConsent']) === true && $this->getData(['theme', 'footer', 'displayCookie']) === true) ? '>' : ' class="displayNone" >';
$label = empty($this->getData(['locale', 'cookies', 'cookiesFooterText'])) ? 'Cookies' : $this->getData(['locale', 'cookies', 'cookiesFooterText']); $label = empty($this->getData(['locale', 'cookies', 'cookiesFooterText'])) ? 'Cookies' : $this->getData(['locale', 'cookies', 'cookiesFooterText']);
$items .= '<wbr>&nbsp;|&nbsp;<a href="javascript:void(0)" class="skiptranslate" id="footerLinkCookie">' . $label . '</a>'; $items .= '<wbr>&nbsp;|&nbsp;<a href="javascript:void(0)" id="footerLinkCookie">' . $label . '</a>';
$items .= '</span>'; $items .= '</span>';
// Affichage du lien de connexion // Affichage du lien de connexion
if ( if (
($this->getData(['theme', 'footer', 'loginLink']) ($this->getData(['theme', 'footer', 'loginLink'])
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD') and $this->isConnected() === false
) )
or $this->getUrl(0) === 'theme' or $this->getUrl(0) === 'theme'
) { ) {
@ -336,19 +353,14 @@ class layout extends common
} }
// Affichage de la barre de membre simple // Affichage de la barre de membre simple
if ( if (
$this->getUser('group') === self::GROUP_MEMBER $this->getUser('group') >= self::GROUP_MEMBER && $this->getUser('group') < self::GROUP_ADMIN
&& $this->getData(['theme', 'footer', 'memberBar']) === true && $this->getData(['theme', 'footer', 'memberBar']) === true
) { ) {
$items .= '<span id="footerDisplayMemberAccount"'; $items .= '<span id="footerDisplayMemberAccount"';
$items .= $this->getData(['theme', 'footer', 'displaymemberAccount']) === false ? ' class="displayNone">' : '>'; $items .= $this->getData(['theme', 'footer', 'displaymemberAccount']) === false ? ' class="displayNone">' : '>';
$items .= '<wbr>&nbsp;|&nbsp;' . $items .= '<wbr>&nbsp;|&nbsp;';
template::ico('user', [
'margin' => 'all',
'help' => 'Mon compte',
'href' => helper::baseUrl() . 'user/edit/' . $this->getUser('id') . '/' . $_SESSION['csrf']
]);
if ( if (
$this->getData(['user', $this->getUser('id'), 'files']) === true $this->getUser('permission', 'filemanager') === true
) { ) {
$items .= '<wbr>' . template::ico('folder', [ $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']),
@ -357,6 +369,15 @@ class layout extends common
'help' => 'Fichiers du site' 'help' => 'Fichiers du site'
]); ]);
} }
if (
$this->getUser('permission', 'user', 'edit') === true
) {
$items .= '<wbr>' . template::ico('user', [
'margin' => 'all',
'help' => 'Mon compte',
'href' => helper::baseUrl() . 'user/edit/' . $this->getUser('id')
]);
}
$items .= '<wbr>' . template::ico('logout', [ $items .= '<wbr>' . template::ico('logout', [
'margin' => 'all', 'margin' => 'all',
'help' => 'Déconnecter', 'help' => 'Déconnecter',
@ -410,11 +431,27 @@ class layout extends common
$socialUrl = 'https://www.github.com/'; $socialUrl = 'https://www.github.com/';
$title = 'Github'; $title = 'Github';
break; break;
case 'redditId':
$socialUrl = 'https://www.reddit.com/user/';
$title = 'Reddit';
break;
case 'twitchId':
$socialUrl = 'https://www.twitch.tv/';
$title = 'Twitch';
break;
case 'vimeoId':
$socialUrl = 'https://vimeo.com/';
$title = 'Vimeo';
break;
case 'steamId':
$socialUrl = 'https://steamcommunity.com/id/';
$title = 'Steam';
break;
default: default:
$socialUrl = ''; $socialUrl = '';
} }
if ($socialId !== '') { if ($socialId !== '') {
$socials .= '<a href="' . $socialUrl . $socialId . '" onclick="window.open(this.href);return false" data-tippy-content="' . $title . '">' . template::ico(substr(str_replace('User', '', $socialName), 0, -2)) . '</a>'; $socials .= '<a href="' . $socialUrl . $socialId . '" onclick="window.open(this.href);return false" data-tippy-content="' . $title . '" alt="' . $title . '">' . template::ico(substr(str_replace('User', '', $socialName), 0, -2)) . '</a>';
} }
} }
if ($socials !== '') { if ($socials !== '') {
@ -464,7 +501,7 @@ class layout extends common
// Lien de connexion // Lien de connexion
if ( if (
($this->getData(['theme', 'menu', 'loginLink']) ($this->getData(['theme', 'menu', 'loginLink'])
and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD') and $this->isConnected() === false
) )
or $this->getUrl(0) === 'theme' or $this->getUrl(0) === 'theme'
) { ) {
@ -477,11 +514,12 @@ class layout extends common
} }
// Commandes pour les membres simples // Commandes pour les membres simples
if ( if (
$this->getUser('group') == self::GROUP_MEMBER $this->getUser('group') === self::GROUP_MEMBER
&& $this->getData(['theme', 'menu', 'memberBar']) === true && $this->getData(['theme', 'menu', 'memberBar']) === true
) { ) {
if ( if (
$this->getData(['user', $this->getUser('id'), 'files']) === true $this->getUser('group') >= self::GROUP_MEMBER &&
$this->getUser('permission', 'filemanager') === true
) { ) {
$itemsRight .= '<li>' . template::ico('folder', [ $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']),
@ -489,11 +527,15 @@ class layout extends common
'help' => 'Fichiers du site' 'help' => 'Fichiers du site'
]) . '</li>'; ]) . '</li>';
} }
if (
$this->getUser('permission', 'user', 'edit') === true
) {
$itemsRight .= '<li>' . template::ico('user', [ $itemsRight .= '<li>' . template::ico('user', [
'help' => 'Mon compte', 'help' => 'Mon compte',
'margin' => 'right', 'margin' => 'right',
'href' => helper::baseUrl() . 'user/edit/' . $this->getUser('id') . '/' . $_SESSION['csrf'] 'href' => helper::baseUrl() . 'user/edit/' . $this->getUser('id')
]) . '</li>'; ]) . '</li>';
}
$itemsRight .= '<li>' . $itemsRight .= '<li>' .
template::ico('logout', [ template::ico('logout', [
'help' => 'Déconnecter', 'help' => 'Déconnecter',
@ -503,7 +545,7 @@ class layout extends common
} }
// Retourne les items du menu // Retourne les items du menu
echo '<ul class="navMain" id="menuLeft">' . $itemsLeft . '</ul><ul class="navMain" id="menuRight">' . $itemsRight; echo '<ul class="navMain" id="menuLeft">' . $itemsLeft . '</ul><ul class="navMain" id="menuRight">' . $itemsRight;
// Drapeau les langues des langues selon l'existance des dossiers // Drapeau les langues
foreach (self::$languages as $key => $value) { foreach (self::$languages as $key => $value) {
if (is_dir(self::DATA_DIR . $key)) { if (is_dir(self::DATA_DIR . $key)) {
$t[] = $this->showi18n($key); $t[] = $this->showi18n($key);
@ -546,10 +588,10 @@ class layout extends common
if ( if (
($this->getData(['page', $parentPageId, 'disable']) === true ($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 ) 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_MODERATOR and $this->getUser('group') < self::GROUP_EDITOR
) )
) { ) {
$pageUrl = ($this->getData(['locale', 'homePageId']) === $this->getUrl(0)) ? helper::baseUrl(false) : helper::baseUrl() . $this->getUrl(0); $pageUrl = ($this->getData(['locale', 'homePageId']) === $this->getUrl(0)) ? helper::baseUrl(false) : helper::baseUrl() . $this->getUrl(0);
@ -612,10 +654,10 @@ class layout extends common
$items .= '<li id=' . $childKey . '>'; $items .= '<li id=' . $childKey . '>';
if ( if (
($this->getData(['page', $childKey, 'disable']) === true ($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 ) 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_MODERATOR and $this->getUser('group') < self::GROUP_EDITOR
) )
) { ) {
$pageUrl = ($this->getData(['locale', 'homePageId']) === $this->getUrl(0)) ? helper::baseUrl(false) : helper::baseUrl() . $this->getUrl(0); $pageUrl = ($this->getData(['locale', 'homePageId']) === $this->getUrl(0)) ? helper::baseUrl(false) : helper::baseUrl() . $this->getUrl(0);
@ -708,7 +750,7 @@ class layout extends common
$items .= '<li class="menuSideChild">'; $items .= '<li class="menuSideChild">';
if ( if (
$this->getData(['page', $parentPageId, 'disable']) === true $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) . '">'; $items .= '<a href="' . $this->getUrl(1) . '">';
} else { } else {
@ -732,7 +774,7 @@ class layout extends common
if ( if (
$this->getData(['page', $childKey, 'disable']) === true $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) . '">'; $itemsChildren .= '<a href="' . $this->getUrl(1) . '">';
} else { } else {
@ -798,12 +840,34 @@ class layout extends common
*/ */
public function showMetaImage() public function showMetaImage()
{ {
$items = '<meta property="og:image" content="' . helper::baseUrl(false) . self::FILE_DIR . 'source/screenshot.jpg" />'; $imagePath = self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']);
$items .= '<meta property="og:image:type" content="image/jpeg" />'; if (
$items .= '<meta property="og:image:width" content="1200" />'; $this->getData(['config', 'seo', 'openGraphImage'])
$items .= '<meta property="og:image:height" content="627" />'; && file_exists($imagePath)
) {
$typeMime = exif_imagetype($imagePath);
switch ($typeMime) {
case IMAGETYPE_JPEG:
$typeMime = 'image/jpeg';
break;
case IMAGETYPE_PNG:
$typeMime = 'image/png';
break;
default:
// Type incorrect
return;
}
$imageSize = getimagesize($imagePath);
$wide = $imageSize[0];
$height = $imageSize[1];
//Sortie
$items = '<meta property="og:image" content="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']) . '" />';
$items .= '<meta property="og:image:type" content="' . $typeMime . '" />';
$items .= '<meta property="og:image:width" content="' . $wide . '" />';
$items .= '<meta property="og:image:height" content="' . $height . '" />';
echo $items; echo $items;
} }
}
/** /**
* Affiche la notification * Affiche la notification
@ -846,31 +910,34 @@ class layout extends common
*/ */
public function showBar() public function showBar()
{ {
if ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')) { if ($this->isConnected() === true) {
// Items de gauche // Items de gauche
$leftItems = ''; $leftItems = '';
// Sélecteur de langues // Sélecteur de langues
if ($this->getUser('group') >= self::GROUP_MODERATOR) { if ($this->getUser('group') >= self::GROUP_EDITOR) {
$c = 0;
$leftItem = ''; $leftItem = '';
foreach (self::$languages as $key => $value) { foreach (self::$languages as $key => $value) {
if (is_dir(self::DATA_DIR . $key)) { if (is_dir(self::DATA_DIR . $key)) {
$c++; $location = helper::baseUrl() . 'language/content/' . $key;
$location = helper::baseUrl() . 'translate/content/' . $key; $leftItem .= '<option name="' . $key . '" value="' . $location . '" ' . ($key === self::$siteContent ? 'selected' : '') . '>' . $value . '</option>';
$leftItem .= '<option name="' . $key . '" value="' . $location . '" ' . ($key === self::$i18nContent ? 'selected' : '') . '>' . $value . '</option>';
} }
} }
if ($c > 1) {
$leftItems .= '<li><select id="barSelectLanguage" >'; $leftItems .= '<li><select id="barSelectLanguage" >';
$leftItems .= $leftItem; $leftItems .= $leftItem;
$leftItems .= '</select></li>'; $leftItems .= '</select></li>';
} }
if ($this->getUser('group') >= self::GROUP_ADMIN) {
$leftItems .= '<li>' . template::ico('flag', [
'help' => 'Langues',
'href' => helper::baseUrl() . 'language'
]) . '</li>';
} }
// Liste des pages // Liste des pages
if ($this->getUser('group') >= self::GROUP_MODERATOR) { if ($this->getUser('group') >= self::GROUP_EDITOR) {
$leftItems .= '<li><select id="barSelectPage">'; $leftItems .= '<li><select id="barSelectPage">';
$leftItems .= '<option value="">Pages du site</option>'; $leftItems .= '<option value="">' . helper::translate('Pages du site') . '</option>';
$leftItems .= '<optgroup label="Pages orphelines">'; $leftItems .= '<optgroup label="' . helper::translate('Pages orphelines') . '">';
$orpheline = true; $orpheline = true;
$currentPageId = $this->getData(['page', $this->getUrl(0)]) ? $this->getUrl(0) : $this->getUrl(2); $currentPageId = $this->getData(['page', $this->getUrl(0)]) ? $this->getUrl(0) : $this->getUrl(2);
foreach ($this->getHierarchy(null, false) as $parentPageId => $childrenPageIds) { foreach ($this->getHierarchy(null, false) as $parentPageId => $childrenPageIds) {
@ -879,7 +946,7 @@ class layout extends common
$orpheline $orpheline
) { ) {
$orpheline = false; $orpheline = false;
$leftItems .= '<optgroup label="Pages dans le menu">'; $leftItems .= '<optgroup label="' . helper::translate('Pages dans le menu') . '">';
} }
// Exclure les barres // Exclure les barres
if ($this->getData(['page', $parentPageId, 'block']) !== 'bar') { if ($this->getData(['page', $parentPageId, 'block']) !== 'bar') {
@ -909,7 +976,7 @@ class layout extends common
} }
$leftItems .= '</optgroup' > $leftItems .= '</optgroup' >
// Afficher les barres // Afficher les barres
$leftItems .= '<optgroup label="Barres latérales">'; $leftItems .= '<optgroup label="' . helper::translate('Barres latérales') . '">';
foreach ($this->getHierarchy(null, false, true) as $parentPageId => $childrenPageIds) { foreach ($this->getHierarchy(null, false, true) as $parentPageId => $childrenPageIds) {
$leftItems .= '<option value="' . helper::baseUrl() . $parentPageId . '"' . ($parentPageId === $currentPageId ? ' selected' : false) . '>' . $this->getData(['page', $parentPageId, 'shortTitle']) . '</option>'; $leftItems .= '<option value="' . helper::baseUrl() . $parentPageId . '"' . ($parentPageId === $currentPageId ? ' selected' : false) . '>' . $this->getData(['page', $parentPageId, 'shortTitle']) . '</option>';
foreach ($childrenPageIds as $childKey) { foreach ($childrenPageIds as $childKey) {
@ -918,49 +985,82 @@ class layout extends common
} }
$leftItems .= '</optgroup>'; $leftItems .= '</optgroup>';
$leftItems .= '</select></li>'; $leftItems .= '</select></li>';
// Bouton Ajouter une page
if ($this->getUser('permission', 'page', 'add')) {
$leftItems .= '<li>' . template::ico('plus', [ $leftItems .= '<li>' . template::ico('plus', [
'href' => helper::baseUrl() . 'page/add', 'href' => helper::baseUrl() . 'page/add/' . self::$siteContent,
'help' => 'Nouvelle page ou barre latérale' 'help' => 'Nouvelle page ou barre latérale'
]) . '</li>'; ]) . '</li>';
}
if ( if (
// Sur un module de page qui autorise le bouton de modification de la page // Sur un module de page qui autorise le bouton de modification de la page
$this->core->output['showBarEditButton'] $this->core->output['showBarEditButton']
// Sur une page sans module // Sur une page sans module
or $this->getData(['page', $this->getUrl(0), 'moduleId']) === '' or $this->getData(['page', $this->getUrl(0), 'moduleId']) === ''
// Sur une page avec un module invalide // Sur une page avec un module invalide
or (!is_null($this->getData(['page', $this->getUrl(2), 'moduleId'])) && or (empty($this->getData(['page', $this->getUrl(0), 'moduleId'])) === false
!class_exists($this->getData(['page', $this->getUrl(2), 'moduleId'])) and class_exists($this->getData(['page', $this->getUrl(0), 'moduleId'])) === false
) )
// Sur une page d'accueil // Sur une page d'accueil
or $this->getUrl(0) === '' or $this->getUrl(0) === ''
) {
// Bouton Editer une page
if (
$this->getUser('permission', 'page', 'edit')
and $this->geturl(1) !== 'edit'
) { ) {
$leftItems .= '<li>' . template::ico('pencil', [ $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' 'help' => 'Éditer la page'
]) . '</li>'; ]) . '</li>';
if ($this->getData(['page', $this->getUrl(0), 'moduleId'])) { }
// Bouton Editer le module d'une page
if (
$this->getUser('permission', 'page', 'module')
and $this->geturl(1) !== 'edit'
and $this->getData(['page', $this->getUrl(0), 'moduleId'])
and class_exists($this->getData(['page', $this->getUrl(0), 'moduleId'])) === true
) {
$leftItems .= '<li>' . template::ico('gear', [ $leftItems .= '<li>' . template::ico('gear', [
'href' => helper::baseUrl() . $this->getUrl(0) . '/config', 'href' => helper::baseUrl() . $this->getUrl(0) . '/config',
'help' => 'Module de la page' 'help' => 'Module de la page'
]) . '</li>'; ]) . '</li>';
} }
// Bouton dupliquer une page
if (
$this->getUser('permission', 'page', 'duplicate')
and $this->geturl(1) !== 'edit'
) {
$leftItems .= '<li>' . template::ico('clone', [ $leftItems .= '<li>' . template::ico('clone', [
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(0) . '&csrf=' . $_SESSION['csrf'], 'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(0) . '/' . self::$siteContent,
'help' => 'Dupliquer la page' 'help' => 'Dupliquer la page'
]) ])
. '</li>'; . '</li>';
}
// Bouton Effacer une page
if (
$this->getUser('permission', 'page', 'delete')
and $this->geturl(1) !== 'edit'
) {
$leftItems .= '<li>' . template::ico('trash', [ $leftItems .= '<li>' . template::ico('trash', [
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(0) . '&csrf=' . $_SESSION['csrf'], 'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(0) . '/' . self::$siteContent,
'help' => 'Supprimer la page', 'help' => 'Supprimer la page',
'id' => 'pageDelete' 'id' => 'pageDelete'
]) ])
. '</li>'; . '</li>';
} }
} }
}
// Items de droite // Items de droite
$rightItems = ''; $rightItems = '';
if ($this->getUser('group') >= self::GROUP_MODERATOR) { if (
$this->getUser('group') >= self::GROUP_EDITOR
&& $this->getUser(
'permission',
'filemanager'
)
) {
$rightItems .= '<li>' . template::ico('folder', [ $rightItems .= '<li>' . template::ico('folder', [
'help' => 'Fichiers', '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']),
@ -972,23 +1072,14 @@ class layout extends common
'help' => 'Thème', 'help' => 'Thème',
'href' => helper::baseUrl() . 'theme' 'href' => helper::baseUrl() . 'theme'
]) . '</li>'; ]) . '</li>';
$rightItems .= '<li>' . template::ico('puzzle', [ $rightItems .= '<li>' . template::ico('users', [
'help' => 'Modules', 'help' => 'Utilisateurs',
'href' => helper::baseUrl() . 'plugin' 'href' => helper::baseUrl() . 'user'
]) . '</li>';
$rightItems .= '<li>' . template::ico('flag', [
'help' => 'Multilingue',
'href' => helper::baseUrl() . 'translate'
]) . '</li>'; ]) . '</li>';
$rightItems .= '<li>' . template::ico('cog-alt', [ $rightItems .= '<li>' . template::ico('cog-alt', [
'help' => 'Configuration', 'help' => 'Configuration',
'href' => helper::baseUrl() . 'config' 'href' => helper::baseUrl() . 'config'
]) . '</li>'; ]) . '</li>';
$rightItems .= '<li>' . template::ico('users', [
'help' => 'Utilisateurs',
'href' => helper::baseUrl() . 'user'
]) . '</li>';
// Mise à jour automatique // Mise à jour automatique
$today = mktime(0, 0, 0); $today = mktime(0, 0, 0);
$checkUpdate = $this->getData(['core', 'lastAutoUpdate']); $checkUpdate = $this->getData(['core', 'lastAutoUpdate']);
@ -1000,24 +1091,62 @@ class layout extends common
$today > $checkUpdate + $this->getData(['config', 'autoUpdateDelay', 86400]) $today > $checkUpdate + $this->getData(['config', 'autoUpdateDelay', 86400])
) { ) {
// Dernier auto controle // Dernier auto controle
$this->setData(['core', 'lastAutoUpdate', $today]); $this->setData(['core', 'lastAutoUpdate', $today], false);
if ( if (
helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL) 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 // Afficher le bouton : Mise à jour détectée + activée
if ($this->getData(['core', 'updateAvailable'])) { 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>'; $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->getUser('group') >= self::GROUP_MODERATOR) { if ($this->getData(['core', 'updateModuleAvailable'])) {
$rightItems .= '<li><a href="' . helper::baseUrl() . 'user/edit/' . $this->getUser('id') . '/' . $_SESSION['csrf'] . $rightItems .= '<li>' . template::ico('puzzle colorRed', [
'" data-tippy-content="'. helper::translate('Configurer mon compte') . '">' . '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')
) {
$rightItems .= '<li><a href="' . helper::baseUrl() . 'user/edit/' . $this->getUser('id') .
'" data-tippy-content="' . helper::translate('Configurer mon compte') . '">' .
template::ico('user', ['margin' => 'right']) . '<span id="displayUsername">' . $this->getUser('firstname') . ' ' . $this->getUser('lastname') . template::ico('user', ['margin' => 'right']) . '<span id="displayUsername">' . $this->getUser('firstname') . ' ' . $this->getUser('lastname') .
'</span></a></li>'; '</span></a></li>';
} }
@ -1043,7 +1172,8 @@ class layout extends common
if ($this->core->output['inlineScript']) { if ($this->core->output['inlineScript']) {
$inlineScript = implode($this->core->output['inlineScript']); $inlineScript = implode($this->core->output['inlineScript']);
} }
echo '<script defer>' . helper::minifyJs($coreScript . $this->core->output['script'] . htmlspecialchars_decode($inlineScript)) . '</script>'; echo '<script defer>' . helper::minifyJs($coreScript . $this->core->output['script']) . '</script>';
echo '<script defer>' . helper::minifyJs(htmlspecialchars_decode($inlineScript)) . '</script>';
} }
/** /**
@ -1070,7 +1200,7 @@ class layout extends common
if ($this->core->output['inlineStyle']) { if ($this->core->output['inlineStyle']) {
foreach ($this->core->output['inlineStyle'] as $style) { foreach ($this->core->output['inlineStyle'] as $style) {
if ($style) { if ($style) {
echo '<style type="text/css">' . helper::minifyCss($style) . '</style>'; echo '<style type="text/css">' . helper::minifyCss(htmlspecialchars_decode($style)) . '</style>';
} }
} }
@ -1083,8 +1213,8 @@ class layout extends common
public function showFonts() public function showFonts()
{ {
// Import des fontes liées au thème // Import des fontes liées au thème
if (file_exists(self::DATA_DIR . 'fonts/fonts.html')) { if (file_exists(self::DATA_DIR . 'font/font.html')) {
include_once(self::DATA_DIR . 'fonts/fonts.html'); include_once(self::DATA_DIR . 'font/font.html');
} }
} }
@ -1097,8 +1227,8 @@ class layout extends common
$vars = 'var baseUrl = ' . json_encode(helper::baseUrl(false)) . ';'; $vars = 'var baseUrl = ' . json_encode(helper::baseUrl(false)) . ';';
$vars .= 'var baseUrlQs = ' . json_encode(helper::baseUrl()) . ';'; $vars .= 'var baseUrlQs = ' . json_encode(helper::baseUrl()) . ';';
if ( if (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') $this->isConnected() === true
and $this->getUser('group') >= self::GROUP_MODERATOR and $this->getUser('group') >= self::GROUP_EDITOR
) { ) {
$vars .= 'var privateKey = ' . json_encode(md5_file(self::DATA_DIR . 'core.json')) . ';'; $vars .= 'var privateKey = ' . json_encode(md5_file(self::DATA_DIR . 'core.json')) . ';';
} }
@ -1146,11 +1276,8 @@ class layout extends common
public function showi18n($lang) public function showi18n($lang)
{ {
if ( if (
is_dir(self::DATA_DIR . $lang) (isset($_SESSION['ZWII_SITE_CONTENT'])
) { and $_SESSION['ZWII_SITE_CONTENT'] === $lang
if (
(isset($_COOKIE['ZWII_CONTENT'])
and $_COOKIE['ZWII_CONTENT'] === $lang
) )
) { ) {
$select = ' class="i18nFlagSelected" '; $select = ' class="i18nFlagSelected" ';
@ -1159,9 +1286,75 @@ class layout extends common
} }
$items = '<li>'; $items = '<li>';
$items .= '<a href="' . helper::baseUrl() . 'translate/content/' . $lang . '"><img ' . $select . ' alt="' . self::$languages[$lang] . '" src="' . helper::baseUrl(false) . 'core/vendor/i18n/png/' . $lang . '.png"/></a>'; $items .= '<a href="' . helper::baseUrl() . 'language/content/' . $lang . '"><img ' . $select . ' alt="' . self::$languages[$lang] . '" src="' . helper::baseUrl(false) . 'core/vendor/i18n/png/' . $lang . '.png"/></a>';
$items .= '</li>'; $items .= '</li>';
}
return $items; return $items;
} }
// Affiche une icône de navigation
// @param $position string 'top' or 'bottom
public function showNavButtons($position)
{
// Boutons par défaut
$leftButton = 'left';
$rightButton = 'right-dir';
// Déterminer la hiérarchie des pages
$hierarchy = array();
foreach ($this->getHierarchy() as $parentKey => $parentValue) {
$hierarchy[] = $parentKey;
foreach ($parentValue as $childKey) {
$hierarchy[] = $childKey;
}
}
// Parcourir la hiérarchie et rechercher les éléments avant et après
$elementToFind = $this->getUrl(0);
// Trouver la clé de l'élément recherché
$key = array_search($elementToFind, $hierarchy);
$previousPage = null;
$nextPage = null;
if ($key !== false) {
// Trouver l'élément précédent
$previousKey = ($key > 0) ? $key - 1 : null;
$previousValue = ($previousKey !== null) ? $hierarchy[$previousKey] : null;
// Trouver l'élément suivant
$nextKey = ($key < count($hierarchy) - 1) ? $key + 1 : null;
$nextValue = ($nextKey !== null) ? $hierarchy[$nextKey] : null;
$previousPage = $previousValue;
$nextPage = $nextValue;
}
// Jeux d'icônes sinon celui par défaut
if ($this->getData(['page', $this->getUrl(0), 'navTemplate'])) {
$leftButton = self::$navIconTemplate[$this->getData(['page', $this->getUrl(0), 'navTemplate'])]['left'];
$rightButton = self::$navIconTemplate[$this->getData(['page', $this->getUrl(0), 'navTemplate'])]['right'];
}
$items = '<div class="navButton">';
$items .= '<div class="row">';
$items .= '<div class="col1">';
if (
$previousPage !== null && $this->getData(['page', $this->getUrl(0), 'navLeft']) === $position
) {
$items .= template::button('navPreviousButtonLeft', [
'href' => helper::baseUrl() . $previousPage,
'value' => template::ico($leftButton)
]);
}
$items .= '</div>';
$items .= '<div class="col1 offset10">';
if ($nextPage !== null && $this->getData(['page', $this->getUrl(0), 'navRight']) === $position) {
$items .= template::button('navNextButtonRight', [
'href' => helper::baseUrl() . $nextPage,
'value' => template::ico($rightButton)
]);
}
$items .= '</div></div></div>';
echo $items;
}
} }

View File

@ -1,12 +1,5 @@
<?php <?php
/**
* Chargement des classes filles
* router : aiguillage des pages
*/
require_once('core/class/layout.class.php');
class core extends common class core extends common
{ {
@ -18,16 +11,16 @@ class core extends common
parent::__construct(); parent::__construct();
// Token CSRF // Token CSRF
if (empty($_SESSION['csrf'])) { if (empty($_SESSION['csrf'])) {
$_SESSION['csrf'] = bin2hex(openssl_random_pseudo_bytes(32)); $_SESSION['csrf'] = bin2hex(openssl_random_pseudo_bytes(64));
} }
// Fuseau horaire // Fuseau horaire
self::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper common::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper
date_default_timezone_set(self::$timezone); date_default_timezone_set(common::$timezone);
// Supprime les fichiers temporaires // Supprime les fichiers temporaires
$lastClearTmp = mktime(0, 0, 0); $lastClearTmp = mktime(0, 0, 0);
if ($lastClearTmp > $this->getData(['core', 'lastClearTmp']) + 86400) { if ($lastClearTmp > $this->getData(['core', 'lastClearTmp']) + 86400) {
$iterator = new DirectoryIterator(self::TEMP_DIR); $iterator = new DirectoryIterator(common::TEMP_DIR);
foreach ($iterator as $fileInfos) { foreach ($iterator as $fileInfos) {
if ( if (
$fileInfos->isFile() && $fileInfos->isFile() &&
@ -39,8 +32,6 @@ class core extends common
} }
// Date de la dernière suppression // Date de la dernière suppression
$this->setData(['core', 'lastClearTmp', $lastClearTmp]); $this->setData(['core', 'lastClearTmp', $lastClearTmp]);
// Enregistre les données
//$this->SaveData();
} }
// Backup automatique des données // Backup automatique des données
$lastBackup = mktime(0, 0, 0); $lastBackup = mktime(0, 0, 0);
@ -50,11 +41,11 @@ class core extends common
and $this->getData(['user']) // Pas de backup pendant l'installation and $this->getData(['user']) // Pas de backup pendant l'installation
) { ) {
// Copie des fichier de données // 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 // Date du dernier backup
$this->setData(['core', 'lastBackup', $lastBackup]); $this->setData(['core', 'lastBackup', $lastBackup]);
// Supprime les backups de plus de 30 jours // Supprime les backups de plus de 30 jours
$iterator = new DirectoryIterator(self::BACKUP_DIR); $iterator = new DirectoryIterator(common::BACKUP_DIR);
foreach ($iterator as $fileInfos) { foreach ($iterator as $fileInfos) {
if ( if (
$fileInfos->isFile() $fileInfos->isFile()
@ -67,23 +58,23 @@ class core extends common
} }
// Crée le fichier de personnalisation avancée // Crée le fichier de personnalisation avancée
if (file_exists(self::DATA_DIR . 'custom.css') === false) { if (file_exists(common::DATA_DIR . 'custom.css') === false) {
file_put_contents(self::DATA_DIR . 'custom.css', file_get_contents('core/module/theme/resource/custom.css')); $this->secure_file_put_contents(common::DATA_DIR . 'custom.css', file_get_contents('core/module/theme/resource/custom.css'));
chmod(self::DATA_DIR . 'custom.css', 0755); chmod(common::DATA_DIR . 'custom.css', 0755);
} }
// Crée le fichier de personnalisation // Crée le fichier de personnalisation
if (file_exists(self::DATA_DIR . 'theme.css') === false) { if (file_exists(common::DATA_DIR . 'theme.css') === false) {
file_put_contents(self::DATA_DIR . 'theme.css', ''); $this->secure_file_put_contents(common::DATA_DIR . 'theme.css', '');
chmod(self::DATA_DIR . 'theme.css', 0755); chmod(common::DATA_DIR . 'theme.css', 0755);
} }
// Crée le fichier de personnalisation de l'administration // Crée le fichier de personnalisation de l'administration
if (file_exists(self::DATA_DIR . 'admin.css') === false) { if (file_exists(common::DATA_DIR . 'admin.css') === false) {
file_put_contents(self::DATA_DIR . 'admin.css', ''); $this->secure_file_put_contents(common::DATA_DIR . 'admin.css', '');
chmod(self::DATA_DIR . 'admin.css', 0755); chmod(common::DATA_DIR . 'admin.css', 0755);
} }
// Check la version rafraichissement du theme // Check la version rafraichissement du theme
$cssVersion = preg_split('/\*+/', file_get_contents(self::DATA_DIR . 'theme.css')); $cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . 'theme.css'));
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['theme'])))) { if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['theme'])))) {
// Version // Version
$css = '/*' . md5(json_encode($this->getData(['theme']))) . '*/'; $css = '/*' . md5(json_encode($this->getData(['theme']))) . '*/';
@ -97,9 +88,9 @@ class core extends common
*/ */
// Fonts disponibles // Fonts disponibles
$fontsAvailable['files'] = $this->getData(['fonts', 'files']); $fontsAvailable['files'] = $this->getData(['font', 'files']);
$fontsAvailable['imported'] = $this->getData(['fonts', 'imported']); $fontsAvailable['imported'] = $this->getData(['font', 'imported']);
$fontsAvailable['websafe'] = self::$fontsWebSafe; $fontsAvailable['websafe'] = common::$fontsWebSafe;
// Fontes installées // Fontes installées
$fonts = [ $fonts = [
@ -112,53 +103,14 @@ class core extends common
// Suppression des polices identiques // Suppression des polices identiques
$fonts = array_unique($fonts); $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 fonts.html inclus dans main.php * Charge les fontes
*/
$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 . 'fonts')) {
mkdir(self::DATA_DIR . 'fonts');
}
file_put_contents(self::DATA_DIR . 'fonts/fonts.html', $fontFile);
/**
* Fontes installées localement
*/ */
foreach ($fonts as $fontId) { foreach ($fonts as $fontId) {
// Validité du tableau : foreach (['websafe', 'imported', 'files'] as $typeFont) {
if (isset($fontsAvailable['files'][$fontId])) { if (isset($fontsAvailable[$typeFont][$fontId])) {
if (file_exists(self::DATA_DIR . 'fonts/' . $fontId)) { $fonts[$fontId] = $fontsAvailable[$typeFont][$fontId]['font-family'];
// Chargement de la police
$css .= '@font-face {font-family:"' . $fontsAvailable['files'][$fontId]['font-family'] . '";';
$css .= 'src: url("' . helper::baseUrl(false) . self::DATA_DIR . 'fonts/' . $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';
} }
} }
} }
@ -309,7 +261,7 @@ class core extends common
$css .= 'footer span, #footerText > p {color:' . $this->getData(['theme', 'footer', 'textColor']) . ';font-family:' . $fonts[$this->getData(['theme', 'footer', 'font'])] . ';font-weight:' . $this->getData(['theme', 'footer', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'footer', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'footer', 'textTransform']) . '}'; $css .= 'footer span, #footerText > p {color:' . $this->getData(['theme', 'footer', 'textColor']) . ';font-family:' . $fonts[$this->getData(['theme', 'footer', 'font'])] . ';font-weight:' . $this->getData(['theme', 'footer', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'footer', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'footer', 'textTransform']) . '}';
$css .= 'footer {background-color:' . $colors['normal'] . ';color:' . $this->getData(['theme', 'footer', 'textColor']) . '}'; $css .= 'footer {background-color:' . $colors['normal'] . ';color:' . $this->getData(['theme', 'footer', 'textColor']) . '}';
$css .= 'footer a{color:' . $this->getData(['theme', 'footer', 'textColor']) . '}'; //$css .= 'footer a{color:' . $this->getData(['theme', 'footer', 'textColor']) . '}';
$css .= 'footer #footersite > div {margin:' . $this->getData(['theme', 'footer', 'height']) . ' 0}'; $css .= 'footer #footersite > div {margin:' . $this->getData(['theme', 'footer', 'height']) . ' 0}';
$css .= 'footer #footerbody > div {margin:' . $this->getData(['theme', 'footer', 'height']) . ' 0}'; $css .= 'footer #footerbody > div {margin:' . $this->getData(['theme', 'footer', 'height']) . ' 0}';
@ -318,14 +270,8 @@ class core extends common
$css .= '#footerText > p {text-align:' . $this->getData(['theme', 'footer', 'textAlign']) . '}'; $css .= '#footerText > p {text-align:' . $this->getData(['theme', 'footer', 'textAlign']) . '}';
$css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}'; $css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}';
// Enregistre les fontes
if (!is_dir(self::DATA_DIR . 'fonts')) {
mkdir(self::DATA_DIR . 'fonts');
}
file_put_contents(self::DATA_DIR . 'fonts/fonts.html', $fontFile);
// Enregistre la personnalisation // Enregistre la personnalisation
file_put_contents(self::DATA_DIR . 'theme.css', $css); $this->secure_file_put_contents(common::DATA_DIR . 'theme.css', $css);
// Effacer le cache pour tenir compte de la couleur de fond TinyMCE // Effacer le cache pour tenir compte de la couleur de fond TinyMCE
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT"); header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
@ -336,16 +282,16 @@ class core extends common
} }
// Check la version rafraichissement du theme admin // 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'])))) { if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['admin'])))) {
// Version // Version
$css = '/*' . md5(json_encode($this->getData(['admin']))) . '*/'; $css = '/*' . md5(json_encode($this->getData(['admin']))) . '*/';
// Fonts disponibles // Fonts disponibles
$fontsAvailable['files'] = $this->getData(['fonts', 'files']); $fontsAvailable['files'] = $this->getData(['font', 'files']);
$fontsAvailable['imported'] = $this->getData(['fonts', 'imported']); $fontsAvailable['imported'] = $this->getData(['font', 'imported']);
$fontsAvailable['websafe'] = self::$fontsWebSafe; $fontsAvailable['websafe'] = common::$fontsWebSafe;
/** /**
* Import des polices de caractères * Import des polices de caractères
@ -359,44 +305,12 @@ class core extends common
$fonts = array_unique($fonts); $fonts = array_unique($fonts);
/** /**
* Charge les fontes websafe * Charge les fontes
*/
$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 fonts.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 . 'fonts/fonts.html', $fontFile);
/**
* Fontes installées localement
*/ */
foreach ($fonts as $fontId) { foreach ($fonts as $fontId) {
// Validité du tableau : foreach (['websafe', 'imported', 'files'] as $typeFont) {
if (isset($fontsAvailable['files'][$fontId])) { if (isset($fontsAvailable[$typeFont][$fontId])) {
if (file_exists(self::DATA_DIR . 'fonts/' . $fontId)) { $fonts[$fontId] = $fontsAvailable[$typeFont][$fontId]['font-family'];
// Chargement de la police
$css .= '@font-face {font-family:"' . $fontsAvailable['files'][$fontId]['font-family'] . '";';
$css .= 'src: url("' . helper::baseUrl(false) . self::DATA_DIR . 'fonts/' . $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';
} }
} }
} }
@ -407,6 +321,26 @@ class core extends common
$css .= 'p, div, label, select, input, table, span {font-family:' . $fonts[$this->getData(['admin', 'fontText'])] . '}'; $css .= 'p, div, label, select, input, table, span {font-family:' . $fonts[$this->getData(['admin', 'fontText'])] . '}';
$css .= 'body,.row > div {font-size:' . $this->getData(['admin', 'fontSize']) . '}'; $css .= 'body,.row > div {font-size:' . $this->getData(['admin', 'fontSize']) . '}';
$css .= 'body h1, h2, h3, h4 a, h5, h6 {font-family:' . $fonts[$this->getData(['admin', 'fontTitle'])] . ';color:' . $this->getData(['admin', 'colorTitle']) . ';}'; $css .= 'body h1, h2, h3, h4 a, h5, h6 {font-family:' . $fonts[$this->getData(['admin', 'fontTitle'])] . ';color:' . $this->getData(['admin', 'colorTitle']) . ';}';
$css .= '.container {max-width:' . $this->getData(['admin', 'width']) . '}';
$margin = $this->getData(['theme', 'site', 'margin']) ? '0' : '20px';
// Marge supplémentaire lorsque le pied de page est fixe
if (
$this->getData(['theme', 'footer', 'fixed']) === true &&
$this->getData(['theme', 'footer', 'position']) === 'body'
) {
$marginBottomLarge = ((str_replace('px', '', $this->getData(['theme', 'footer', 'height'])) * 2) + 31) . 'px';
$marginBottomSmall = ((str_replace('px', '', $this->getData(['theme', 'footer', 'height'])) * 2) + 93) . 'px';
} else {
$marginBottomSmall = $margin;
$marginBottomLarge = $margin;
}
$css .= $this->getData(['admin', 'width']) === '100%'
? '@media (min-width: 769px) {#site{margin:0 auto ' . $marginBottomLarge . ' 0 !important;}}@media (max-width: 768px) {#site{margin:0 auto ' . $marginBottomSmall . ' 0 !important;}}#site.light{margin:5% auto !important;} body{margin:0 auto !important;} #bar{margin:0 auto !important;} body > header{margin:0 auto !important;} body > nav {margin: 0 auto !important;} body > footer {margin:0 auto !important;}'
: '@media (min-width: 769px) {#site{margin: ' . $margin . ' auto ' . $marginBottomLarge . ' auto !important;}}@media (max-width: 768px) {#site{margin: ' . $margin . ' auto ' . $marginBottomSmall . ' auto !important;}}#site.light{margin: 5% auto !important;} body{margin:0px 10px;} #bar{margin: 0 -10px;} body > header{margin: 0 -10px;} body > nav {margin: 0 -10px;} body > footer {margin: 0 -10px;} ';
$css .= $this->getData(['admin', 'width']) === '750px'
? '.button, button{font-size:0.8em;}'
: '';
// TinyMCE // TinyMCE
$colors = helper::colorVariants($this->getData(['admin', 'colorText'])); $colors = helper::colorVariants($this->getData(['admin', 'colorText']));
@ -431,7 +365,7 @@ class core extends common
// Bordure du contour TinyMCE // Bordure du contour TinyMCE
$css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}'; $css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}';
// Enregistre la personnalisation // Enregistre la personnalisation
file_put_contents(self::DATA_DIR . 'admin.css', $css); $this->secure_file_put_contents(common::DATA_DIR . 'admin.css', $css);
} }
} }
/** /**
@ -447,8 +381,8 @@ class core extends common
require 'core/module/' . $classPath; require 'core/module/' . $classPath;
} }
// Module // Module
elseif (is_readable(self::MODULE_DIR . $classPath)) { elseif (is_readable(common::MODULE_DIR . $classPath)) {
require self::MODULE_DIR . $classPath; require common::MODULE_DIR . $classPath;
} }
// Librairie // Librairie
elseif (is_readable('core/vendor/' . $classPath)) { elseif (is_readable('core/vendor/' . $classPath)) {
@ -462,7 +396,6 @@ class core extends common
public function router() public function router()
{ {
//
$layout = new layout($this); $layout = new layout($this);
// Installation // Installation
@ -474,19 +407,14 @@ class core extends common
header('Location:' . helper::baseUrl() . 'install'); header('Location:' . helper::baseUrl() . 'install');
exit(); exit();
} }
// Journalisation // Journalisation
$dataLog = helper::dateUTF8('%Y %m %d', time()) . ' - ' . helper::dateUTF8('%H:%M', time()); $this->saveLog();
$dataLog .= helper::getIp($this->getData(['config', 'connect', 'anonymousIp'])) . ';';
$dataLog .= $this->getUser('id') ? $this->getUser('id') . ';' : 'anonyme' . ';';
$dataLog .= $this->getUrl();
$dataLog .= PHP_EOL;
if ($this->getData(['config', 'connect', 'log'])) {
file_put_contents(self::DATA_DIR . 'journal.log', $dataLog, FILE_APPEND);
}
// Force la déconnexion des membres bannis ou d'une seconde session // Force la déconnexion des membres bannis ou d'une seconde session
if ( if (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') $this->isConnected() === true
and ($this->getUser('group') === self::GROUP_BANNED and ($this->getUser('group') === common::GROUP_BANNED
or ($_SESSION['csrf'] !== $this->getData(['user', $this->getUser('id'), 'accessCsrf']) or ($_SESSION['csrf'] !== $this->getData(['user', $this->getUser('id'), 'accessCsrf'])
and $this->getData(['config', 'connect', 'autoDisconnect']) === true) and $this->getData(['config', 'connect', 'autoDisconnect']) === true)
) )
@ -499,9 +427,9 @@ class core extends common
$this->getData(['config', 'maintenance']) $this->getData(['config', 'maintenance'])
and in_array($this->getUrl(0), ['maintenance', 'user']) === false and in_array($this->getUrl(0), ['maintenance', 'user']) === false
and $this->getUrl(1) !== 'login' and $this->getUrl(1) !== 'login'
and ($this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD') and ($this->isConnected() === false
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') or ($this->isConnected() === true
and $this->getUser('group') < self::GROUP_ADMIN and $this->getUser('group') < common::GROUP_ADMIN
) )
) )
) { ) {
@ -513,13 +441,16 @@ class core extends common
header('Location:' . helper::baseUrl() . 'maintenance'); header('Location:' . helper::baseUrl() . 'maintenance');
exit(); exit();
} }
// Check l'accès à la page // Check l'accès à la page
$access = null; $access = null;
if ($this->getData(['page', $this->getUrl(0)]) !== null) { if ($this->getData(['page', $this->getUrl(0)]) !== null) {
if ( if (
$this->getData(['page', $this->getUrl(0), 'group']) === self::GROUP_VISITOR $this->getData(['page', $this->getUrl(0), 'group']) === common::GROUP_VISITOR
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') or ($this->isConnected() === true
and $this->getUser('group') >= $this->getData(['page', $this->getUrl(0), 'group']) // 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']))
) )
) { ) {
$access = true; $access = true;
@ -533,14 +464,22 @@ class core extends common
// Empêcher l'accès aux pages désactivées par URL directe // Empêcher l'accès aux pages désactivées par URL directe
if ( if (
($this->getData(['page', $this->getUrl(0), 'disable']) === true ($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 ) or ($this->getData(['page', $this->getUrl(0), 'disable']) === true
and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') and $this->isConnected() === true
and $this->getUser('group') < self::GROUP_MODERATOR and $this->getUser('group') < common::GROUP_EDITOR
) )
) { ) {
$access = false; $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;
}
} }
/** /**
@ -553,6 +492,7 @@ class core extends common
*/ */
$accessInfo['userName'] = ''; $accessInfo['userName'] = '';
$accessInfo['pageId'] = ''; $accessInfo['pageId'] = '';
if ($this->getData(['user'])) {
foreach ($this->getData(['user']) as $userId => $userIds) { foreach ($this->getData(['user']) as $userId => $userIds) {
if (!is_null($this->getData(['user', $userId, 'accessUrl']))) { if (!is_null($this->getData(['user', $userId, 'accessUrl']))) {
$t = explode('/', $this->getData(['user', $userId, 'accessUrl'])); $t = explode('/', $this->getData(['user', $userId, 'accessUrl']));
@ -561,21 +501,23 @@ class core extends common
$this->getUser('id') && $this->getUser('id') &&
$userId !== $this->getUser('id') && $userId !== $this->getUser('id') &&
$this->getData(['user', $userId, 'accessUrl']) === $this->getUrl() && $this->getData(['user', $userId, 'accessUrl']) === $this->getUrl() &&
array_intersect($t, self::$accessList) && array_intersect($t, common::$concurrentAccess) &&
array_intersect($t, self::$accessExclude) !== false && //array_intersect($t, common::$accessExclude) !== false &&
time() < $this->getData(['user', $userId, 'accessTimer']) + self::ACCESS_TIMER time() < $this->getData(['user', $userId, 'accessTimer']) + common::ACCESS_TIMER
) { ) {
$access = false; $access = false;
$accessInfo['userName'] = $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']); $accessInfo['userName'] = $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']);
$accessInfo['pageId'] = end($t); $accessInfo['pageId'] = end($t);
} }
} }
}
// Accès concurrent stocke la page visitée // Accès concurrent stocke la page visitée
if ( if (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') $this->isConnected() === true
&& $this->getUser('id') && $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()]); $this->setData(['user', $this->getUser('id'), 'accessTimer', time()]);
} }
// Breadcrumb // Breadcrumb
@ -599,10 +541,10 @@ class core extends common
$inlineScript[] = $this->getData(['page', $this->getUrl(0), 'js']) === null ? '' : $this->getData(['page', $this->getUrl(0), 'js']); $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 // 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::$i18nContent) : ''; $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']); $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']); $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::$i18nContent) : ''; $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']); $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']); $inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']);
@ -620,7 +562,7 @@ class core extends common
$this->addOutput([ $this->addOutput([
'title' => $title, 'title' => $title,
'content' => $this->getPage($this->getUrl(0), self::$i18nContent), 'content' => $this->getPage($this->getUrl(0), common::$siteContent),
'metaDescription' => $this->getData(['page', $this->getUrl(0), 'metaDescription']), 'metaDescription' => $this->getData(['page', $this->getUrl(0), 'metaDescription']),
'metaTitle' => $this->getData(['page', $this->getUrl(0), 'metaTitle']), 'metaTitle' => $this->getData(['page', $this->getUrl(0), 'metaTitle']),
'typeMenu' => $this->getData(['page', $this->getUrl(0), 'typeMenu']), 'typeMenu' => $this->getData(['page', $this->getUrl(0), 'typeMenu']),
@ -646,7 +588,7 @@ class core extends common
: $this->getData(['page', $this->getUrl(0), 'metaDescription']); : $this->getData(['page', $this->getUrl(0), 'metaDescription']);
// Importe le CSS de la page principale // Importe le CSS de la page principale
$pageContent = $this->getPage($this->getUrl(0), self::$i18nContent); $pageContent = $this->getPage($this->getUrl(0), common::$siteContent);
$this->addOutput([ $this->addOutput([
'title' => $title, 'title' => $title,
@ -691,9 +633,10 @@ class core extends common
$output = $module->output; $output = $module->output;
// Check le groupe de l'utilisateur // Check le groupe de l'utilisateur
if ( if (
($module::$actions[$action] === self::GROUP_VISITOR ($module::$actions[$action] === common::GROUP_VISITOR
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') or ($this->isConnected() === true
and $this->getUser('group') >= $module::$actions[$action] and $this->getUser('group') >= $module::$actions[$action]
and $this->getUser('permission', $moduleId, $action)
) )
) )
and $output['access'] === true and $output['access'] === true
@ -703,10 +646,10 @@ class core extends common
foreach ($_POST as $postId => $postValue) { foreach ($_POST as $postId => $postValue) {
if (is_array($postValue)) { if (is_array($postValue)) {
foreach ($postValue as $subPostId => $subPostValue) { foreach ($postValue as $subPostId => $subPostValue) {
self::$inputBefore[$postId . '_' . $subPostId] = $subPostValue; common::$inputBefore[$postId . '_' . $subPostId] = $subPostValue;
} }
} else { } else {
self::$inputBefore[$postId] = $postValue; common::$inputBefore[$postId] = $postValue;
} }
} }
} }
@ -746,9 +689,9 @@ class core extends common
// Contenu par vue // Contenu par vue
elseif ($output['view']) { elseif ($output['view']) {
// Chemin en fonction d'un module du coeur ou d'un module // 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 // 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)) { if (file_exists($stylePath)) {
$this->addOutput([ $this->addOutput([
'style' => file_get_contents($stylePath) 'style' => file_get_contents($stylePath)
@ -761,7 +704,7 @@ class core extends common
} }
// JS // 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)) { if (file_exists($scriptPath)) {
ob_start(); ob_start();
include $scriptPath; include $scriptPath;
@ -770,7 +713,7 @@ class core extends common
]); ]);
} }
// Vue // 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)) { if (file_exists($viewPath)) {
ob_start(); ob_start();
include $viewPath; include $viewPath;
@ -779,7 +722,7 @@ class core extends common
$this->addOutput([ $this->addOutput([
'content' => ob_get_clean() . ($output['showPageContent'] ? $pageContent : '') 'content' => ob_get_clean() . ($output['showPageContent'] ? $pageContent : '')
]); ]);
} else if ($modpos === 'free') { } elseif ($modpos === 'free' && strstr($pageContent, '[MODULE]')) {
if (strstr($pageContent, '[MODULE]', true) === false) { if (strstr($pageContent, '[MODULE]', true) === false) {
$begin = strstr($pageContent, '[]', true); $begin = strstr($pageContent, '[]', true);
} else { } else {
@ -839,7 +782,7 @@ class core extends common
if ($accessInfo['userName']) { if ($accessInfo['userName']) {
$this->addOutput([ $this->addOutput([
'title' => 'Accès verrouillé', 'title' => 'Accès verrouillé',
'content' => template::speech(sprintf(helper::translate('La page %s est ouverte par l\'utilisateur %s'), $accessInfo['pageId'], $accessInfo['userName'])) '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 { } else {
@ -851,12 +794,35 @@ class core extends common
} else { } else {
$this->addOutput([ $this->addOutput([
'title' => 'Accès interdit', 'title' => 'Accès interdit',
'content' => template::speech(helper::translate('Vous n\'êtes pas autorisé à consulter cette page (erreur 403)')) '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'] === '') { } elseif ($this->output['content'] === '') {
http_response_code(404); http_response_code(404);
// Pour éviter une 404, bascule dans l'espace correct si la page existe dans cette langue.
// Parcourir les espaces
foreach (common::$languages as $langId => $value) {
;
if (
// l'espace existe
is_dir(common::DATA_DIR . $langId) &&
file_exists(common::DATA_DIR . $langId . '/page.json')
) {
// Lire les données des pages
$pagesId = json_decode(file_get_contents(common::DATA_DIR . $langId . '/page.json'), true);
if (
// La page existe
is_array($pagesId['page']) &&
array_key_exists($this->getUrl(0), $pagesId['page'])
) {
// Basculer
$_SESSION['ZWII_SITE_CONTENT'] = $langId;
header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
exit();
}
}
}
if ( if (
$this->getData(['locale', 'page404']) !== 'none' $this->getData(['locale', 'page404']) !== 'none'
and $this->getData(['page', $this->getData(['locale', 'page404'])]) and $this->getData(['page', $this->getData(['locale', 'page404'])])
@ -865,7 +831,7 @@ class core extends common
} else { } else {
$this->addOutput([ $this->addOutput([
'title' => 'Page indisponible', 'title' => 'Page indisponible',
'content' => template::speech(helper::translate('La page demandée n\'existe pas ou est introuvable (erreur 404)')) '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>')
]); ]);
} }
} }
@ -888,41 +854,43 @@ class core extends common
} }
switch ($this->output['display']) { switch ($this->output['display']) {
// Layout brut // Layout brut
case self::DISPLAY_RAW: case common::DISPLAY_RAW:
echo $this->output['content']; echo $this->output['content'];
break; break;
// Layout vide // Layout vide
case self::DISPLAY_LAYOUT_BLANK: case common::DISPLAY_LAYOUT_BLANK:
require 'core/layout/blank.php'; require 'core/layout/blank.php';
break; break;
// Affichage en JSON // Affichage en JSON
case self::DISPLAY_JSON: case common::DISPLAY_JSON:
header('Content-Type: application/json'); header('Content-Type: application/json');
echo json_encode($this->output['content']); echo json_encode($this->output['content']);
break; break;
// RSS feed // RSS feed
case self::DISPLAY_RSS: case common::DISPLAY_RSS:
header('Content-type: application/rss+xml; charset=UTF-8'); header('Content-type: application/rss+xml; charset=UTF-8');
echo $this->output['content']; echo $this->output['content'];
break; break;
// Layout allégé // Layout allégé
case self::DISPLAY_LAYOUT_LIGHT: case common::DISPLAY_LAYOUT_LIGHT:
ob_start(); ob_start();
require 'core/layout/light.php'; require 'core/layout/light.php';
// Supprime les espaces, les sauts de ligne, les tabulations et autres caractères inutiles $content = ob_get_clean();
$content = preg_replace('/[\t ]+/u', ' ', ob_get_clean());
// Convertit la chaîne en UTF-8 pour conserver les caractères accentués // Convertit la chaîne en UTF-8 pour conserver les caractères accentués
$content = mb_convert_encoding($content, 'UTF-8', 'UTF-8'); $content = mb_convert_encoding($content, 'UTF-8', 'UTF-8');
// Supprime les espaces, les sauts de ligne, les tabulations et autres caractères inutiles
$content = preg_replace('/[\t ]+/u', ' ', $content);
echo $content; echo $content;
break; break;
// Layout principal // Layout principal
case self::DISPLAY_LAYOUT_MAIN: case common::DISPLAY_LAYOUT_MAIN:
ob_start(); ob_start();
require 'core/layout/main.php'; require 'core/layout/main.php';
// Supprime les espaces, les sauts de ligne, les tabulations et autres caractères inutiles $content = ob_get_clean();
$content = preg_replace('/[\t ]+/u', ' ', ob_get_clean());
// Convertit la chaîne en UTF-8 pour conserver les caractères accentués // Convertit la chaîne en UTF-8 pour conserver les caractères accentués
$content = mb_convert_encoding($content, 'UTF-8', 'UTF-8'); $content = mb_convert_encoding($content, 'UTF-8', 'UTF-8');
// Supprime les espaces, les sauts de ligne, les tabulations et autres caractères inutiles
$content = preg_replace('/[\t ]+/u', ' ', $content);
echo $content; echo $content;
break; break;
} }

View File

@ -128,7 +128,17 @@ class SitemapGenerator
*/ */
private $sampleRobotsLines = [ private $sampleRobotsLines = [
"User-agent: *", "User-agent: *",
"Disallow: /",
"User-agent: Googlebot",
"Allow: /", "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 * @var array list of valid changefreq values according to the spec

View File

@ -93,19 +93,19 @@ class template
// Icône de l'opérateur et calcul du résultat // Icône de l'opérateur et calcul du résultat
switch ($operator) { switch ($operator) {
case 1: case 1:
$operator = template::ico('plus'); $operator = template::ico('plus', ['fontSize' => '2em;']);
$result = $firstNumber + $secondNumber; $result = $firstNumber + $secondNumber;
break; break;
case 2: case 2:
$operator = template::ico('minus'); $operator = template::ico('minus', ['fontSize' => '2em;']);
$result = $firstNumber - $secondNumber; $result = $firstNumber - $secondNumber;
break; break;
case 3: case 3:
$operator = template::ico('cancel'); $operator = template::ico('cancel', ['fontSize' => '2em;']);
$result = $firstNumber * $secondNumber; $result = $firstNumber * $secondNumber;
break; break;
case 4: case 4:
$operator = template::ico('divide'); $operator = template::ico('divide', ['fontSize' => '2em;']);
$limit2 = [10, 10, 6, 5, 4, 3, 2, 2, 2, 2]; $limit2 = [10, 10, 6, 5, 4, 3, 2, 2, 2, 2];
for ($i = 1; $i <= $firstNumber; $i++) { for ($i = 1; $i <= $firstNumber; $i++) {
$limit = $limit2[$i - 1]; $limit = $limit2[$i - 1];
@ -134,7 +134,7 @@ class template
// Label // Label
$html .= self::label( $html .= self::label(
$attributes['id'], $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" /> en chiffres ?', '<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'] 'help' => $attributes['help']
] ]
@ -224,7 +224,7 @@ class template
* Crée un champ date * Crée un champ date
* @param string $nameId Nom et id du champ * @param string $nameId Nom et id du champ
* @param array $attributes Attributs ($key => $value) * @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 * @return string
*/ */
public static function date($nameId, array $attributes = []) public static function date($nameId, array $attributes = [])
@ -244,17 +244,32 @@ class template
'placeholder' => '', 'placeholder' => '',
'readonly' => false, 'readonly' => false,
'value' => '', 'value' => '',
'type'=> 'date', 'type' => 'date',
], $attributes); ], $attributes);
// Traduction de l'aide et de l'étiquette // Traduction de l'aide et de l'étiquette
$attributes['label'] = helper::translate($attributes['label']); $attributes['label'] = helper::translate($attributes['label']);
$attributes['help'] = helper::translate($attributes['help']); $attributes['help'] = helper::translate($attributes['help']);
//$attributes['placeholder'] = helper::translate($attributes['placeholder']); //$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 // Sauvegarde des données en cas d'erreur
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) { if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
$attributes['value'] = common::$inputBefore[$attributes['id']]; $attributes['value'] = common::$inputBefore[$attributes['id']];
} else { } 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 // Début du wrapper
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">'; $html = '<div id="' . $attributes['id'] . 'Wrapper" class="inputWrapper ' . $attributes['classWrapper'] . '">';
@ -310,6 +325,7 @@ class template
'name' => $nameId, 'name' => $nameId,
'type' => 2, 'type' => 2,
'value' => '', 'value' => '',
'folder' => '',
'language' => 'fr_FR' 'language' => 'fr_FR'
], $attributes); ], $attributes);
// Traduction de l'aide et de l'étiquette // Traduction de l'aide et de l'étiquette
@ -352,13 +368,15 @@ class template
'&field_id=' . $attributes['id'] . '&field_id=' . $attributes['id'] .
'&type=' . $attributes['type'] . '&type=' . $attributes['type'] .
'&akey=' . md5_file(core::DATA_DIR . 'core.json') . '&akey=' . md5_file(core::DATA_DIR . 'core.json') .
// Ajoute le nom du dossier si la variable est passée
(empty($attributes['folder']) ? '&fldr=/': '&fldr=' . $attributes['folder']) .
($attributes['extensions'] ? '&extensions=' . $attributes['extensions'] : '') ($attributes['extensions'] ? '&extensions=' . $attributes['extensions'] : '')
. '" . '"
class="inputFile %s %s" class="inputFile %s %s"
%s %s
data-lity data-lity
> >
' . self::ico('upload', ['margin' => 'right']) . ' ' . self::ico('upload-cloud', ['margin' => 'right']) . '
<span class="inputFileLabel"></span> <span class="inputFileLabel"></span>
</a>', </a>',
$attributes['class'], $attributes['class'],
@ -397,7 +415,7 @@ class template
$html = '<form id="' . $id . '" method="post">'; $html = '<form id="' . $id . '" method="post">';
// Stock le token CSRF // Stock le token CSRF
$html .= self::hidden('csrf', [ $html .= self::hidden('csrf', [
'value' => $_SESSION['csrf'] 'value' => htmlentities($_SESSION['csrf'], ENT_QUOTES | ENT_HTML5, 'UTF-8')
]); ]);
// Retourne le html // Retourne le html
return $html; return $html;
@ -494,8 +512,8 @@ class template
$lang = $langId; $lang = $langId;
break; break;
case 'selected': case 'selected':
if (isset($_COOKIE['ZWII_CONTENT'])) { if (isset($_SESSION['ZWII_SITE_CONTENT'])) {
$lang = $_COOKIE['ZWII_CONTENT']; $lang = $_SESSION['ZWII_SITE_CONTENT'];
} else { } else {
$lang = 'fr_FR'; $lang = 'fr_FR';
} }
@ -686,15 +704,16 @@ class template
'label' => '', 'label' => '',
'name' => $nameId, 'name' => $nameId,
'selected' => '', 'selected' => '',
'fonts' => [] 'font' => [],
'multiple' => ''
], $attributes); ], $attributes);
// Traduction de l'aide et de l'étiquette // Traduction de l'aide et de l'étiquette
$attributes['label'] = helper::translate($attributes['label']); $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 // Stocker les fontes et remettre à zéro le tableau des fontes transmis pour éviter une erreur de sprintAttributes
if (empty($attributes['fonts']) === false) { if (empty($attributes['font']) === false) {
$fonts = $attributes['fonts']; $fonts = $attributes['font'];
$attributes['fonts'] = []; $attributes['font'] = [];
} }
// Sauvegarde des données en cas d'erreur // Sauvegarde des données en cas d'erreur
if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) { if ($attributes['before'] and array_key_exists($attributes['id'], common::$inputBefore)) {
@ -715,6 +734,11 @@ class template
$attributes['class'] .= ' notice'; $attributes['class'] .= ' notice';
} }
$html .= self::notice($attributes['id'], $notice); $html .= self::notice($attributes['id'], $notice);
// Attribut multiple
if ($attributes['multiple'] === true) {
echo "ppp";
$attributes['multiple'] = 'multiple';
}
// Début sélection // Début sélection
$html .= sprintf( $html .= sprintf(
'<select %s>', '<select %s>',
@ -744,6 +768,7 @@ class template
return $html; return $html;
} }
/** /**
* Crée une bulle de dialogue * Crée une bulle de dialogue
* @param string $text Texte de la bulle * @param string $text Texte de la bulle
@ -898,7 +923,7 @@ class template
$html .= self::notice($attributes['id'], $notice); $html .= self::notice($attributes['id'], $notice);
// Texte // Texte
$html .= sprintf( $html .= sprintf(
'<input type="' . $attributes['type']. '" %s>', '<input type="' . $attributes['type'] . '" %s>',
helper::sprintAttributes($attributes) helper::sprintAttributes($attributes)
); );
// Fin du wrapper // Fin du wrapper

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -216,12 +216,14 @@ core.start = function () {
// Variables des cookies // Variables des cookies
var getUrl = window.location; var getUrl = window.location;
var domain = "domain=" + getUrl.hostname + ";"; var domain = "domain=" + getUrl.hostname + ";";
var basePath = getUrl.pathname.substring(0, getUrl.pathname.lastIndexOf('/') + 1);
var path = "path=" + basePath + ";";
var e = new Date(); var e = new Date();
e.setFullYear(e.getFullYear() + 1); e.setFullYear(e.getFullYear() + 1);
var expires = "expires=" + e.toUTCString(); var expires = "expires=" + e.toUTCString() + ";";
// Stocke le cookie d'acceptation // 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;
}); });
@ -291,14 +293,14 @@ core.start = function () {
}); });
// Confirmation de mise à jour // Confirmation de mise à jour
$("#barUpdate").on("click", function () { $("#barUpdate").on("click", function () {
message = "<?php echo helper::translate('Mettre à jour') . ' ?';?>"; message = "<?php echo helper::translate('Mise à jour') . ' ?';?>";
return core.confirm(message, function () { return core.confirm(message, function () {
$(location).attr("href", $("#barUpdate").attr("href")); $(location).attr("href", $("#barUpdate").attr("href"));
}); });
}); });
// Confirmation de déconnexion // Confirmation de déconnexion
$("#barLogout").on("click", function () { $("#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 () { return core.confirm(message, function () {
$(location).attr("href", $("#barLogout").attr("href")); $(location).attr("href", $("#barLogout").attr("href"));
}); });
@ -462,7 +464,7 @@ $(document).ready(function () {
/** /**
* Chargement paresseux des images et des iframes * Chargement paresseux des images et des iframes
*/ */
$("img,picture,iframe").attr("loading", "lazy"); $("img").attr("loading", "lazy");
/** /**
* Effet accordéon * Effet accordéon
@ -532,14 +534,14 @@ $(document).ready(function () {
var langSelected = $(this).val(); var langSelected = $(this).val();
var langSelected = langSelected.split("/"); var langSelected = langSelected.split("/");
// Lit le cookie de langue // Lit le cookie de langue
var langCookie = getCookie('ZWII_CONTENT'); 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 // Découpe l'URL pour exclure le changement de page avec le thème
var url = window.location; var url = window.location;
var currentUrl = url.href.split("/"); var currentUrl = url.href.split("/");
// Change si différent, corrige le problème avec le thème et le rechargement de la langue. // Change si différent, corrige le problème avec le thème et le rechargement de la langue.
if ((currentUrl !== "?theme" || if ((currentUrl !== "?theme" ||
currentUrl !== "theme") && currentUrl !== "theme") &&
langSelected[6] !== langCookie langSelected[6] !== langSession
) { ) {
//$(location).attr("href", langUrl); //$(location).attr("href", langUrl);
var select = document.getElementById("barSelectLanguage"); var select = document.getElementById("barSelectLanguage");

File diff suppressed because it is too large Load Diff

View File

@ -9,8 +9,8 @@ if(version_compare(PHP_VERSION, '7.2.0', '<') ) {
} }
if ( version_compare(PHP_VERSION, '8.2.999', '>') ) { if ( version_compare(PHP_VERSION, '8.3.999', '>') ) {
exit('PHP 8.2 pas encore supporté, installez PHP 7.n ou PHP 8.1.n - PHP 8.2 not yet supported, install PHP 7.n or PHP 8.1.n'); exit('PHP 8.3 pas encore supporté, installez PHP 7.n ou PHP 8.1.n - PHP 8.3 not yet supported, install PHP 7.n or PHP 8.1.n');
} }
/** /**
@ -34,11 +34,11 @@ $b = false;
foreach ($e as $k => $v) { foreach ($e as $k => $v) {
if (array_search($v,$m) === false) { if (array_search($v,$m) === false) {
$b = true; $b = true;
echo '<pre><p>Module ' . $v . ' manquant - Module ' . $v . ' missing.</p></pre>'; echo '<pre><p>Module PHP : ' . $v . ' manquant - Module PHP ' . $v . ' missing.</p></pre>';
} }
} }
if ($b) if ($b)
exit('<pre><p>ZwiiCMS ne peut pas démarrer ; activez les extensions requises - ZwiiCMS cannot start, enabled missing extensions.</p></pre>'); exit('<pre><p>ZwiiCMS ne peut pas démarrer ; activez les extensions requises dans PHP.ini- ZwiiCMS cannot start, enabled PHP missing extensions into PHP.ini</p></pre>');
/** /**
* Contrôle les htacess * Contrôle les htacess
*/ */
@ -48,9 +48,9 @@ $d = [
'site/data/', 'site/data/',
'site/backup/', 'site/backup/',
'site/tmp/', 'site/tmp/',
'site/i18n/' // 'site/i18n/', pas contrôler pour éviter les pbs de mise à jour
]; ];
foreach ($d as $key) { foreach ($d as $key) {
if (file_exists($key . '.htaccess') === false) if (file_exists($key . '.htaccess') === false)
exit('<pre>ZwiiCMS ne peut pas démarrer, le fichier ' .$key . '.htaccess est manquant.<br />ZwiiCMS cannot start, file ' . $key . '.htaccess is missing manquant.</pre>' ); exit('<pre>ZwiiCMS ne peut pas démarrer, le fichier ' .$key . '.htaccess est manquant.<br />ZwiiCMS cannot start, file ' . $key . '.htaccess is missing.</pre>' );
} }

View File

@ -5,10 +5,12 @@
* */ * */
if (file_exists('site/data/core.json')) { if (file_exists('site/data/core.json')) {
$version = json_decode(file_get_contents('site/data/core.json'), true); $core = json_decode(file_get_contents('site/data/core.json'), true);
$version = $core['core']['dataVersion'];
// Avant version 12.0.00 // Avant version 12.0.00
if ($version['core']['dataVersion'] < 12000) { if (
$version < 12000
) {
// Correspondance pour les dossiers de langue à convertir // Correspondance pour les dossiers de langue à convertir
$languages = [ $languages = [
'fr' => 'fr_FR', 'fr' => 'fr_FR',
@ -24,7 +26,27 @@ if (file_exists('site/data/core.json')) {
$end = rename('site/data/' . $key, 'site/data/' . $value); $end = rename('site/data/' . $key, 'site/data/' . $value);
} }
} }
sleep(1); sleep(1);
} }
}
// Renomme les bases de données
if (
$version < 12400
) {
// Renommage les fichiers de données au pluriel
$t = [
'site/data/languages.json' => 'site/data/language.json',
'site/data/fonts.json' => 'site/data/font.json'
];
foreach ($t as $k => $v) {
if (file_exists($k)) {
$d = file_get_contents($k);
$d = str_replace('"' . basename($k, '.json') . '"' , '"' . basename($v, '.json') . '"', $d);
file_put_contents($v, $d);
unlink($k);
}
}
}
}

View File

@ -3,7 +3,11 @@
/** /**
* Mises à jour suivant les versions de Zwii * Mises à jour suivant les versions de Zwii
*/ */
if ($this->getData(['core', 'dataVersion']) < 9227) {
// Pas d'installation depuis une version inférieur
if (
$this->getData(['core', 'dataVersion']) < 9227
) {
// Arrêt du script // Arrêt du script
exit('ZwiiCMS version 12 est incompatible avec la base de données installée. L\'installation d\'une version intermédiaire 10 ou 11 est nécessaire.'); exit('ZwiiCMS version 12 est incompatible avec la base de données installée. L\'installation d\'une version intermédiaire 10 ou 11 est nécessaire.');
} }
@ -14,15 +18,15 @@ if ($this->getData(['core', 'dataVersion']) < 10000) {
//---------------------------------------- //----------------------------------------
// Mettre à jour les données des galeries // Mettre à jour les données des galeries
$pageList = array(); $hierarchy = array();
foreach ($this->getHierarchy(null, null, null) as $parentKey => $parentValue) { foreach ($this->getHierarchy() as $parentKey => $parentValue) {
$pageList[] = $parentKey; $hierarchy[] = $parentKey;
foreach ($parentValue as $childKey) { foreach ($parentValue as $childKey) {
$pageList[] = $childKey; $hierarchy[] = $childKey;
} }
} }
// Mise à jour des données pour la galerie v2 // Mise à jour des données pour la galerie v2
foreach ($pageList as $parentKey => $parent) { foreach ($hierarchy as $parentKey => $parent) {
//La page a une galerie //La page a une galerie
if ($this->getData(['page', $parent, 'moduleId']) === 'gallery') { if ($this->getData(['page', $parent, 'moduleId']) === 'gallery') {
// Parcourir les dossiers de la galerie // Parcourir les dossiers de la galerie
@ -131,7 +135,7 @@ if ($this->getData(['core', 'dataVersion']) < 10200) {
} }
// Créer les en-têtes du journal // Créer les en-têtes du journal
$d = 'Date;Heure;IP;Id;Action' . PHP_EOL; $d = 'Date;Heure;IP;Id;Action' . PHP_EOL;
file_put_contents(self::DATA_DIR . 'journal.log', $d); $this->secure_file_put_contents(self::DATA_DIR . 'journal.log', $d);
// Init préservation htaccess // Init préservation htaccess
$this->setData(['config', 'autoUpdateHtaccess', false]); $this->setData(['config', 'autoUpdateHtaccess', false]);
// Options de barre de membre simple // Options de barre de membre simple
@ -175,15 +179,15 @@ if ($this->getData(['core', 'dataVersion']) < 10300) {
$this->setData(['config', 'searchPageId', '']); $this->setData(['config', 'searchPageId', '']);
// Mettre à jour les données des galeries // Mettre à jour les données des galeries
$pageList = array(); foreach ($this->getHierarchy(null, null, null) as $parentKey => $parentValue) { $hierarchy = array(); foreach ($this->getHierarchy() as $parentKey => $parentValue) {
$pageList[] = $parentKey; $hierarchy[] = $parentKey;
foreach ($parentValue as $childKey) { foreach ($parentValue as $childKey) {
$pageList[] = $childKey; $hierarchy[] = $childKey;
} }
} }
// Mise à jour des données de thème de la galerie // Mise à jour des données de thème de la galerie
// Les données de thème sont communes au site // Les données de thème sont communes au site
foreach ($pageList as $parentKey => $parent) { foreach ($hierarchy as $parentKey => $parent) {
//La page a une galerie //La page a une galerie
if ($this->getData(['page', $parent, 'moduleId']) === 'gallery') { if ($this->getData(['page', $parent, 'moduleId']) === 'gallery') {
foreach ($this->getData(['module', $parent]) as $galleryKey => $galleryItem) { foreach ($this->getData(['module', $parent]) as $galleryKey => $galleryItem) {
@ -235,15 +239,15 @@ if ($this->getData(['core', 'dataVersion']) < 10304) {
// Version 10.3.06 // Version 10.3.06
if ($this->getData(['core', 'dataVersion']) < 10306) { if ($this->getData(['core', 'dataVersion']) < 10306) {
// Liste des pages // Liste des pages
$pageList = array(); $hierarchy = array();
foreach ($this->getHierarchy(null, null, null) as $parentKey => $parentValue) { foreach ($this->getHierarchy() as $parentKey => $parentValue) {
$pageList[] = $parentKey; $hierarchy[] = $parentKey;
foreach ($parentValue as $childKey) { foreach ($parentValue as $childKey) {
$pageList[] = $childKey; $hierarchy[] = $childKey;
} }
} }
// Mettre à jour les données des blogs les articles sont dans posts // Mettre à jour les données des blogs les articles sont dans posts
foreach ($pageList as $parentKey => $parent) { foreach ($hierarchy as $parentKey => $parent) {
//La page a un blog //La page a un blog
if ($this->getData(['page', $parent, 'moduleId']) === 'blog') { if ($this->getData(['page', $parent, 'moduleId']) === 'blog') {
if (is_array($this->getData(['module', $parent]))) { if (is_array($this->getData(['module', $parent]))) {
@ -258,7 +262,7 @@ if ($this->getData(['core', 'dataVersion']) < 10306) {
} }
} }
} }
foreach ($pageList as $parentKey => $parent) { foreach ($hierarchy as $parentKey => $parent) {
//La page a une news //La page a une news
if ($this->getData(['page', $parent, 'moduleId']) === 'news') { if ($this->getData(['page', $parent, 'moduleId']) === 'news') {
if (is_array($this->getData(['module', $parent]))) { if (is_array($this->getData(['module', $parent]))) {
@ -293,16 +297,16 @@ if ($this->getData(['core', 'dataVersion']) < 10400) {
// Ajouter les champs de blog v3 // Ajouter les champs de blog v3
// Liste des pages dans pageList // Liste des pages dans pageList
$pageList = array(); $hierarchy = array();
foreach ($this->getHierarchy(null, null, null) as $parentKey => $parentValue) { foreach ($this->getHierarchy() as $parentKey => $parentValue) {
$pageList[] = $parentKey; $hierarchy[] = $parentKey;
foreach ($parentValue as $childKey) { foreach ($parentValue as $childKey) {
$pageList[] = $childKey; $hierarchy[] = $childKey;
} }
} }
// Parcourir pageList et rechercher les modules de blog // Parcourir pageList et rechercher les modules de blog
foreach ($pageList as $parentKey => $parent) { foreach ($hierarchy as $parentKey => $parent) {
//La page est un blog //La page est un blog
if ($this->getData(['page', $parent, 'moduleId']) === 'blog') { if ($this->getData(['page', $parent, 'moduleId']) === 'blog') {
$articleIds = array_keys(helper::arrayColumn($this->getData(['module', $parent, 'posts']), 'publishedOn', 'SORT_DESC')); $articleIds = array_keys(helper::arrayColumn($this->getData(['module', $parent, 'posts']), 'publishedOn', 'SORT_DESC'));
@ -384,15 +388,15 @@ if ($this->getData(['core', 'dataVersion']) < 10600) {
// Mise à jour des données des modules autonomes // Mise à jour des données des modules autonomes
// Liste des pages dans pageList // Liste des pages dans pageList
$pageList = array(); $hierarchy = array();
foreach ($this->getHierarchy(null, null, null) as $parentKey => $parentValue) { foreach ($this->getHierarchy() as $parentKey => $parentValue) {
$pageList[] = $parentKey; $hierarchy[] = $parentKey;
foreach ($parentValue as $childKey) { foreach ($parentValue as $childKey) {
$pageList[] = $childKey; $hierarchy[] = $childKey;
} }
} }
// Parcourir pageList et rechercher les modules au CSS autonomes // Parcourir pageList et rechercher les modules au CSS autonomes
foreach ($pageList as $parentKey => $parent) { foreach ($hierarchy as $parentKey => $parent) {
if ( if (
$this->getData(['page', $parent, 'moduleId']) === 'search' $this->getData(['page', $parent, 'moduleId']) === 'search'
|| $this->getData(['page', $parent, 'moduleId']) === 'gallery' || $this->getData(['page', $parent, 'moduleId']) === 'gallery'
@ -442,20 +446,20 @@ if ($this->getData(['core', 'dataVersion']) < 11000) {
// Externaliser les contenus des pages // Externaliser les contenus des pages
// Liste des pages dans pageList // Liste des pages dans pageList
$pageList = array(); $hierarchy = array();
// Creation du contenu de la page // Creation du contenu de la page
if (!is_dir(self::DATA_DIR . self::$i18nContent . '/content')) { if (!is_dir(self::DATA_DIR . self::$siteContent . '/content')) {
mkdir(self::DATA_DIR . self::$i18nContent . '/content', 0755); mkdir(self::DATA_DIR . self::$siteContent . '/content', 0755);
} }
foreach ($this->getHierarchy(null, null, null) as $parentKey => $parentValue) { foreach ($this->getHierarchy() as $parentKey => $parentValue) {
$pageList[] = $parentKey; $hierarchy[] = $parentKey;
foreach ($parentValue as $childKey) { foreach ($parentValue as $childKey) {
$pageList[] = $childKey; $hierarchy[] = $childKey;
} }
} }
foreach ($pageList as $parentKey => $parent) { foreach ($hierarchy as $parentKey => $parent) {
$content = $this->getData(['page', $parent, 'content']); $content = $this->getData(['page', $parent, 'content']);
//file_put_contents(self::DATA_DIR . self::$i18nContent . '/content/' . $parent . '.html', $content); //$this->secure_file_put_contents(self::DATA_DIR . self::$siteContent . '/content/' . $parent . '.html', $content);
$this->setPage($parent, $content, 'fr'); $this->setPage($parent, $content, 'fr');
$this->setData(['page', $parent, 'content', $parent . '.html']); $this->setData(['page', $parent, 'content', $parent . '.html']);
} }
@ -505,13 +509,13 @@ if ($this->getData(['core', 'dataVersion']) < 11200) {
$this->setData(['config', 'connect', 'captchaType', 'alpha']); $this->setData(['config', 'connect', 'captchaType', 'alpha']);
// Ajout de la variable shortTitle basée sur Title // Ajout de la variable shortTitle basée sur Title
foreach ($this->getHierarchy(null, null, null) as $parentKey => $parentValue) { foreach ($this->getHierarchy() as $parentKey => $parentValue) {
$pageList[] = $parentKey; $hierarchy[] = $parentKey;
foreach ($parentValue as $childKey) { foreach ($parentValue as $childKey) {
$pageList[] = $childKey; $hierarchy[] = $childKey;
} }
} }
foreach ($pageList as $parentKey => $parent) { foreach ($hierarchy as $parentKey => $parent) {
$this->setData(['page', $parent, 'shortTitle', $this->getData(['page', $parent, 'title'])]); $this->setData(['page', $parent, 'shortTitle', $this->getData(['page', $parent, 'title'])]);
} }
@ -569,8 +573,8 @@ if ($this->getData(['core', 'dataVersion']) < 11203) {
$c3 = 0; $c3 = 0;
$success = false; $success = false;
// Boucler sur les pages // Boucler sur les pages
foreach ($this->getHierarchy(null, null, null) as $parentId => $childIds) { foreach ($this->getHierarchy() as $parentId => $childIds) {
$content = $this->getPage($parentId, self::$i18nContent); $content = $this->getPage($parentId, self::$siteContent);
$titre = $this->getData(['page', $parentId, 'title']); $titre = $this->getData(['page', $parentId, 'title']);
$content = $titre . ' ' . $content; $content = $titre . ' ' . $content;
$replace = str_replace('href="' . $old, 'href="' . $new, stripslashes($content), $c1); $replace = str_replace('href="' . $old, 'href="' . $new, stripslashes($content), $c1);
@ -578,17 +582,17 @@ if ($this->getData(['core', 'dataVersion']) < 11203) {
if ($c1 > 0 || $c2 > 0) { if ($c1 > 0 || $c2 > 0) {
$success = true; $success = true;
$this->setPage($parentId, $replace, self::$i18nContent); $this->setPage($parentId, $replace, self::$siteContent);
$c3 += $c1 + $c2; $c3 += $c1 + $c2;
} }
foreach ($childIds as $childId) { foreach ($childIds as $childId) {
$content = $this->getPage($childId, self::$i18nContent); $content = $this->getPage($childId, self::$siteContent);
$content = $titre . ' ' . $content; $content = $titre . ' ' . $content;
$replace = str_replace('href="' . $old, 'href="' . $new, stripslashes($content), $c1); $replace = str_replace('href="' . $old, 'href="' . $new, stripslashes($content), $c1);
$replace = str_replace('src="' . $old, 'src="' . $new, stripslashes($replace), $c2); $replace = str_replace('src="' . $old, 'src="' . $new, stripslashes($replace), $c2);
if ($c1 > 0 || $c2 > 0) { if ($c1 > 0 || $c2 > 0) {
$success = true; $success = true;
$this->setPage($childId, $replace, self::$i18nContent); $this->setPage($childId, $replace, self::$siteContent);
$c3 += $c1 + $c2; $c3 += $c1 + $c2;
} }
} }
@ -665,13 +669,13 @@ if ($this->getData(['core', 'dataVersion']) < 11300) {
if ($this->getData(['core', 'dataVersion']) < 11303) { if ($this->getData(['core', 'dataVersion']) < 11303) {
// Ajout de la variable shortTitle basée sur Title // Ajout de la variable shortTitle basée sur Title
foreach ($this->getHierarchy(null, null, null) as $parentKey => $parentValue) { foreach ($this->getHierarchy() as $parentKey => $parentValue) {
$pageList[] = $parentKey; $hierarchy[] = $parentKey;
foreach ($parentValue as $childKey) { foreach ($parentValue as $childKey) {
$pageList[] = $childKey; $hierarchy[] = $childKey;
} }
} }
foreach ($pageList as $parentKey => $parent) { foreach ($hierarchy as $parentKey => $parent) {
$this->setData(['page', $parent, 'extraPosition', false]); $this->setData(['page', $parent, 'extraPosition', false]);
} }
@ -684,10 +688,10 @@ if ($this->getData(['core', 'dataVersion']) < 11303) {
if ($this->getData(['core', 'dataVersion']) < 11306) { if ($this->getData(['core', 'dataVersion']) < 11306) {
// Supprime les fontes déclarées en double par la version précédentes // Supprime les fontes déclarées en double par la version précédentes
$files = $this->getData(['fonts', 'files']); $files = $this->getData(['font', 'files']);
foreach ($files as $fontId => $fontFile) { foreach ($files as $fontId => $fontFile) {
if (!is_null($this->getData(['fonts', 'imported', $fontId]))) { if (!is_null($this->getData(['font', 'imported', $fontId]))) {
$this->deleteData(['fonts', 'imported', $fontId]); $this->deleteData(['font', 'imported', $fontId]);
} }
} }
// Mise à jour // Mise à jour
@ -699,7 +703,7 @@ if ($this->getData(['core', 'dataVersion']) < 11400) {
// Effacer le dossier // Effacer le dossier
if (is_dir('core/module/addon')) { if (is_dir('core/module/addon')) {
$this->removeDir('core/module/addon'); $this->deleteDir('core/module/addon');
} }
@ -797,7 +801,9 @@ if ($this->getData(['core', 'dataVersion']) < 11400) {
]; ];
// Conversion des fontes locales // Conversion des fontes locales
$files = $this->getData(['fonts', 'files']);
$files = $this->getData(['font', 'files']);
if (is_array($files)) { if (is_array($files)) {
foreach ($files as $fontId => $fontName) { foreach ($files as $fontId => $fontName) {
if ( if (
@ -805,7 +811,7 @@ if ($this->getData(['core', 'dataVersion']) < 11400) {
&& file_exists(self::DATA_DIR . 'fonts/' . $fontName) && file_exists(self::DATA_DIR . 'fonts/' . $fontName)
) { ) {
$this->setData([ $this->setData([
'fonts', 'font',
'files', 'files',
$fontId, $fontId,
[ [
@ -819,12 +825,12 @@ if ($this->getData(['core', 'dataVersion']) < 11400) {
} }
// Consersion des fontes importées // Consersion des fontes importées
$imported = $this->getData(['fonts', 'imported']); $imported = $this->getData(['font', 'imported']);
if (is_array($imported)) { if (is_array($imported)) {
foreach ($imported as $fontId => $fontUrl) { foreach ($imported as $fontId => $fontUrl) {
if (gettype($fontUrl) === 'string') { if (gettype($fontUrl) === 'string') {
$this->setData([ $this->setData([
'fonts', 'font',
'imported', 'imported',
$fontId, $fontId,
[ [
@ -839,7 +845,7 @@ if ($this->getData(['core', 'dataVersion']) < 11400) {
// Importation des fontes exemples // Importation des fontes exemples
$template = $fonts; $template = $fonts;
foreach ($template as $fontId => $fontValue) { foreach ($template as $fontId => $fontValue) {
$this->setData(['fonts', 'imported', $fontId, $fontValue]); $this->setData(['font', 'imported', $fontId, $fontValue]);
} }
// Redirection des pages d'administration vers la bannière de connexion // Redirection des pages d'administration vers la bannière de connexion
@ -897,10 +903,10 @@ if ($this->getData(['core', 'dataVersion']) < 12000) {
// Supprimer les fichier associés // Supprimer les fichier associés
if (is_dir('core/module/translate/ressource')) { if (is_dir('core/module/translate/ressource')) {
$this->removeDir('core/module/translate/ressource'); $this->deleteDir('core/module/translate/ressource');
} }
if (is_dir('core/vendor/i18n/css')) { if (is_dir('core/vendor/i18n/css')) {
$this->removeDir('core/vendor/i18n/css'); $this->deleteDir('core/vendor/i18n/css');
} }
if (file_exists('core/vendor/i18n/inc.json')) { if (file_exists('core/vendor/i18n/inc.json')) {
unlink('core/vendor/i18n/inc.json'); unlink('core/vendor/i18n/inc.json');
@ -935,7 +941,7 @@ if ($this->getData(['core', 'dataVersion']) < 12301) {
// Nettoyage de flatPickr // Nettoyage de flatPickr
if (is_dir('core/vendor/flatpickr')) { if (is_dir('core/vendor/flatpickr')) {
$this->removeDir('core/vendor/flatpickr'); $this->deleteDir('core/vendor/flatpickr');
} }
// email reply // email reply
@ -945,3 +951,168 @@ if ($this->getData(['core', 'dataVersion']) < 12301) {
// Mise à jour // Mise à jour
$this->setData(['core', 'dataVersion', 12301]); $this->setData(['core', 'dataVersion', 12301]);
} }
// Version 12.3.08
if ($this->getData(['core', 'dataVersion']) < 12308) {
// Langue par défaut
$l = [
'fr_FR' => 'Français',
'en_EN' => 'English',
'es' => 'Español',
];
foreach ($l as $key => $value) {
if (is_dir(self::DATA_DIR . $key)) {
touch(self::DATA_DIR . $key . '/.default');
break;
}
}
// Mise à jour
$this->setData(['core', 'dataVersion', 12308]);
}
// Version 12.3.09
if ($this->getData(['core', 'dataVersion']) < 12309) {
// Mettre à jour les locales
foreach (self::$languages as $key => $value) {
// tableau des langues installées
if (is_dir(self::DATA_DIR . $key)) {
$d = json_decode(file_get_contents(self::DATA_DIR . $key . '/locale.json'), true);
$d = array_merge($d['locale'], ['poweredPageLabel' => 'Motorisé par']);
$t['locale'] = $d;
$this->secure_file_put_contents(self::DATA_DIR . $key . '/locale.json', $t);
}
}
// Mise à jour
$this->setData(['core', 'dataVersion', 12309]);
}
// Version 13.0.00
if ($this->getData(['core', 'dataVersion']) < 13000) {
// Nettoyage du dossier de langue d'installation'
if (file_exists('core/vendor/tinymce/langs/langs.zip'))
unlink('core/vendor/tinymce/langs/langs.zip');
if (file_exists('core/module/install/ressource/i18n/de.json'))
unlink('core/module/install/ressource/i18n/de.json');
if (file_exists('core/module/install/ressource/i18n/it.json'))
unlink('core/module/install/ressource/i18n/it.json');
if (file_exists('core/module/install/ressource/i18n/pt_PT.json'))
unlink('core/module/install/ressource/i18n/pt_PT.json');
if (file_exists('core/module/install/ressource/i18n/gr_GR.json'))
unlink('core/module/install/ressource/i18n/gr_GR.json');
// Création du dossier partage pour les nouveaux droits
if (!is_dir(self::FILE_DIR . 'source/partage')) {
mkdir(self::FILE_DIR . 'source/partage');
}
// Efface le dossier translate
if (is_dir('core/module/translate')) {
$this->deleteDir('core/module/translate');
}
// Renomme le fichier et le dossier des fontes
if (file_exists(self::DATA_DIR . 'fonts/fonts.html')) {
rename(self::DATA_DIR . 'fonts/fonts.html', self::DATA_DIR . 'fonts/font.html');
}
if (is_dir(self::DATA_DIR . 'fonts')) {
rename(self::DATA_DIR . 'fonts', self::DATA_DIR . 'font');
}
// Ajouter le prénom comme pseudo et le pseudo comme signature
foreach ($this->getData(['user']) as $userId => $userIds) {
switch ($this->getData(['user', $userId, 'group'])) {
case '1':
case '2':
$this->setData(['user', $userId, 'profil', 1]);
break;
default:
$this->setData(['user', $userId, 'profil', 0]);
break;
}
}
// Récupérer la liste de toutes les pages dans toutes langues
$hierarchy = array();
$languages = array();
// Tableau des langues non installées
foreach (self::$languages as $key => $value) {
if (is_dir(self::DATA_DIR . $key))
$languages[] = $key;
foreach ($this->getHierarchy() as $parentKey => $parentValue) {
$hierarchy[] = $parentKey;
foreach ($parentValue as $childKey) {
$hierarchy[] = $childKey;
}
}
}
// Mise à jour des pages, le profil est mis à 0 pour les groupes sans profil et 1 pour es groupes avec profil
$currentlanguage = self::$siteContent;
foreach ($languages as $langId) {
foreach ($hierarchy as $parentKey => $parent) {
switch ($this->getData(['page', $parent, 'group'])) {
case 1:
case 2:
$this->setData(['page', $parent, 'profil', 1]);
break;
default:
$this->setData(['page', $parent, 'profil', 0]);
break;
}
}
}
$_SESSION['ZWII_SITE_CONTENT'] = $currentlanguage;
// Supprime la clé OpenOgraph
$this->deleteData(['config', 'seo', 'keyApi']);
// Mise à jour
$this->setData(['core', 'dataVersion', 13000]);
}
// Version 13.0.05
if ($this->getData(['core', 'dataVersion']) < 13005) {
if (is_dir('core/module/plugin/view/dataImport')) {
$this->deleteDir('core/module/plugin/view/dataImport');
}
if (file_exists('core/module/plugin/view/index/index.js.php')) {
unlink('core/module/plugin/view/index/index.js.php');
}
// Installe l'adresse d'envoi si non spécifiée
if (empty($this->getData(['config', 'smtp', 'from']))) {
$this->setData(['config', 'smtp', 'from', 'no-reply@localhost']);
}
// Fixe la taille de l'administration identique à la taille de site
$size = $this->getData(['theme', 'site', 'width']);
$this->setData(['admin', 'width', $size]);
// Ancienne déclaration oubliée !!
if ($this->getData(['admin', 'backgroundColorButtonHelp']) === null) {
$this->setData(['admin', 'backgroundColorButtonHelp', 'rgba(255, 153, 0, 1)']);
}
// Mise à jour
$this->setData(['core', 'dataVersion', 13005]);
}
// Version 13.1.01
if ($this->getData(['core', 'dataVersion']) < 13101) {
// Supprime le choix du thème à l'installation
if (is_dir('core/module/install/ressource/themes')) {
$this->deleteDir('core/module/install/ressource/themes') ;
}
// Mise à jour
$this->setData(['core', 'dataVersion', 13101]);
}

View File

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

View File

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

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -951,6 +951,38 @@ footer #footerSocials .zwiico-github:hover {
background: #000; background: #000;
} }
footer #footerSocials .zwiico-reddit {
background: #FF4500;
}
footer #footerSocials .zwiico-reddit:hover {
background: #D23311;
}
footer #footerSocials .zwiico-steam {
background: #171A21;
}
footer #footerSocials .zwiico-steam:hover {
background: #0F1318;
}
footer #footerSocials .zwiico-vimeo {
background: #162221;
}
footer #footerSocials .zwiico-vimeo:hover {
background: #121B1E;
}
footer #footerSocials .zwiico-twitch {
background: #9146FF;
}
footer #footerSocials .zwiico-twitch:hover {
background: #703CEC;
}
/* Bulle de dialogue */ /* Bulle de dialogue */
@ -971,9 +1003,10 @@ footer #footerSocials .zwiico-github:hover {
max-width: 500px; max-width: 500px;
width: 100%; width: 100%;
margin: 16px auto; margin: 16px auto;
text-align: left; text-align: center;
border-radius: 2px; border-radius: 2px;
transition: background-color .3s ease-out; transition: background-color .3s ease-out;
z-index: 100;
} }
.speechBubble:before { .speechBubble:before {
@ -1786,4 +1819,7 @@ th.col12 {
.bannerDisplay { .bannerDisplay {
display: none; display: none;
} }
header {
background-size: cover !important;
}
} }

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -18,6 +18,14 @@
/* Site */ /* Site */
#site { #site {
max-width: 600px !important; max-width: 600px !important;
border-radius: 5px !important;
}
#site > section:not(.message),
input[type='password'], input[type='text']
{
background-color: rgba(255, 255, 255, 1) !important;
color: rgba(33, 34, 35, 1) !important;
} }
section { section {

View File

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

View File

@ -1,8 +1,8 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?php echo substr(self::$i18nContent, 0, 2);?>"> <html xmlns="http://www.w3.org/1999/xhtml" lang="<?php echo substr(self::$siteContent, 0, 2);?>">
<head> <head>
<meta charset="utf-8"> <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 name="viewport" content="width=device-width">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="x-apple-disable-message-reformatting"> <meta name="x-apple-disable-message-reformatting">

View File

@ -1,8 +1,9 @@
<!DOCTYPE html> <!DOCTYPE html>
<html prefix="og: http://ogp.me/ns#" lang="<?php echo substr(self::$i18nContent, 0, 2); ?>"> <html prefix="og: http://ogp.me/ns#" lang="<?php echo substr(self::$siteContent, 0, 2); ?>">
<head> <head>
<meta charset="UTF-8"> <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 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="generator" content="ZiiCMS https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
@ -13,15 +14,23 @@
<?php $layout->showFavicon(); ?> <?php $layout->showFavicon(); ?>
<?php $layout->showVendor(); ?> <?php $layout->showVendor(); ?>
<?php $layout->showFonts(); ?> <?php $layout->showFonts(); ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/common.css?<?php echo md5_file('core/layout/common.css'); ?>"> <?php if (file_exists(self::DATA_DIR . 'font/font.css')): ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>theme.css?<?php echo md5_file(self::DATA_DIR . 'theme.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'); ?>">
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>custom.css?<?php echo md5_file(self::DATA_DIR . 'custom.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; ?>theme.css?<?php echo md5_file(self::DATA_DIR . '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'); ?>">
<!-- Détection RSS --> <!-- Détection RSS -->
<?php if (($this->getData(['page', $this->getUrl(0), 'moduleId']) === 'blog' <?php if (
($this->getData(['page', $this->getUrl(0), 'moduleId']) === 'blog'
or $this->getData(['page', $this->getUrl(0), 'moduleId']) === 'news') or $this->getData(['page', $this->getUrl(0), 'moduleId']) === 'news')
and $this->getData(['module', $this->getUrl(0), 'config', 'feeds']) === TRUE and $this->getData(['module', $this->getUrl(0), 'config', 'feeds']) === TRUE
) : ?> ): ?>
<link rel="alternate" type="application/rss+xml" href="'<?php echo helper::baseUrl() . $this->getUrl(0) . '/rss'; ?>" title="fLUX rss"> <link rel="alternate" type="application/rss+xml"
href="'<?php echo helper::baseUrl() . $this->getUrl(0) . '/rss'; ?>" title="fLUX rss">
<?php endif; ?> <?php endif; ?>
<?php $layout->showStyle(); ?> <?php $layout->showStyle(); ?>
<?php $layout->showInlineStyle(); ?> <?php $layout->showInlineStyle(); ?>
@ -30,21 +39,22 @@
include(self::DATA_DIR . 'head.inc.html'); include(self::DATA_DIR . 'head.inc.html');
} ?> } ?>
</head> </head>
<body> <body>
<!-- Barre d'administration --> <!-- Barre d'administration -->
<?php if ($this->getUser('group') > self::GROUP_MEMBER) : ?> <?php if ($this->getUser('group') > self::GROUP_MEMBER): ?>
<?php $layout->showBar(); ?> <?php $layout->showBar(); ?>
<?php endif; ?> <?php endif; ?>
<!-- Notifications --> <!-- Notifications -->
<?php $layout->showNotification(); ?> <?php $layout->showNotification(); ?>
<!-- Menu dans le fond du site avant la bannière --> <!-- Menu dans le fond du site avant la bannière -->
<?php if ($this->getData(['theme', 'menu', 'position']) === 'body-first' || $this->getData(['theme', 'menu', 'position']) === 'top') : ?> <?php if ($this->getData(['theme', 'menu', 'position']) === 'body-first' || $this->getData(['theme', 'menu', 'position']) === 'top'): ?>
<!-- Détermine si le menu est fixe en haut de page lorsque l'utilisateur n'est pas connecté --> <!-- Détermine si le menu est fixe en haut de page lorsque l'utilisateur n'est pas connecté -->
<?php <?php
if ( if (
$this->getData(['theme', 'menu', 'position']) === 'top' $this->getData(['theme', 'menu', 'position']) === 'top'
and $this->getData(['theme', 'menu', 'fixed']) === true 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 and $this->getUser('group') > self::GROUP_MEMBER
) { ) {
echo '<nav id="navfixedconnected" >'; echo '<nav id="navfixedconnected" >';
@ -56,7 +66,8 @@
<div id="toggle"> <div id="toggle">
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?> <?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?>
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?> <?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?>
<?php echo template::ico('menu', ['fontSize' => '2em']); ?></div> <?php echo template::ico('menu', ['fontSize' => '2em']); ?>
</div>
<!-- fin du menu burger --> <!-- fin du menu burger -->
<?php <?php
$menuClass = $this->getData(['theme', 'menu', 'position']) === 'top' ? 'class="container-large"' : 'class="container"'; $menuClass = $this->getData(['theme', 'menu', 'position']) === 'top' ? 'class="container-large"' : 'class="container"';
@ -68,7 +79,7 @@
</nav> </nav>
<?php endif; ?> <?php endif; ?>
<!-- Bannière dans le fond du site --> <!-- Bannière dans le fond du site -->
<?php if ($this->getData(['theme', 'header', 'position']) === 'body') : ?> <?php if ($this->getData(['theme', 'header', 'position']) === 'body'): ?>
<?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(false) . '">' : ''; ?>
<?php <?php
$headerClass = $this->getData(['theme', 'header', 'position']) === 'hide' ? 'displayNone' : ''; $headerClass = $this->getData(['theme', 'header', 'position']) === 'hide' ? 'displayNone' : '';
@ -76,17 +87,19 @@
$headerClass .= $this->getData(['theme', 'header', 'wide']) === 'none' ? '' : 'container'; $headerClass .= $this->getData(['theme', 'header', 'wide']) === 'none' ? '' : 'container';
?> ?>
<header <?php echo empty($headerClass) ? '' : 'class="' . $headerClass . '"'; ?>> <header <?php echo empty($headerClass) ? '' : 'class="' . $headerClass . '"'; ?>>
<?php if ($this->getData(['theme', 'header', 'feature']) === 'wallpaper') : ?> <?php if ($this->getData(['theme', 'header', 'feature']) === 'wallpaper'): ?>
<?php if ( <?php if (
$this->getData(['theme', 'header', 'textHide']) === false $this->getData(['theme', 'header', 'textHide']) === false
// Affiche toujours le titre de la bannière pour l'édition du thème // Affiche toujours le titre de la bannière pour l'édition du thème
or ($this->getUrl(0) === 'theme' and $this->getUrl(1) === 'header') or ($this->getUrl(0) === 'theme' and $this->getUrl(1) === 'header')
) : ?> ): ?>
<span id="themeHeaderTitle"><?php echo $this->getData(['locale', 'title']); ?></span> <span id="themeHeaderTitle">
<?php else : ?> <?php echo $this->getData(['locale', 'title']); ?>
</span>
<?php else: ?>
<span id="themeHeaderTitle">&nbsp;</span> <span id="themeHeaderTitle">&nbsp;</span>
<?php endif; ?> <?php endif; ?>
<?php else : ?> <?php else: ?>
<div id="featureContent"> <div id="featureContent">
<?php echo $this->getData(['theme', 'header', 'featureContent']); ?> <?php echo $this->getData(['theme', 'header', 'featureContent']); ?>
</div> </div>
@ -95,31 +108,36 @@
<?php echo ($this->getData(['theme', 'header', 'linkHomePage']) && $this->getData(['theme', 'header', 'feature']) === 'wallpaper') ? '</a>' : ''; ?> <?php echo ($this->getData(['theme', 'header', 'linkHomePage']) && $this->getData(['theme', 'header', 'feature']) === 'wallpaper') ? '</a>' : ''; ?>
<?php endif; ?> <?php endif; ?>
<!-- Menu dans le fond du site après la bannière --> <!-- Menu dans le fond du site après la bannière -->
<?php if ($this->getData(['theme', 'menu', 'position']) === 'body-second') : ?> <?php if ($this->getData(['theme', 'menu', 'position']) === 'body-second'): ?>
<nav> <nav>
<!-- Menu burger --> <!-- Menu burger -->
<div id="toggle"> <div id="toggle">
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?> <?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?>
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?> <?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?>
<?php echo template::ico('menu', ['fontSize' => '2em']); ?></div> <?php echo template::ico('menu', ['fontSize' => '2em']); ?>
</div>
<!-- fin du menu burger --> <!-- fin du menu burger -->
<?php <?php
$menuClass = $this->getData(['theme', 'menu', 'wide']) === 'none' ? 'class="container-large"' : 'class="container"'; $menuClass = $this->getData(['theme', 'menu', 'wide']) === 'none' ? 'class="container-large"' : 'class="container"';
?> ?>
<div id="menu" <?php echo $menuClass; ?>> <div id="menu" <?php echo $menuClass; ?>>
<?php $layout->showMenu(); ?></div> <?php $layout->showMenu(); ?>
</div>
</nav> </nav>
<?php endif; ?> <?php endif; ?>
<!-- Site --> <!-- Site -->
<div id="site" class="container"> <div id="site" class="container">
<?php if ($this->getData(['theme', 'menu', 'position']) === 'site-first') : ?> <?php if ($this->getData(['theme', 'menu', 'position']) === 'site-first'): ?>
<!-- Menu dans le site avant la bannière --> <!-- Menu dans le site avant la bannière -->
<nav> <nav>
<div id="toggle"> <div id="toggle">
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?> <?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?>
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?> <?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?>
<?php echo template::ico('menu', ['fontSize' => '2em']); ?></div> <?php echo template::ico('menu', ['fontSize' => '2em']); ?>
<div id="menu" class="container"><?php $layout->showMenu(); ?></div> </div>
<div id="menu" class="container">
<?php $layout->showMenu(); ?>
</div>
</nav> </nav>
<?php endif; ?> <?php endif; ?>
<?php if ( <?php if (
@ -128,7 +146,7 @@
or ($this->getData(['theme', 'header', 'position']) === 'hide' or ($this->getData(['theme', 'header', 'position']) === 'hide'
and $this->getUrl(0) === 'theme' and $this->getUrl(0) === 'theme'
) )
) : ?> ): ?>
<!-- Bannière dans le site --> <!-- 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(false) . '">' : ''; ?>
<?php <?php
@ -136,17 +154,19 @@
$headerClass .= $this->getData(['theme', 'header', 'tinyHidden']) ? ' bannerDisplay ' : ''; $headerClass .= $this->getData(['theme', 'header', 'tinyHidden']) ? ' bannerDisplay ' : '';
?> ?>
<header <?php echo empty($headerClass) ? '' : 'class="' . $headerClass . '"'; ?>> <header <?php echo empty($headerClass) ? '' : 'class="' . $headerClass . '"'; ?>>
<?php if ($this->getData(['theme', 'header', 'feature']) === 'wallpaper') : ?> <?php if ($this->getData(['theme', 'header', 'feature']) === 'wallpaper'): ?>
<?php if ( <?php if (
$this->getData(['theme', 'header', 'textHide']) === false $this->getData(['theme', 'header', 'textHide']) === false
// Affiche toujours le titre de la bannière pour l'édition du thème // Affiche toujours le titre de la bannière pour l'édition du thème
or ($this->getUrl(0) === 'theme' and $this->getUrl(1) === 'header') or ($this->getUrl(0) === 'theme' and $this->getUrl(1) === 'header')
) : ?> ): ?>
<span id="themeHeaderTitle"><?php echo $this->getData(['locale', 'title']); ?></span> <span id="themeHeaderTitle">
<?php else : ?> <?php echo $this->getData(['locale', 'title']); ?>
</span>
<?php else: ?>
<span id="themeHeaderTitle">&nbsp;</span> <span id="themeHeaderTitle">&nbsp;</span>
<?php endif; ?> <?php endif; ?>
<?php else : ?> <?php else: ?>
<div id="featureContent"> <div id="featureContent">
<?php echo $this->getData(['theme', 'header', 'featureContent']); ?> <?php echo $this->getData(['theme', 'header', 'featureContent']); ?>
</diV> </diV>
@ -161,24 +181,29 @@
or ($this->getData(['theme', 'menu', 'position']) === 'hide' or ($this->getData(['theme', 'menu', 'position']) === 'hide'
and $this->getUrl(0) === 'theme' and $this->getUrl(0) === 'theme'
) )
) : ?> ): ?>
<!-- Menu dans le site après la bannière --> <!-- Menu dans le site après la bannière -->
<nav <?php if ($this->getData(['theme', 'menu', 'position']) === 'hide') : ?>class="displayNone" <?php endif; ?>> <nav <?php if ($this->getData(['theme', 'menu', 'position']) === 'hide'): ?>class="displayNone" <?php endif; ?>>
<div id="toggle"> <div id="toggle">
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?> <?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'title' ? '<div id="burgerText">' . $this->getData(['locale', 'title']) . '</div>' : ''; ?>
<?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?> <?php echo $this->getData(['theme', 'menu', 'burgerContent']) === 'logo' ? '<div id="burgerLogo"><img src="' . helper::baseUrl(false) . self::FILE_DIR . 'source/' . $this->getData(['theme', 'menu', 'burgerLogo']) . '"></div>' : ''; ?>
<?php echo template::ico('menu', ['fontSize' => '2em']); ?></div> <?php echo template::ico('menu', ['fontSize' => '2em']); ?>
<div id="menu" class="container"><?php $layout->showMenu(); ?></div> </div>
<div id="menu" class="container">
<?php $layout->showMenu(); ?>
</div>
</nav> </nav>
<?php endif; ?> <?php endif; ?>
<!-- Corps de page --> <!-- Corps de page -->
<?php $layout->showSection(); ?> <?php $layout->showMain(); ?>
<!-- footer --> <!-- footer -->
<?php $layout->showFooter(); ?> <?php $layout->showFooter(); ?>
<!-- Fin du site --> <!-- Fin du site -->
<?php echo $this->getData(['theme', 'footer', 'position']) === 'site' ? '</div>' : ''; ?> <?php echo $this->getData(['theme', 'footer', 'position']) === 'site' ? '</div>' : ''; ?>
<!-- Lien remonter en haut --> <!-- Lien remonter en haut -->
<div id="backToTop"><?php echo template::ico('up'); ?></div> <div id="backToTop">
<?php echo template::ico('up'); ?>
</div>
<!-- Affichage du consentement aux cookies--> <!-- Affichage du consentement aux cookies-->
<?php $layout->showCookies(); ?> <?php $layout->showCookies(); ?>
<!-- Les scripts --> <!-- Les scripts -->
@ -186,7 +211,7 @@
<!-- Script perso dans body --> <!-- Script perso dans body -->
<?php if (file_exists(self::DATA_DIR . 'body.inc.html')) { <?php if (file_exists(self::DATA_DIR . 'body.inc.html')) {
include(self::DATA_DIR . 'body.inc.html'); include(self::DATA_DIR . 'body.inc.html');
}?> } ?>
</body> </body>
</html> </html>

View File

@ -9,7 +9,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -22,7 +22,7 @@ class config extends common
'copyBackups' => self::GROUP_ADMIN, 'copyBackups' => self::GROUP_ADMIN,
'delBackups' => self::GROUP_ADMIN, 'delBackups' => self::GROUP_ADMIN,
'configMetaImage' => self::GROUP_ADMIN, 'configMetaImage' => self::GROUP_ADMIN,
'siteMap' => self::GROUP_ADMIN, 'sitemap' => self::GROUP_ADMIN,
'index' => self::GROUP_ADMIN, 'index' => self::GROUP_ADMIN,
'restore' => self::GROUP_ADMIN, 'restore' => self::GROUP_ADMIN,
'updateBaseUrl' => self::GROUP_ADMIN, 'updateBaseUrl' => self::GROUP_ADMIN,
@ -30,7 +30,8 @@ class config extends common
'logReset' => self::GROUP_ADMIN, 'logReset' => self::GROUP_ADMIN,
'logDownload' => self::GROUP_ADMIN, 'logDownload' => self::GROUP_ADMIN,
'blacklistReset' => self::GROUP_ADMIN, 'blacklistReset' => self::GROUP_ADMIN,
'blacklistDownload' => self::GROUP_ADMIN 'blacklistDownload' => self::GROUP_ADMIN,
'testmail' => self::GROUP_ADMIN,
]; ];
public static $timezones = [ public static $timezones = [
@ -204,16 +205,26 @@ class config extends common
public static $onlineVersion = ''; public static $onlineVersion = '';
public static $updateButtonText = 'Réinstaller'; public static $updateButtonText = 'Réinstaller';
public static $imageOpenGraph = [];
/** /**
* Génére les fichiers pour les crawlers * Génére les fichiers pour les crawlers
* Sitemap compressé et non compressé * Sitemap compressé et non compressé
* Robots.txt * Robots.txt
*/ */
public function siteMap() public function sitemap()
{ {
// La page n'existe pas
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
// Mettre à jour le site map // Mettre à jour le site map
$successSitemap = $this->createSitemap(); $successSitemap = $this->updateSitemap();
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
@ -223,6 +234,8 @@ class config extends common
]); ]);
} }
}
/** /**
* Sauvegarde des données * Sauvegarde des données
@ -230,7 +243,10 @@ class config extends common
public function backup() public function backup()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Creation du ZIP // Creation du ZIP
$filter = $this->getInput('configBackupOption', helper::FILTER_BOOLEAN) === true ? ['backup', 'tmp'] : ['backup', 'tmp', 'file']; $filter = $this->getInput('configBackupOption', helper::FILTER_BOOLEAN) === true ? ['backup', 'tmp'] : ['backup', 'tmp', 'file'];
$fileName = helper::autoBackup(self::TEMP_DIR, $filter); $fileName = helper::autoBackup(self::TEMP_DIR, $filter);
@ -286,8 +302,6 @@ class config extends common
} }
} }
// Traitement des données reçues valides. // Traitement des données reçues valides.
if (!empty($token) && $data !== false) { if (!empty($token) && $data !== false) {
$data = json_decode($data, true); $data = json_decode($data, true);
@ -320,7 +334,10 @@ class config extends common
public function restore() public function restore()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
$success = false; $success = false;
@ -349,12 +366,7 @@ class config extends common
'state' => false 'state' => false
]); ]);
} }
// Lire le contenu de l'archive dans le tableau files
/*
for ($i = 0; $i < $zip->numFiles; $i++) {
$stat = $zip->statIndex($i);
$files[] = (basename($stat['name']));
}*/
// Extraction de l'archive dans un dossier temporaire // Extraction de l'archive dans un dossier temporaire
$tmpDir = uniqid(8); $tmpDir = uniqid(8);
$success = $zip->extractTo(self::TEMP_DIR . $tmpDir); $success = $zip->extractTo(self::TEMP_DIR . $tmpDir);
@ -382,7 +394,7 @@ class config extends common
// Copie dans le dossier /site/data // Copie dans le dossier /site/data
$success = $this->copyDir(self::TEMP_DIR . $tmpDir, 'site/'); $success = $this->copyDir(self::TEMP_DIR . $tmpDir, 'site/');
$this->removeDir(self::TEMP_DIR . $tmpDir); $this->deleteDir(self::TEMP_DIR . $tmpDir);
// Restaurer les users originaux d'une v10 si option cochée // Restaurer les users originaux d'une v10 si option cochée
if ( if (
@ -417,7 +429,10 @@ class config extends common
public function index() public function index()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Basculement en mise à jour auto, remise à 0 du compteur // Basculement en mise à jour auto, remise à 0 du compteur
if ( if (
@ -451,21 +466,25 @@ class config extends common
'twitterId' => $this->getInput('socialTwitterId'), 'twitterId' => $this->getInput('socialTwitterId'),
'youtubeId' => $this->getInput('socialYoutubeId'), 'youtubeId' => $this->getInput('socialYoutubeId'),
'youtubeUserId' => $this->getInput('socialYoutubeUserId'), 'youtubeUserId' => $this->getInput('socialYoutubeUserId'),
'githubId' => $this->getInput('socialGithubId') 'githubId' => $this->getInput('socialGithubId'),
'redditId' => $this->getInput('socialRedditId'),
'twitchId' => $this->getInput('socialTwitchId'),
'vimeoId' => $this->getInput('socialVimeoId'),
'steamId' => $this->getInput('socialSteamId'),
], ],
'smtp' => [ 'smtp' => [
'enable' => $this->getInput('smtpEnable', helper::FILTER_BOOLEAN), 'enable' => $this->getInput('smtpEnable', helper::FILTER_BOOLEAN),
'host' => $this->getInput('smtpHost', helper::FILTER_STRING_SHORT, $this->getInput('smtpEnable', helper::FILTER_BOOLEAN)), 'host' => $this->getInput('smtpHost', helper::FILTER_STRING_SHORT),
'port' => $this->getInput('smtpPort', helper::FILTER_INT, $this->getInput('smtpEnable', helper::FILTER_BOOLEAN)), 'port' => $this->getInput('smtpPort', helper::FILTER_INT),
'auth' => $this->getInput('smtpAuth', helper::FILTER_BOOLEAN), 'auth' => $this->getInput('smtpAuth', helper::FILTER_BOOLEAN),
'secure' => $this->getInput('smtpSecure', helper::FILTER_STRING_SHORT), 'secure' => $this->getInput('smtpSecure', helper::FILTER_STRING_SHORT),
'username' => $this->getInput('smtpUsername', helper::FILTER_STRING_SHORT, $this->getInput('smtpAuth', helper::FILTER_BOOLEAN)), 'username' => $this->getInput('smtpUsername', helper::FILTER_STRING_SHORT),
'password' => helper::encrypt($this->getData(['config', 'smtp', 'username']), $this->getInput('smtpPassword', null, $this->getInput('smtpAuth', helper::FILTER_BOOLEAN))), 'password' => helper::encrypt($this->getInput('smtpPassword', helper::FILTER_STRING_SHORT), $this->getInput('smtpHost', helper::FILTER_STRING_SHORT)),
'from' => $this->getInput('smtpFrom', helper::FILTER_MAIL, true), 'from' => $this->getInput('smtpFrom', helper::FILTER_MAIL, true),
], ],
'seo' => [ 'seo' => [
'robots' => $this->getInput('seoRobots', helper::FILTER_BOOLEAN), 'robots' => $this->getInput('seoRobots', helper::FILTER_BOOLEAN),
'keyApi' => $this->getInput('seoKeyApi', helper::FILTER_STRING_SHORT), 'openGraphImage' => $this->getInput('seoOpenGraphImage', helper::FILTER_STRING_SHORT),
], ],
'connect' => [ 'connect' => [
'attempt' => $this->getInput('connectAttempt', helper::FILTER_INT), 'attempt' => $this->getInput('connectAttempt', helper::FILTER_INT),
@ -477,11 +496,23 @@ class config extends common
'autoDisconnect' => $this->getInput('connectAutoDisconnect', helper::FILTER_BOOLEAN), 'autoDisconnect' => $this->getInput('connectAutoDisconnect', helper::FILTER_BOOLEAN),
'captchaType' => $this->getInput('connectCaptchaType'), 'captchaType' => $this->getInput('connectCaptchaType'),
'showPassword' => $this->getInput('connectShowPassword', helper::FILTER_BOOLEAN), 'showPassword' => $this->getInput('connectShowPassword', helper::FILTER_BOOLEAN),
'redirectLogin' => $this->getInput('connectRedirectLogin', helper::FILTER_BOOLEAN) 'redirectLogin' => $this->getInput('connectRedirectLogin', helper::FILTER_BOOLEAN),
'mailAuth' => $this->getInput('connectAuthMail', helper::FILTER_INT),
] ]
] ]
]); ]);
// Sauvegarde la position des onglets de la vue de l'utilisateur courant
$this->setData([
'user',
$this->getUser('id'),
'view',
[
'config' => $this->getInput('containerSelected'),
'page' => $this->getData(['user', $this->getUser('id'), 'view', 'page']),
]
]);
// Efface les fichiers de backup lorsque l'option est désactivée // Efface les fichiers de backup lorsque l'option est désactivée
if ($this->getInput('configFileBackup', helper::FILTER_BOOLEAN) === false) { if ($this->getInput('configFileBackup', helper::FILTER_BOOLEAN) === false) {
$path = realpath('site/data'); $path = realpath('site/data');
@ -490,7 +521,8 @@ class config extends common
unlink($filename); unlink($filename);
} }
} }
if (file_exists('site/data/.backup')) unlink('site/data/.backup'); if (file_exists('site/data/.backup'))
unlink('site/data/.backup');
} else { } else {
touch('site/data/.backup'); touch('site/data/.backup');
} }
@ -504,7 +536,7 @@ class config extends common
) { ) {
// Ajout des lignes dans le .htaccess // Ajout des lignes dans le .htaccess
$fileContent = file_get_contents('.htaccess'); $fileContent = file_get_contents('.htaccess');
$rewriteData = PHP_EOL . $rewriteData =
'# URL rewriting' . PHP_EOL . '# URL rewriting' . PHP_EOL .
'<IfModule mod_rewrite.c>' . PHP_EOL . '<IfModule mod_rewrite.c>' . PHP_EOL .
"\tRewriteEngine on" . PHP_EOL . "\tRewriteEngine on" . PHP_EOL .
@ -513,9 +545,9 @@ class config extends common
"\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL . "\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL .
"\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL . "\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL .
'</IfModule>' . PHP_EOL . '</IfModule>' . PHP_EOL .
'# URL rewriting' . PHP_EOL; '# URL rewriting';
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent); $fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
file_put_contents( $this->secure_file_put_contents(
'.htaccess', '.htaccess',
$fileContent $fileContent
); );
@ -531,7 +563,7 @@ class config extends common
$fileContent = file_get_contents('.htaccess'); $fileContent = file_get_contents('.htaccess');
$fileContent = explode('# URL rewriting', $fileContent); $fileContent = explode('# URL rewriting', $fileContent);
$fileContent = $fileContent[0] . '# URL rewriting' . $fileContent[2]; $fileContent = $fileContent[0] . '# URL rewriting' . $fileContent[2];
file_put_contents( $this->secure_file_put_contents(
'.htaccess', '.htaccess',
$fileContent $fileContent
); );
@ -566,14 +598,58 @@ class config extends common
// Variable de version // Variable de version
if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) { if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) {
self::$updateButtonText = helper::translate('Mettre à jour'); self::$updateButtonText = helper::translate('Mise à jour');
} }
// Sélecteur de délais, compléter avec la traduction en jours // Sélecteur de délais, compléter avec la traduction en jours
foreach(self::$updateDelay as $key => $value) { foreach (self::$updateDelay as $key => $value) {
self::$updateDelay[$key] = $key === 86400 ? $value . ' ' . helper::translate('jour') : $value . ' ' . helper::translate('jours'); self::$updateDelay[$key] = $key === 86400 ? $value . ' ' . helper::translate('jour') : $value . ' ' . helper::translate('jours');
} }
// Paramètres de l'image OpenGraph
$imagePath = self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']);
// Par défaut
self::$imageOpenGraph['type'] = '';
self::$imageOpenGraph['size'] = '';
self::$imageOpenGraph['wide'] = '';
self::$imageOpenGraph['height'] = '';
self::$imageOpenGraph['ratio'] = 0;
if (
$this->getData(['config', 'seo', 'openGraphImage'])
&& file_exists($imagePath)
) {
// Infos sur l'image Open Graph
$typeMime = exif_imagetype($imagePath);
switch ($typeMime) {
case IMAGETYPE_JPEG:
$typeMime = 'jpeg';
break;
case IMAGETYPE_PNG:
$typeMime = 'png';
break;
default:
$typeMime = image_type_to_mime_type($typeMime);
}
self::$imageOpenGraph['type'] = $typeMime;
$imageSize = getimagesize($imagePath);
self::$imageOpenGraph['wide'] = $imageSize[0];
self::$imageOpenGraph['height'] = $imageSize[1];
self::$imageOpenGraph['ratio'] = self::$imageOpenGraph['wide'] / self::$imageOpenGraph['height'];
self::$imageOpenGraph['size'] = filesize($imagePath);
$tailleEnOctets = filesize($imagePath);
if ($tailleEnOctets >= 1024 * 1024) {
// Si la taille est supérieure ou égale à 1 Mo, afficher en mégaoctets
self::$imageOpenGraph['size'] = round($tailleEnOctets / (1024 * 1024), 2) . ' Mo';
} else {
// Sinon, afficher en kilooctets
self::$imageOpenGraph['size'] = round($tailleEnOctets / 1024, 2) . ' Ko';
}
}
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Configuration'), 'title' => helper::translate('Configuration'),
@ -585,13 +661,16 @@ class config extends common
public function script() public function script()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Ecrire les fichiers de script // Ecrire les fichiers de script
if ($this->geturl(2) === 'head') { if ($this->geturl(2) === 'head') {
file_put_contents(self::DATA_DIR . 'head.inc.html', $this->getInput('configScriptHead', null)); $this->secure_file_put_contents(self::DATA_DIR . 'head.inc.html', $this->getInput('configScriptHead', null));
} }
if ($this->geturl(2) === 'body') { if ($this->geturl(2) === 'body') {
file_put_contents(self::DATA_DIR . 'body.inc.html', $this->getInput('configScriptBody', null)); $this->secure_file_put_contents(self::DATA_DIR . 'body.inc.html', $this->getInput('configScriptBody', null));
} }
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
@ -620,11 +699,20 @@ class config extends common
public function logReset() public function logReset()
{ {
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
if (file_exists(self::DATA_DIR . 'journal.log')) { if (file_exists(self::DATA_DIR . 'journal.log')) {
unlink(self::DATA_DIR . 'journal.log'); unlink(self::DATA_DIR . 'journal.log');
// Créer les en-têtes des journaux // Créer les en-têtes des journaux
$d = 'Date;Heure;IP;Id;Action' . PHP_EOL; $d = 'Date;Heure;IP;Id;Action' . PHP_EOL;
file_put_contents(self::DATA_DIR . 'journal.log', $d); $this->secure_file_put_contents(self::DATA_DIR . 'journal.log', $d);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Configuration'), 'title' => helper::translate('Configuration'),
@ -642,6 +730,7 @@ class config extends common
]); ]);
} }
} }
}
@ -650,6 +739,15 @@ class config extends common
*/ */
public function logDownload() public function logDownload()
{ {
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
$fileName = self::DATA_DIR . 'journal.log'; $fileName = self::DATA_DIR . 'journal.log';
if (file_exists($fileName)) { if (file_exists($fileName)) {
ob_start(); ob_start();
@ -671,24 +769,34 @@ class config extends common
]); ]);
} }
} }
}
/** /**
* Tableau des IP blacklistés * Tableau des IP blacklistés
*/ */
public function blacklistDownload() public function blacklistDownload()
{ {
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
ob_start(); ob_start();
$fileName = self::TEMP_DIR . 'blacklist.log'; $fileName = self::TEMP_DIR . 'blacklist.log';
$d = 'Date dernière tentative;Heure dernière tentative;Id;Adresse IP;Nombre d\'échecs' . PHP_EOL; $d = 'Date dernière tentative;Heure dernière tentative;Id;Adresse IP;Nombre d\'échecs' . PHP_EOL;
file_put_contents($fileName, $d); $this->secure_file_put_contents($fileName, $d);
if (file_exists($fileName)) { if (file_exists($fileName)) {
$d = $this->getData(['blacklist']); $d = $this->getData(['blacklist']);
$data = ''; $data = '';
foreach ($d as $key => $item) { foreach ($d as $key => $item) {
$data .= helper::dateUTF8('%Y %m %d', $item['lastFail']) . ' - ' . helper::dateUTF8('%H:%M', time()); $data .= helper::dateUTF8('%Y %m %d', $item['lastFail'], self::$i18nUI) . ' - ' . helper::dateUTF8('%H:%M', time(), self::$i18nUI);
$data .= $key . ';' . $item['ip'] . ';' . $item['connectFail'] . PHP_EOL; $data .= $key . ';' . $item['ip'] . ';' . $item['connectFail'] . PHP_EOL;
} }
file_put_contents($fileName, $data, FILE_APPEND); $this->secure_file_put_contents($fileName, $data, FILE_APPEND);
header('Content-Description: File Transfer'); header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream'); header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary'); header('Content-Transfer-Encoding: binary');
@ -702,13 +810,14 @@ class config extends common
} else { } else {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Confighelper::translate(uration'), 'title' => helper::translate('Configuration'),
'view' => 'index', 'view' => 'index',
'notification' => helper::translate('Aucune liste noire à télécharger'), 'notification' => helper::translate('Aucune liste noire à télécharger'),
'state' => false 'state' => false
]); ]);
} }
} }
}
/** /**
* Réinitialiser les ip blacklistées * Réinitialiser les ip blacklistées
@ -716,6 +825,15 @@ class config extends common
public function blacklistReset() public function blacklistReset()
{ {
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
if (file_exists(self::DATA_DIR . 'blacklist.json')) { if (file_exists(self::DATA_DIR . 'blacklist.json')) {
$this->setData(['blacklist', []]); $this->setData(['blacklist', []]);
// Valeurs en sortie // Valeurs en sortie
@ -735,12 +853,22 @@ class config extends common
]); ]);
} }
} }
}
/** /**
* Récupération des backups auto dans le gestionnaire de fichiers * Récupération des backups auto dans le gestionnaire de fichiers
*/ */
public function copyBackups() public function copyBackups()
{ {
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
$success = $this->copyDir(self::BACKUP_DIR, self::FILE_DIR . 'source/backup'); $success = $this->copyDir(self::BACKUP_DIR, self::FILE_DIR . 'source/backup');
@ -752,12 +880,22 @@ class config extends common
'state' => $success 'state' => $success
]); ]);
} }
}
/** /**
* Vider le dosser des sauvegardes automatisées * Vider le dosser des sauvegardes automatisées
*/ */
public function delBackups() public function delBackups()
{ {
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
$path = realpath(self::BACKUP_DIR); $path = realpath(self::BACKUP_DIR);
$success = $fail = 0; $success = $fail = 0;
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) { foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
@ -776,4 +914,51 @@ class config extends common
'state' => true 'state' => true
]); ]);
} }
}
/**
* 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';
}
}
/**
* Envoi un message de test
* @return void
*/
public function testmail()
{
$sent = $this->sendMail(
$this->getUser('mail'),
helper::translate('Test de la messagerie du site'),
'<strong>' . $this->getUser('firstname') . ' ' . $this->getUser('lastname') . '</strong>,<br><br>' .
'<h4>' . helper::translate('Il semblerait que votre messagerie fonctionne correctement !') . '</h4>',
null,
'no-reply@localhost'
);
if ($sent !== true) {
// Désactivation de l'authentification par email
$this->setData(['config', 'connect', 'mailAuth', 0]);
// Journalisation
$this->saveLog($sent);
}
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'config/' . $this->getUrl(2),
'state' => $sent === true ? true : false,
'notification' => $sent === true ? helper::translate('Message de test envoyé avec succès') : helper::translate('Message non envoyé')
]);
}
} }

View File

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

View File

@ -0,0 +1,47 @@
<?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
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é et ajoute les fichiers à l'archive ZIP. 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'])) {
$key = $_GET['key'];
$storedKey = file_get_contents('data.key');
if ($key !== $storedKey) {
http_response_code(401);
exit();
}
// Création du ZIP
$filter = ['backup', 'tmp'];
$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);
}

View File

@ -0,0 +1,49 @@
<?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);
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);
}

View File

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

View File

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

@ -3,13 +3,7 @@
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Sécurité de la connexion'); ?> <h4><?php echo helper::translate('Sécurité de la connexion'); ?>
<!--<span id="specialeHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/connexion" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php // echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>-->
</h4> </h4>
<div class="row"> <div class="row">
<div class="col4"> <div class="col4">
<?php echo template::checkbox('connectShowPassword', true, 'Dévoiler le mot de passe', [ <?php echo template::checkbox('connectShowPassword', true, 'Dévoiler le mot de passe', [
@ -43,32 +37,32 @@
'selected' => $this->getData(['config', 'connect', 'timeout']) 'selected' => $this->getData(['config', 'connect', 'timeout'])
]); ?> ]); ?>
</div> </div>
<div class="col3 verticalAlignBottom"> <div class="col3">
<label id="helpBlacklist"><?php echo helper::translate('Liste noire'); ?> <?php echo template::select('connectAuthMail', array_merge([0 => 'Aucune'], self::$groupNews), [
<?php echo template::help( 'label' => 'Validation par clé ⚠️',
'La liste noire énumère les tentatives de connexion à partir de comptes inexistants. Sont stockés : la date, l\'heure, le nom du compte et l\'IP. 'selected' => $this->getData(['config', 'connect', 'mailAuth']),
Après le nombre de tentatives autorisées, l\'IP et le compte sont bloqués.' 'help' => 'La connexion est confirmée à l\'aide d\'une clé transmise par messagerie. Depuis le groupe sélectionné et les groupes supérieurs.'
);
?>
</label>
<?php echo template::button('ConnectBlackListDownload', [
'href' => helper::baseUrl() . 'config/blacklistDownload',
'value' => 'Télécharger la liste',
'ico' => 'download'
]); ?> ]); ?>
</div> </div>
<div class="col3 verticalAlignBottom"> <div class="col3 verticalAlignBottom">
<?php echo template::button('CnnectBlackListReset', [ <?php echo template::button('ConfigSendMail', [
'class' => 'buttonRed', 'href' => helper::baseUrl() . 'config/testmail',
'href' => helper::baseUrl() . 'config/blacklistReset', 'value' => 'Message de test',
'value' => 'Réinitialiser la liste', 'ico' => 'mail'
'ico' => 'trash'
]); ?> ]); ?>
</div> </div>
</div> </div>
</div>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4><?php echo helper::translate('Captcha à la connexion'); ?>
</h4>
<div class="row"> <div class="row">
<div class="col3"> <div class="col3">
<?php echo template::checkbox('connectCaptcha', true, 'Captcha à la connexion', [ <?php echo template::checkbox('connectCaptcha', true, 'Activer', [
'checked' => $this->getData(['config', 'connect', 'captcha']) 'checked' => $this->getData(['config', 'connect', 'captcha'])
]); ?> ]); ?>
</div> </div>
@ -92,34 +86,32 @@
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Journalisation'); ?> <h4><?php echo helper::translate('Journalisation'); ?>
<!--<span id="specialeHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/journalisation" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php // echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>
-->
</h4> </h4>
<div class="row"> <div class="row">
<div class="col3"> <div class="col6">
<div class="row">
<div class="col6">
<?php echo template::checkbox('connectLog', true, 'Activer la journalisation', [ <?php echo template::checkbox('connectLog', true, 'Activer la journalisation', [
'checked' => $this->getData(['config', 'connect', 'log']) 'checked' => $this->getData(['config', 'connect', 'log'])
]); ?> ]); ?>
</div> </div>
<div class="col3"> <div class="col6">
<?php echo template::select('connectAnonymousIp', $module::$anonIP, [ <?php echo template::select('connectAnonymousIp', $module::$anonIP, [
'label' => 'Anonymat des adresses IP', 'label' => 'Anonymat des adresses IP',
'selected' => $this->getData(['config', 'connect', 'anonymousIp']), 'selected' => $this->getData(['config', 'connect', 'anonymousIp']),
'help' => 'La règlementation française impose un anonymat de niveau 2' 'help' => 'La règlementation française impose un anonymat de niveau 2'
]); ?> ]); ?>
</div> </div>
<div class="col3 verticalAlignBottom"> </div>
<div class="row">
<div class="col6 ">
<?php echo template::button('ConfigLogDownload', [ <?php echo template::button('ConfigLogDownload', [
'href' => helper::baseUrl() . 'config/logDownload', 'href' => helper::baseUrl() . 'config/logDownload',
'value' => 'Télécharger le journal', 'value' => 'Télécharger le journal',
'ico' => 'download' 'ico' => 'download'
]); ?> ]); ?>
</div> </div>
<div class="col3 verticalAlignBottom"> <div class="col6">
<?php echo template::button('ConnectLogReset', [ <?php echo template::button('ConnectLogReset', [
'class' => 'buttonRed', 'class' => 'buttonRed',
'href' => helper::baseUrl() . 'config/logReset', 'href' => helper::baseUrl() . 'config/logReset',
@ -129,6 +121,34 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col6 verticalAlignBottom">
<div class="row">
<div class="col6 verticalAlignBottom">
<label id="helpBlacklist"><?php echo helper::translate('Liste noire'); ?>
<?php echo template::help(
'La liste noire énumère les tentatives de connexion à partir de comptes inexistants. Sont stockés : la date, l\'heure, le nom du compte et l\'IP.
Après le nombre de tentatives autorisées, l\'IP et le compte sont bloqués.'
);
?>
</label>
<?php echo template::button('ConnectBlackListDownload', [
'href' => helper::baseUrl() . 'config/blacklistDownload',
'value' => 'Télécharger la liste',
'ico' => 'download'
]); ?>
</div>
<div class="col6 verticalAlignBottom">
<?php echo template::button('ConnectBlackListReset', [
'class' => 'buttonRed',
'href' => helper::baseUrl() . 'config/blacklistReset',
'value' => 'Réinitialiser la liste',
'ico' => 'trash'
]); ?>
</div>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -53,3 +53,15 @@
.activeButton { .activeButton {
background-color: #00BFFF; background-color: #00BFFF;
} }
.greenInfo, .redInfo {
font-weight: bold;
}
.greenInfo {
color: green;
}
.redInfo {
color: red;
}

File diff suppressed because one or more lines are too long

View File

@ -7,16 +7,13 @@
'value' => template::ico('home') 'value' => template::ico('home')
]); ?> ]); ?>
</div> </div>
<div class="col1"> <div class="col2 offset7">
<?php /**echo template::button('configHelp', [ <?php echo template::button('configLocaleButton', [
'class' => 'buttonHelp', 'value' => 'Identité',
'href' => 'https://doc.zwiicms.fr/configuration-du-site', 'href' => helper::baseUrl() . 'language/site'
'target' => '_blank', ]); ?>
'value' => template::ico('help'),
'help' => 'Consulter l\'aide en ligne'
]); */ ?>
</div> </div>
<div class="col2 offset8"> <div class="col2">
<?php echo template::submit('Submit'); ?> <?php echo template::submit('Submit'); ?>
</div> </div>
</div> </div>
@ -24,24 +21,26 @@
<div class="tab"> <div class="tab">
<?php echo template::button('configSetupButton', [ <?php echo template::button('configSetupButton', [
'value' => 'Configuration', 'value' => 'Configuration',
'class' => 'buttonTab' 'class' => 'buttonTab',
]); ?> ]); ?>
<?php echo template::button('configSocialButton', [ <?php echo template::button('configSocialButton', [
'value' => 'Référencement', 'value' => 'Référencement',
'class' => 'buttonTab' 'class' => 'buttonTab',
]); ?> ]); ?>
<?php echo template::button('configConnectButton', [ <?php echo template::button('configConnectButton', [
'value' => 'Connexion', 'value' => 'Connexion',
'class' => 'buttonTab' 'class' => 'buttonTab',
]); ?> ]); ?>
<?php echo template::button('configNetworkButton', [ <?php echo template::button('configNetworkButton', [
'value' => 'Réseau', 'value' => 'Réseau',
'class' => 'buttonTab' 'class' => 'buttonTab',
]); ?> ]); ?>
</div> </div>
<!-- Champ caché pour transmettre l'onglet-->
<?php echo template::hidden('containerSelected'); ?>
<!-- Pages de formulaires -->
<?php include('core/module/config/view/setup/setup.php') ?> <?php include('core/module/config/view/setup/setup.php') ?>
<?php include('core/module/config/view/social/social.php') ?> <?php include('core/module/config/view/social/social.php') ?>
<?php include('core/module/config/view/connect/connect.php') ?> <?php include('core/module/config/view/connect/connect.php') ?>

View File

@ -4,11 +4,6 @@
<div class="block"> <div class="block">
<h4> <h4>
<?php echo helper::translate('Paramètres'); ?> <?php echo helper::translate('Paramètres'); ?>
<!--<span id="specialeHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/reseau" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>-->
</h4> </h4>
<div class="row"> <div class="row">
<div class="col2"> <div class="col2">
@ -40,11 +35,6 @@
<div class="block"> <div class="block">
<h4> <h4>
<?php echo helper::translate('SMTP'); ?> <?php echo helper::translate('SMTP'); ?>
<!--<span id="specialeHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/smtp" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']); ?>
</a>
</span>-->
</h4> </h4>
<div class="row"> <div class="row">
<div class="col6"> <div class="col6">
@ -113,3 +103,4 @@
</div> </div>
</div> </div>
</div> </div>
</div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,12 +3,6 @@
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Paramètres'); ?> <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> </h4>
<div class="row"> <div class="row">
<div class="col4"> <div class="col4">
@ -17,7 +11,8 @@
'language' => $this->getData(['user', $this->getUser('id'), 'language']), 'language' => $this->getData(['user', $this->getUser('id'), 'language']),
'help' => 'Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.', 'help' => 'Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.',
'label' => 'Favicon', 'label' => 'Favicon',
'value' => $this->getData(['config', 'favicon']) 'value' => $this->getData(['config', 'favicon']),
'folder' => $this->getData(['config', 'favicon']) ? dirname($this->getData(['config', 'favicon'])) : ''
]); ?> ]); ?>
</div> </div>
<div class="col4"> <div class="col4">
@ -26,7 +21,8 @@
'language' => $this->getData(['user', $this->getUser('id'), 'language']), '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.', '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', '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>
<div class="col4"> <div class="col4">
@ -48,7 +44,7 @@
<?php echo template::checkbox('configRewrite', true, 'Apache URL intelligentes', [ <?php echo template::checkbox('configRewrite', true, 'Apache URL intelligentes', [
'checked' => helper::checkRewrite(), 'checked' => helper::checkRewrite(),
'help' => 'Supprime le point d\'interrogation dans les URL, l\'option est indisponible avec les autres serveurs Web', 'help' => 'Supprime le point d\'interrogation dans les URL, l\'option est indisponible avec les autres serveurs Web',
'disabled' => stripos($_SERVER["SERVER_SOFTWARE"], 'nginx') 'disabled' => helper::checkServerSoftware() === false and $module->isModRewriteEnabled()
]); ?> ]); ?>
</div> </div>
</div> </div>
@ -59,12 +55,6 @@
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Mise à jour automatisée'); ?> <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> </h4>
<div class="row"> <div class="row">
<div class="col6"> <div class="col6">
@ -89,11 +79,11 @@
'selected' => $this->getData(['config', 'autoUpdateDelay']), 'selected' => $this->getData(['config', 'autoUpdateDelay']),
]); ?> ]); ?>
</div> </div>
<div class="col3 offset2 verticalAlignBottom"> <div class="col3 offset1 verticalAlignBottom">
<pre>Version installée : <strong><?php echo common::ZWII_VERSION ; ?></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> <pre>Version en ligne : <strong><?php echo helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL); ?></strong></pre>
</div> </div>
<div class="col3 verticalAlignBottom"> <div class="col3 offset2 verticalAlignBottom">
<?php echo template::button('configUpdateForced', [ <?php echo template::button('configUpdateForced', [
'ico' => 'download-cloud', 'ico' => 'download-cloud',
'href' => helper::baseUrl() . 'install/update', 'href' => helper::baseUrl() . 'install/update',
@ -109,12 +99,6 @@
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Maintenance'); ?> <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> </h4>
<div class="row"> <div class="row">
<div class="col6"> <div class="col6">
@ -169,12 +153,6 @@
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Scripts externes'); ?> <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> </h4>
<div class="row"> <div class="row">
<div class="col4 offset1 verticalAlignBottom"> <div class="col4 offset1 verticalAlignBottom">
@ -198,13 +176,21 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <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> </h4>
<div class="row textAlignCenter"> <div class="row textAlignCenter">
<div class="col12"> <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> <a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img
<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> alt="Licence Creative Commons" style="border-width:0"
<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> 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> </div>
</div> </div>

View File

@ -2,40 +2,52 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Capture d\'écran Open Graph'); ?> <h4>
<!--<span id="specialeHelpButton" class="helpDisplayButton"> <?php echo helper::translate('Capture d\'écran Open Graph'); ?>
<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> </h4>
<div class="row"> <div class="row">
<div class="col7"> <div class="col6">
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<?php echo template::text('seoKeyApi', [ <?php echo template::file('seoOpenGraphImage', [
'label' => 'Clé de l\'API <a href="https://app.screenshotapi.net/" target="_blank">ScreenShotApi</a>', 'language' => $this->getData(['user', $this->getUser('id'), 'language']),
'value' => $this->getData(['config', 'seo', 'keyApi']), 'label' => 'Image Open Graph',
'help' => 'Créez un compte gratuit, recopier la clé , puis valider le formulaire avant de cliquer sur le bouton de génération' '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'))
]); ?> ]); ?>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col6 offset3"> <div class="col10 textAlignCenter">
<?php echo template::button('socialMetaImage', [ <?php if (!empty($module::$imageOpenGraph['type'])): ?>
'href' => helper::baseUrl() . 'config/configMetaImage', <p>
'value' => 'Générer une capture Open Graph' <?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>
</div> </div>
</div> </div>
<div class="col5"> <div class="col6">
<?php if (file_exists(self::FILE_DIR . 'source/screenshot.jpg')) : ?> <?php if (
<div class="row"> $this->getData(['config', 'seo', 'openGraphImage']) &&
<div class="col8 offset2 textAlignCenter"> file_exists(self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']))
<img src="<?php echo helper::baseUrl(false) . self::FILE_DIR . 'source/screenshot.jpg'; ?>" data-tippy-content="Cette capture d'écran est nécessaire aux partages sur les réseaux sociaux. Elle est régénérée lorsque le fichier 'screenshot.jpg' est effacé du gestionnaire de fichiers." /> ): ?>
</div> <img
</div> src="<?php echo self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']); ?>" />
<?php endif; ?> <?php endif; ?>
</div> </div>
</div> </div>
@ -45,7 +57,8 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Référencement'); ?> <h4>
<?php echo helper::translate('Référencement'); ?>
</h4> </h4>
<div class="row"> <div class="row">
<div class="col4 offset1"> <div class="col4 offset1">
@ -66,72 +79,98 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Réseaux sociaux'); ?> <h4>
<!--<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> </h4>
<div class="row"> <div class="row">
<div class="col3"> <div class="col3">
<?php echo template::text('socialFacebookId', [ <?php echo template::text('socialFacebookId', [
'help' => 'Saisissez votre ID : https://www.facebook.com/[ID].', 'help' => 'Saisissez votre ID : https://www.facebook.com/[ID].',
'label' => 'Facebook', 'label' => template::ico('facebook', ['margin' => 'right']) . 'Facebook',
'value' => $this->getData(['config', 'social', 'facebookId']) 'value' => $this->getData(['config', 'social', 'facebookId'])
]); ?> ]); ?>
</div> </div>
<div class="col3"> <div class="col3">
<?php echo template::text('socialInstagramId', [ <?php echo template::text('socialInstagramId', [
'help' => 'Saisissez votre ID : https://www.instagram.com/[ID].', 'help' => 'Saisissez votre ID : https://www.instagram.com/[ID].',
'label' => 'Instagram', 'label' => template::ico('instagram', ['margin' => 'right']) . 'Instagram',
'value' => $this->getData(['config', 'social', 'instagramId']) 'value' => $this->getData(['config', 'social', 'instagramId'])
]); ?> ]); ?>
</div> </div>
<div class="col3">
<?php echo template::text('socialTwitterId', [
'help' => 'Saisissez votre ID : https://twitter.com/[ID].',
'label' => template::ico('twitter', ['margin' => 'right']) . 'Twitter',
'value' => $this->getData(['config', 'social', 'twitterId'])
]); ?>
</div>
<div class="col3">
<?php echo template::text('socialRedditId', [
'help' => 'Saisissez votre ID Reddit : https://www.reddit.com/user/[ID].',
'label' => template::ico('reddit', ['margin' => 'right']) . 'Reddit',
'value' => $this->getData(['config', 'social', 'redditId'])
]); ?>
</div>
</div>
<div class="row">
<div class="col3"> <div class="col3">
<?php echo template::text('socialYoutubeId', [ <?php echo template::text('socialYoutubeId', [
'help' => 'ID de la chaîne : https://www.youtube.com/channel/[ID].', 'help' => 'ID de la chaîne : https://www.youtube.com/channel/[ID].',
'label' => 'Chaîne Youtube', 'label' => template::ico('youtube', ['margin' => 'right']) . 'Chaîne Youtube',
'value' => $this->getData(['config', 'social', 'youtubeId']) 'value' => $this->getData(['config', 'social', 'youtubeId'])
]); ?> ]); ?>
</div> </div>
<div class="col3"> <div class="col3">
<?php echo template::text('socialYoutubeUserId', [ <?php echo template::text('socialYoutubeUserId', [
'help' => 'Saisissez votre ID Utilisateur : https://www.youtube.com/user/[ID].', 'help' => 'Saisissez votre ID Utilisateur : https://www.youtube.com/user/[ID].',
'label' => 'Youtube', 'label' => template::ico('youtube', ['margin' => 'right']) . 'Youtube',
'value' => $this->getData(['config', 'social', 'youtubeUserId']) 'value' => $this->getData(['config', 'social', 'youtubeUserId'])
]); ?> ]); ?>
</div> </div>
</div>
<div class="row">
<div class="col3"> <div class="col3">
<?php echo template::text('socialTwitterId', [ <?php echo template::text('socialVimeoId', [
'help' => 'Saisissez votre ID : https://twitter.com/[ID].', 'help' => 'Saisissez votre ID Viemo : https://vimeo.com/[ID].',
'label' => 'Twitter', 'label' => template::ico('vimeo', ['margin' => 'right']) . 'Vimeo',
'value' => $this->getData(['config', 'social', 'twitterId']) 'value' => $this->getData(['config', 'social', 'vimeoId'])
]); ?> ]); ?>
</div> </div>
<div class="col3"> <div class="col3">
<?php echo template::text('socialPinterestId', [ <?php echo template::text('socialPinterestId', [
'help' => 'Saisissez votre ID : https://pinterest.com/[ID].', 'help' => 'Saisissez votre ID : https://pinterest.com/[ID].',
'label' => 'Pinterest', 'label' => template::ico('pinterest', ['margin' => 'right']) . 'Pinterest',
'value' => $this->getData(['config', 'social', 'pinterestId']) 'value' => $this->getData(['config', 'social', 'pinterestId'])
]); ?> ]); ?>
</div> </div>
</div>
<div class="row">
<div class="col3"> <div class="col3">
<?php echo template::text('socialLinkedinId', [ <?php echo template::text('socialLinkedinId', [
'help' => 'Saisissez votre ID Linkedin : https://fr.linkedin.com/in/[ID].', 'help' => 'Saisissez votre ID Linkedin : https://fr.linkedin.com/in/[ID].',
'label' => 'Linkedin', 'label' => template::ico('linkedin', ['margin' => 'right']) . 'Linkedin',
'value' => $this->getData(['config', 'social', 'linkedinId']) 'value' => $this->getData(['config', 'social', 'linkedinId'])
]); ?> ]); ?>
</div> </div>
<div class="col3"> <div class="col3">
<?php echo template::text('socialGithubId', [ <?php echo template::text('socialGithubId', [
'help' => 'Saisissez votre ID Github : https://github.com/[ID].', 'help' => 'Saisissez votre ID Github : https://github.com/[ID].',
'label' => 'Github', 'label' => template::ico('github', ['margin' => 'right']) . 'Github',
'value' => $this->getData(['config', 'social', 'githubId']) 'value' => $this->getData(['config', 'social', 'githubId'])
]); ?> ]); ?>
</div> </div>
<div class="col3">
<?php echo template::text('socialTwitchId', [
'help' => 'Saisissez votre ID Twitch : https://www.twitch.tv/[ID].',
'label' => template::ico('twitch', ['margin' => 'right']) . 'Twitch',
'value' => $this->getData(['config', 'social', 'twitchId'])
]); ?>
</div>
<div class="col3">
<?php echo template::text('socialSteamId', [
'help' => 'Saisissez votre ID Viemo : https://steamcommunity.com/id/[ID].',
'label' => template::ico('steam', ['margin' => 'right']) . 'Steam',
'value' => $this->getData(['config', 'social', 'steamId'])
]); ?>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,50 @@
<?php
/**
* 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-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
class dashboard extends common
{
public static $actions = [
'index' => self::GROUP_ADMIN,
];
public static $infos = [];
/**
* Dashboard
*/
public function index()
{
self::$infos['webserver'] = $_SERVER['SERVER_SOFTWARE'];
self::$infos['php']['version'] = phpversion();
self::$infos['php']['extension'] = get_loaded_extensions();
self::$infos['system']['memory'] = memory_get_usage() . ' octets';
self::$infos['system']['peek'] = 'Pic de mémoire utilisée : ' . memory_get_peak_usage() . ' octets';
$loadAverage = sys_getloadavg();
self::$infos['system']['charge'] = 'Charge moyenne (1 min / 5 min / 15 min) : ' . implode(' / ', $loadAverage) . '</P>';
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Tableau de bord'),
'view' => 'index'
]);
}
}

View File

@ -0,0 +1,54 @@
<?php echo template::formOpen('dashboard'); ?>
<div class="row">
<div class="col1">
<?php echo template::button('dashboardFormBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl(false),
'value' => template::ico('home')
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>
<?php echo helper::translate('Système'); ?>
</h4>
<div class="row">
<div class="col6">
<p>
<?php echo helper::translate('Serveur Web'); ?>
</p>
<p>
<?php echo $module::$infos['webserver']; ?>
</p>
</div>
<div class="col6">
<p>
<?php echo helper::translate('PHP') . ' ' . $module::$infos['php']['version']; ?>
</p>
<p>
<?php echo implode(' - ', $module::$infos['php']['extension']); ?>
</p>
</div>
</div>
<div class="row">
<div class="col12">
<p>
<?php echo helper::translate('Mémoire'); ?>
</p>
<p>
<?php echo $module::$infos['system']['memory']; ?>
</p>
<p>
<?php echo $module::$infos['system']['charge']; ?>
</p>
<p>
<?php echo $module::$infos['system']['peek']; ?>
</p>
</div>
</div>
</div>
</div>
</div>

View File

@ -8,7 +8,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -30,8 +30,7 @@ class install extends common
'http://' => 'HTTP' 'http://' => 'HTTP'
]; ];
// Thèmes proposés à l'installation public static $updateButtonText = 'Réinstaller';
public static $themes = [];
public static $newVersion; public static $newVersion;
@ -50,33 +49,35 @@ class install extends common
'access' => false 'access' => false
]); ]);
} }
// Accès autorisé
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
//$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
$lang = $this->getInput('installLanguage'); $lang = $this->getInput('installLanguage');
// Place le cookie pour la suite de l'installation // Pour la suite de l'installation
setcookie('ZWII_UI', $lang, time() + 3600, helper::baseUrl(false, false), '', false, false); // setcookie('ZWII_UI', $lang, time() + 3600, helper::baseUrl(false, false), '', false, false);
$_SESSION['ZWII_UI'] = $this->getInput('installLanguage');
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'install/postinstall/' . $lang 'redirect' => helper::baseUrl() . 'install/postinstall'
]); ]);
} }
//Nettoyage anciennes installations
helper::deleteCookie('ZWII_CONTENT');
// Liste des langues UI disponibles // Liste des langues UI disponibles
if (is_dir(self::I18N_DIR)) { if (is_dir(self::I18N_DIR)) {
foreach ($this->getData(['languages']) as $lang => $value) { foreach ($this->getData(['language']) as $lang => $value) {
self::$i18nFiles[$lang] = self::$languages[$lang]; self::$i18nFiles[$lang] = self::$languages[$lang];
;
} }
} }
$this->addOutput([ $this->addOutput([
'display' => self::DISPLAY_LAYOUT_LIGHT, 'display' => self::DISPLAY_LAYOUT_LIGHT,
'title' => helper::translate('Installation'), 'title' => helper::translate('ZwiiCMS Installation'),
'view' => 'index' 'view' => 'index'
]); ]);
} }
@ -96,19 +97,13 @@ class install extends common
// Accès autorisé // Accès autorisé
else { else {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
//$this->getUser('permission', __CLASS__, __FUNCTION__) !== true &&
$this->isPost()
) {
$success = true; $success = true;
// Validation de la langue transmise
self::$i18nUI = $this->getUrl(2);
self::$i18nUI = array_key_exists(self::$i18nUI, self::$languages) ? self::$i18nUI : 'fr_FR';
// par défaut le contenu est la langue d'installation
self::$i18nContent = self::$i18nUI;
setcookie('ZWII_CONTENT', self::$i18nContent, time() + 3600, helper::baseUrl(false, false), '', helper::isHttps(), true);
// Double vérification pour le mot de passe // Double vérification pour le mot de passe
if ($this->getInput('installPassword', helper::FILTER_STRING_SHORT, true) !== $this->getInput('installConfirmPassword', helper::FILTER_STRING_SHORT, true)) { if ($this->getInput('installPassword', helper::FILTER_STRING_SHORT, true) !== $this->getInput('installConfirmPassword', helper::FILTER_STRING_SHORT, true)) {
self::$inputNotices['installConfirmPassword'] = 'Incorrect'; self::$inputNotices['installConfirmPassword'] = 'Incorrect';
@ -120,29 +115,56 @@ class install extends common
$userMail = $this->getInput('installMail', helper::FILTER_MAIL, true); $userMail = $this->getInput('installMail', helper::FILTER_MAIL, true);
$userId = $this->getInput('installId', helper::FILTER_ID, true); $userId = $this->getInput('installId', helper::FILTER_ID, true);
// Validation de la langue transmise
self::$i18nUI = $_SESSION['ZWII_UI'];
self::$i18nUI = array_key_exists(self::$i18nUI, self::$languages) ? self::$i18nUI : 'fr_FR';
// Stockage de la langue par défaut afin d'afficher le site dans cette langue lors de l'affichage de la bannière de connexion.
$this->setData(['config','defaultLanguageUI', self::$i18nUI], false);
// par défaut le contenu est la langue d'installation
$_SESSION['ZWII_SITE_CONTENT'] = self::$i18nUI;
// Création du dossier de langue avec le marqueur de langue par défaut
if (!is_dir(self::DATA_DIR . $_SESSION['ZWII_SITE_CONTENT'])) {
mkdir(self::DATA_DIR . $_SESSION['ZWII_SITE_CONTENT']);
touch(self::DATA_DIR . $_SESSION['ZWII_SITE_CONTENT'] . '/.default');
}
// Installation du site de test
$sample = false;
if (
$this->getInput('installDefaultData', helper::FILTER_BOOLEAN) === false
&& $_SESSION['ZWII_SITE_CONTENT'] === 'fr_FR'
) {
$sample = true;
}
$this->initData('page', $_SESSION['ZWII_SITE_CONTENT'], $sample);
$this->initData('module', $_SESSION['ZWII_SITE_CONTENT'], $sample);
$this->initData('locale', $_SESSION['ZWII_SITE_CONTENT'], $sample);
// Création de l'utilisateur si les données sont complétées. // Création de l'utilisateur si les données sont complétées.
// success retour de l'enregistrement des données // success retour de l'enregistrement des données
$success = $this->setData([ $this->setData([
'user', 'user',
$userId, $userId,
[ [
'firstname' => $userFirstname, 'firstname' => $userFirstname,
'forgot' => 0, 'forgot' => 0,
'group' => self::GROUP_ADMIN, 'group' => self::GROUP_ADMIN,
'profil' => 0,
'lastname' => $userLastname, 'lastname' => $userLastname,
'pseudo' => 'Admin', 'pseudo' => 'Admin',
'signature' => 1, 'signature' => 1,
'mail' => $userMail, 'mail' => $userMail,
'password' => $this->getInput('installPassword', helper::FILTER_PASSWORD, true), 'password' => $this->getInput('installPassword', helper::FILTER_PASSWORD, true),
'language' => self::$i18nUI 'language' => $_SESSION['ZWII_SITE_CONTENT']
] ]
]); ]);
// Compte créé, envoi du mail et création des données du site
if ($success) { // Formulaire complété envoi du mail
// Envoie le mail // Envoie le mail
// Sent contient true si réussite sinon code erreur d'envoi en clair // Sent contient true si réussite sinon code erreur d'envoi en clair
$sent = $this->sendMail( $this->sendMail(
$userMail, $userMail,
'Installation de votre site', 'Installation de votre site',
'Bonjour' . ' <strong>' . $userFirstname . ' ' . $userLastname . '</strong>,<br><br>' . 'Bonjour' . ' <strong>' . $userFirstname . ' ' . $userLastname . '</strong>,<br><br>' .
@ -150,33 +172,21 @@ class install extends common
'<strong>URL du site :</strong> <a href="' . helper::baseUrl(false) . '" target="_blank">' . helper::baseUrl(false) . '</a><br>' . '<strong>URL du site :</strong> <a href="' . helper::baseUrl(false) . '" target="_blank">' . helper::baseUrl(false) . '</a><br>' .
'<strong>Identifiant du compte :</strong> ' . $this->getInput('installId') . '<br>', '<strong>Identifiant du compte :</strong> ' . $this->getInput('installId') . '<br>',
null, null,
$this->getData(['config', 'smtp', 'from']), 'no-reply@localhost'
); );
// Installation du site de test // Nettoyage fr par défaut
if ( if (
$this->getInput('installDefaultData', helper::FILTER_BOOLEAN) === false $_SESSION['ZWII_SITE_CONTENT'] !== 'fr_FR'
&& self::$i18nContent === 'fr_FR'
) { ) {
$this->initData('page', self::$i18nContent, true); if (is_dir(self::DATA_DIR . 'fr_FR'))
$this->initData('module', self::$i18nContent, true); $this->deleteDir(self::DATA_DIR . 'fr_FR');
$this->setData(['module', 'blog', 'posts', 'mon-premier-article', 'userId', $userId]);
$this->setData(['module', 'blog', 'posts', 'mon-deuxieme-article', 'userId', $userId]);
$this->setData(['module', 'blog', 'posts', 'mon-troisieme-article', 'userId', $userId]);
}
// Jeu réduit pour les pages étrangères
if (self::$i18nContent !== 'fr_FR') {
$this->initData('page', self::$i18nContent, false);
$this->initData('module', self::$i18nContent, false);
// Supprime l'installation FR générée par défaut.
$this->removeDir(self::DATA_DIR . 'fr_FR');
} }
// Sauvegarder la configuration du Proxy // Sauvegarder la configuration du Proxy
$this->setData(['config', 'proxyType', $this->getInput('installProxyType')]); $this->setData(['config', 'proxyType', $this->getInput('installProxyType')], false);
$this->setData(['config', 'proxyUrl', $this->getInput('installProxyUrl')]); $this->setData(['config', 'proxyUrl', $this->getInput('installProxyUrl')], false);
$this->setData(['config', 'proxyPort', $this->getInput('installProxyPort', helper::FILTER_INT)]); $this->setData(['config', 'proxyPort', $this->getInput('installProxyPort', helper::FILTER_INT)], false);
// Images exemples livrées dans tous les cas // Images exemples livrées dans tous les cas
try { try {
@ -201,54 +211,30 @@ class install extends common
unlink(self::TEMP_DIR . 'files.tar'); unlink(self::TEMP_DIR . 'files.tar');
// Créer le dossier des fontes // Créer le dossier des fontes
if (!is_dir(self::DATA_DIR . 'fonts')) { if (!is_dir(self::DATA_DIR . 'font')) {
mkdir(self::DATA_DIR . 'fonts'); mkdir(self::DATA_DIR . 'font');
} }
// Installation du thème sélectionné
$dataThemes = json_decode(file_get_contents('core/module/install/ressource/themes/themes.json'), true);
$dataThemes = $dataThemes['themes'];
$themeFilename = $dataThemes[$this->getInput('installTheme', helper::FILTER_STRING_SHORT)]['filename'];
if ($themeFilename !== '') {
$theme = new theme;
$theme->import('core/module/install/ressource/themes/' . $themeFilename);
}
// Copie des thèmes dans les fichiers
if (!is_dir(self::FILE_DIR . 'source/theme')) {
mkdir(self::FILE_DIR . 'source/theme');
}
$this->copyDir('core/module/install/ressource/themes', self::FILE_DIR . 'source/theme');
unlink(self::FILE_DIR . 'source/theme/themes.json');
// Copie des langues de l'UI et génération de la base de données // Copie des langues de l'UI et génération de la base de données
if (is_dir(self::I18N_DIR) === false) { if (is_dir(self::I18N_DIR) === false) {
mkdir(self::I18N_DIR); mkdir(self::I18N_DIR);
} }
// Créer la base de données des langues // Créer la base de données des langues
copy('core/module/install/ressource/i18n/languages.json', self::DATA_DIR . 'languages.json');
$this->copyDir('core/module/install/ressource/i18n', self::I18N_DIR); $this->copyDir('core/module/install/ressource/i18n', self::I18N_DIR);
unlink(self::I18N_DIR . 'languages.json');
// Fixe l'adresse from pour les envois d'email // 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 // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl(true) . $this->getData(['locale', 'homePageId']), 'redirect' => helper::baseUrl(),
'notification' => $sent === true ? helper::translate('Installation terminée') : $sent, 'notification' => helper::translate('Installation terminée'),
'state' => ($sent === true && $success === true) ? true : null 'state' => true
]); ]);
} }
} // Force la sauvegarde
$this->saveDB('config');
// Affichage du formulaire
// Récupération de la liste des thèmes
$dataThemes = json_decode(file_get_contents('core/module/install/ressource/themes/themes.json'), true);
$dataThemes = $dataThemes['themes'];
self::$themes = helper::arrayColumn($dataThemes, 'name');
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
@ -264,10 +250,20 @@ class install extends common
*/ */
public function steps() public function steps()
{ {
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
switch ($this->getInput('step', helper::FILTER_INT)) { switch ($this->getInput('step', helper::FILTER_INT)) {
// Préparation // Préparation
case 1: case 1:
$success = true; $success = true;
$message = '';
// RAZ la mise à jour auto // RAZ la mise à jour auto
$this->setData(['core', 'updateAvailable', false]); $this->setData(['core', 'updateAvailable', false]);
// Backup du dossier Data // Backup du dossier Data
@ -275,43 +271,73 @@ class install extends common
// Sauvegarde htaccess // Sauvegarde htaccess
if ($this->getData(['config', 'autoUpdateHtaccess'])) { if ($this->getData(['config', 'autoUpdateHtaccess'])) {
$success = copy('.htaccess', '.htaccess' . '.bak'); $success = copy('.htaccess', '.htaccess' . '.bak');
$message = $success ? '' : 'Erreur de copie du fichier htaccess';
} }
// Nettoyage des fichiers d'installation précédents // 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 = $success || unlink(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 = $success || unlink(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 // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'display' => self::DISPLAY_JSON, 'display' => self::DISPLAY_JSON,
'content' => [ 'content' => [
'success' => $success, 'success' => $success,
'data' => null 'data' => $message
] ]
]); ]);
break; break;
// Téléchargement // Téléchargement
case 2: case 2:
file_put_contents(self::TEMP_DIR . 'update.tar.gz', helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.tar.gz')); $success = true;
$message = '';
$this->secure_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 = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.md5');
$md5origin = (explode(' ', $md5origin)); $md5origin = explode(' ', $md5origin);
$md5target = md5_file(self::TEMP_DIR . 'update.tar.gz'); $md5target = md5_file(self::TEMP_DIR . 'update.tar.gz');
// Vérifier si les checksums correspondent
if ($md5origin[0] === $md5target) {
$success = true;
$message = "";
} else {
$success = false;
$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 // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'display' => self::DISPLAY_JSON, 'display' => self::DISPLAY_JSON,
'content' => [ 'content' => [
'success' => $md5origin[0] === $md5target, 'success' => $success,
'data' => null 'data' => $message
] ]
]); ]);
break; break;
// Installation // Installation
case 3: case 3:
$success = true; $success = true;
$message = '';
// Check la réécriture d'URL avant d'écraser les fichiers // 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 // Décompression et installation
try { try {
// Décompression dans le dossier de fichier temporaires // Décompression dans le dossier de fichier temporaires
@ -320,8 +346,11 @@ class install extends common
// Installation // Installation
$pharData->extractTo(__DIR__ . '/../../../', null, true); $pharData->extractTo(__DIR__ . '/../../../', null, true);
} catch (Exception $e) { } catch (Exception $e) {
$success = $e->getMessage(); $message = $e->getMessage();
$success = false;
http_response_code(500);
} }
// Nettoyage du dossier // Nettoyage du dossier
if (file_exists(self::TEMP_DIR . 'update.tar.gz')) { if (file_exists(self::TEMP_DIR . 'update.tar.gz')) {
unlink(self::TEMP_DIR . 'update.tar.gz'); unlink(self::TEMP_DIR . 'update.tar.gz');
@ -329,21 +358,44 @@ class install extends common
if (file_exists(self::TEMP_DIR . 'update.tar')) { if (file_exists(self::TEMP_DIR . 'update.tar')) {
unlink(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 // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'display' => self::DISPLAY_JSON, 'display' => self::DISPLAY_JSON,
'content' => [ 'content' => [
'success' => $success, 'success' => $success,
'data' => $rewrite 'data' => $message,
] ]
]); ]);
break; break;
// Configuration // Configuration
case 4: case 4:
$success = true; $success = true;
$rewrite = $this->getInput('data'); $message = '';
// Réécriture d'URL
if ($rewrite === "true") { // Ajout des lignes dans le .htaccess /**
* Restaure le fichier htaccess
*/
// Recopie htaccess
if (
$this->getData(['config', 'autoUpdateHtaccess']) === true
) {
// L'écraser avec le backup
$success = copy('.htaccess.bak', '.htaccess');
if ($success === false) {
$message = helper::translate('La copie de sauvegarde du fichier htaccess n\'a pas été restaurée !');
http_response_code(500);
}
// Effacer le backup
unlink('.htaccess.bak');
} else {
/**
* Restaure la réécriture d'URL
*/
if (file_exists(self::DATA_DIR . '.rewrite')) { // Ajout des lignes dans le .htaccess
$fileContent = file_get_contents('.htaccess'); $fileContent = file_get_contents('.htaccess');
$rewriteData = PHP_EOL . $rewriteData = PHP_EOL .
'# URL rewriting' . PHP_EOL . '# URL rewriting' . PHP_EOL .
@ -356,65 +408,80 @@ class install extends common
'</IfModule>' . PHP_EOL . '</IfModule>' . PHP_EOL .
'# URL rewriting' . PHP_EOL; '# URL rewriting' . PHP_EOL;
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent); $fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
$r = file_put_contents( $success = $this->secure_file_put_contents(
'.htaccess', '.htaccess',
$fileContent $fileContent
); );
$success = $r === false ? false : true; unlink(self::DATA_DIR . '.rewrite');
} }
// Recopie htaccess
if (
$this->getData(['config', 'autoUpdateHtaccess']) &&
$success && file_exists('.htaccess.bak')
) {
// L'écraser avec le backup
$success = $success || copy('.htaccess.bak', '.htaccess');
// Effacer le backup
unlink('.htaccess.bak');
} }
/** /**
* Met à jour les dictionnaires des langues depuis les modèles installés * Met à jour les dictionnaires des langues depuis les nouveaux modèles installés
*/ */
require_once('core/module/install/ressource/defaultdata.php');
$installedLanguages = $this->getData(['language']);
$defaultLanguages = init::$defaultData['language'];
foreach ($installedLanguages as $key => $value) {
// Langues installées if (
$installedUI = $this->getData(['languages']); isset($defaultLanguages[$key]['date']) &&
$defaultLanguages[$key]['date'] > $value['date'] &&
isset($defaultLanguages[$key]['version']) &&
$defaultLanguages[$key]['version'] >= $value['version']
// Langues disponibles avec la mise à jour ) {
$store = json_decode(file_get_contents('core/module/install/ressource/i18n/languages.json'), true); copy('core/module/install/ressource/i18n/' . $key . '.json', self::I18N_DIR . $key . '.json');
$store = $store['languages']; $this->setData(['language', $key, $defaultLanguages[$key]]);
foreach ($installedUI as $key => $value) {
if ($store[$key]['version'] > $value['version']) {
echo copy('core/module/install/ressource/i18n/' . $key . '.json', self::I18N_DIR . $key . '.json');
$this->setData(['languages', $key, $store[$key]]);
} }
} }
// Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'display' => self::DISPLAY_JSON, 'display' => self::DISPLAY_JSON,
'content' => [ 'content' => [
'success' => $success, 'success' => $success,
'data' => null 'data' => $message
] ]
]); ]);
} }
} }
}
/** /**
* Mise à jour * Mise à jour
*/ */
public function update() public function update()
{ {
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
// Nouvelle version // Nouvelle version
self::$newVersion = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/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('Mise à jour');
}
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'display' => self::DISPLAY_LAYOUT_LIGHT, 'display' => self::DISPLAY_LAYOUT_LIGHT,
'title' => helper::translate('Mise à jour'), 'title' => helper::translate(self::$updateButtonText),
'view' => 'update' 'view' => 'update'
]); ]);
} }
}
} }

View File

@ -5,6 +5,7 @@ class init extends common
'config' => [ 'config' => [
'autoBackup' => true, 'autoBackup' => true,
'autoUpdate' => true, 'autoUpdate' => true,
'autoUpdateDelay' => 86400,
'autoUpdateHtaccess' => false, 'autoUpdateHtaccess' => false,
'favicon' => 'favicon.ico', 'favicon' => 'favicon.ico',
'faviconDark' => 'faviconDark.ico', 'faviconDark' => 'faviconDark.ico',
@ -25,10 +26,11 @@ class init extends common
'proxyType' => 'tcp://', 'proxyType' => 'tcp://',
'smtp' => [ 'smtp' => [
'enable' => false, 'enable' => false,
'from'=> 'no-reply@localhost'
], ],
'seo' => [ 'seo' => [
'robots' => true, 'robots' => true,
'keyApi' => 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX' 'openGraphImage' => 'screenshot.png'
], ],
'connect' => [ 'connect' => [
'timeout' => 600, 'timeout' => 600,
@ -44,33 +46,13 @@ class init extends common
] ]
], ],
'core' => [ 'core' => [
'dataVersion' => 12300, 'dataVersion' => 13000,
'lastBackup' => 0, 'lastBackup' => 0,
'lastClearTmp' => 0, 'lastClearTmp' => 0,
'lastAutoUpdate' => 0, 'lastAutoUpdate' => 0,
'updateAvailable' => false 'updateAvailable' => false
], ],
'locale' => [ 'font' => [
'homePageId' => 'accueil',
'page302' => 'none',
'page403' => 'none',
'page404' => 'none',
'legalPageId' => 'none',
'searchPageId' => 'none',
'searchPageLabel' => 'Rechercher',
'sitemapPageLabel' => 'Plan du site',
'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 !',
'cookies' => [
'mainLabel' => 'Ce site utilise des cookies nécessaires à son fonctionnement, ils permettent de fluidifier son fonctionnement par exemple en mémorisant les données de connexion, la langue que vous avez choisie ou la validation de ce message.',
'titleLabel' => 'Cookies essentiels',
'linkLegalLabel' => 'Consulter les mentions légales',
'cookiesFooterText' => 'Cookies',
'buttonValidLabel' => 'J\'ai compris'
]
],
'fonts' => [
'files' => [], 'files' => [],
'imported' => [ 'imported' => [
'arimo' => [ 'arimo' => [
@ -175,37 +157,6 @@ class init extends common
] ]
] ]
], ],
'page' => [
'accueil' => [
'typeMenu' => 'text',
'iconUrl' => '',
'disable' => false,
'content' => 'accueil.html',
'hideTitle' => false,
'homePageId' => true,
'breadCrumb' => false,
'metaDescription' => '',
'metaTitle' => '',
'moduleId' => '',
'modulePosition' => 'bottom',
'parentPageId' => '',
'position' => 1,
'group' => self::GROUP_VISITOR,
'targetBlank' => false,
'title' => 'Accueil',
'shortTitle' => 'Accueil',
'block' => '12',
'barLeft' => '',
'barRight' => '',
'displayMenu' => 'none',
'hideMenuSide' => false,
'hideMenuChildren' => false,
'extraPosition' => false,
'css' => '',
'js' => ''
]
],
'module' => [],
'user' => [], 'user' => [],
'theme' => [ 'theme' => [
'body' => [ 'body' => [
@ -330,13 +281,489 @@ class init extends common
'backgroundColorButtonGreen' => 'rgba(100, 207, 8, 1)', 'backgroundColorButtonGreen' => 'rgba(100, 207, 8, 1)',
'backgroundColorButtonHelp' => 'rgba(255, 153, 0, 1)', 'backgroundColorButtonHelp' => 'rgba(255, 153, 0, 1)',
'backgroundBlockColor' => 'rgba(236, 239, 241, 1)', 'backgroundBlockColor' => 'rgba(236, 239, 241, 1)',
'borderBlockColor' => 'rgba(190, 202, 209, 1)' 'borderBlockColor' => 'rgba(190, 202, 209, 1)',
'width' => '960px'
], ],
'blacklist' => [], 'blacklist' => [],
'languages'=> [], 'language' => [
"fr_FR" => [
"version" => 13500,
"date" => 1734641934
],
"es" => [
"version" => 13500,
"date" => 1734641934
],
"en_EN" => [
"version" => 13500,
"date" => 1734641934
]
],
'profil' => [
'-1' => [
'name' => 'Banni',
'readonly' => true,
'permanent' => true,
'comment' => 'Accès désactivé',
],
'0' => [
'name' => 'Visiteur',
'readonly' => true,
'permanent' => true,
'comment' => 'Accède au site',
],
'1' => [
'1' => [
'name' => 'Membre simple',
'readonly' => false,
'permanent' => true,
'comment' => 'Accède aux pages réservées',
'filemanager' => false,
'file' => [
'download' => false,
'edit' => false,
'create' => false,
'rename' => false,
'upload' => false,
'delete' => false,
'preview' => false,
'duplicate' => false,
'extract' => false,
'copycut' => false,
'chmod' => false
],
'folder' => [
'create' => false,
'delete' => false,
'rename' => false,
'copycut' => false,
'chmod' => false,
'share' => false,
'path' => null,
],
'page' => [
'add' => false,
'delete' => false,
'duplicate' => false,
'edit' => false,
'jsEditor' => false,
'cssEditor' => false,
'module' => false,
],
'blog' => [
'add' => false,
'delete' => false,
'edit' => false,
'option' => false,
'config' => false,
'comment' => false,
'commentApprove' => false,
'commentDelete' => false,
'commentDeleteAll' => false,
],
'form' => [
'option' => false,
'config' => false,
'data' => false,
'delete' => false,
'deleteAll' => false,
'export2csv' => false,
],
'gallery' => [
'config' => false,
'delete' => false,
'edit' => false,
'add' => false,
'option' => false,
'theme' => false,
],
'news' => [
'add' => false,
'config' => false,
'option' => false,
'delete' => false,
'edit' => false,
],
'redirection' => [
'config' => false,
],
'search' => [
'config' => false,
],
'user' => [
'edit' => true,
]
],
'2' => [
'name' => 'Membre avec droit de partage',
'readonly' => false,
'permanent' => false,
'comment' => 'Accède aux pages réservées et à un dossier partagé',
'filemanager' => true,
'file' => [
'download' => false,
'edit' => false,
'create' => false,
'rename' => false,
'upload' => false,
'delete' => false,
'preview' => false,
'duplicate' => false,
'extract' => false,
'copycut' => false,
'chmod' => false
],
'folder' => [
'create' => false,
'delete' => false,
'rename' => false,
'copycut' => false,
'chmod' => false,
'share' => true,
'path' => '/site/file/source/partage/',
],
'page' => [
'add' => false,
'delete' => false,
'duplicate' => false,
'edit' => false,
'jsEditor' => false,
'cssEditor' => false,
'module' => false,
],
'blog' => [
'add' => false,
'delete' => false,
'edit' => false,
'option' => false,
'config' => false,
'comment' => false,
'commentApprove' => false,
'commentDelete' => false,
'commentDeleteAll' => false,
],
'form' => [
'option' => false,
'config' => false,
'data' => false,
'delete' => false,
'deleteAll' => false,
'export2csv' => false,
],
'gallery' => [
'config' => false,
'delete' => false,
'edit' => false,
'add' => false,
'option' => false,
'theme' => false,
'dirs' => false,
'sortGalleries' => false,
'sortPictures' => false,
],
'news' => [
'add' => false,
'config' => false,
'option' => false,
'delete' => false,
'edit' => false,
],
'redirection' => [
'config' => false,
],
'search' => [
'config' => false,
],
'user' => [
'edit' => true,
]
],
],
'2' => [
'1' => [
'name' => 'Éditeur simple',
'readonly' => false,
'permanent' => true,
'comment' => 'Édition des pages',
'filemanager' => true,
'file' => [
'download' => true,
'edit' => true,
'create' => true,
'rename' => true,
'upload' => true,
'delete' => false,
'preview' => true,
'duplicate' => false,
'extract' => false,
'copycut' => false,
'chmod' => false
],
'folder' => [
'create' => false,
'delete' => false,
'rename' => false,
'copycut' => false,
'chmod' => false,
'share' => true,
'path' => '/site/file/source/partage/',
],
'page' => [
'add' => false,
'delete' => false,
'duplicate' => false,
'edit' => true,
'jsEditor' => true,
'cssEditor' => true,
'module' => true,
],
'blog' => [
'add' => true,
'delete' => false,
'edit' => true,
'option' => false,
'config' => false,
'comment' => false,
'commentApprove' => false,
'commentDelete' => false,
'commentDeleteAll' => false,
],
'form' => [
'option' => false,
'config' => false,
'data' => false,
'delete' => false,
'deleteAll' => false,
'export2csv' => false,
],
'gallery' => [
'config' => false,
'delete' => false,
'edit' => false,
'add' => false,
'option' => false,
'theme' => false,
],
'news' => [
'add' => true,
'config' => false,
'option' => false,
'delete' => false,
'edit' => true,
],
'redirection' => [
'config' => false,
],
'search' => [
'config' => false,
],
'user' => [
'edit' => true,
]
],
'2' => [
'name' => 'Rédacteur',
'readonly' => false,
'permanent' => false,
'comment' => 'Tous les droits d\'édition des contenus',
'filemanager' => true,
'file' => [
'download' => true,
'edit' => true,
'create' => true,
'rename' => true,
'upload' => true,
'delete' => true,
'preview' => true,
'duplicate' => true,
'extract' => true,
'copycut' => true,
'chmod' => true
],
'folder' => [
'create' => true,
'delete' => true,
'rename' => true,
'copycut' => true,
'chmod' => true,
'share' => true,
'path' => '/site/file/source/partage/',
],
'page' => [
'add' => true,
'delete' => true,
'duplicate' => true,
'edit' => true,
'jsEditor' => true,
'cssEditor' => true,
'module' => true,
],
'blog' => [
'add' => true,
'delete' => true,
'edit' => true,
'option' => true,
'config' => true,
'comment' => true,
'commentApprove' => true,
'commentDelete' => true,
'commentDeleteAll' => true,
],
'form' => [
'option' => true,
'config' => true,
'data' => true,
'delete' => true,
'deleteAll' => true,
'export2csv' => true,
],
'gallery' => [
'config' => true,
'delete' => true,
'edit' => true,
'add' => true,
'option' => true,
'theme' => true,
],
'news' => [
'add' => true,
'config' => true,
'option' => true,
'delete' => true,
'edit' => true,
],
'redirection' => [
'config' => true,
],
'search' => [
'config' => true,
],
'user' => [
'edit' => true,
]
],
],
'3' => [
'name' => 'Administrateur',
'readonly' => true,
'permanent' => true,
'comment' => 'Contrôle total',
]
]
]; ];
public static $defaultDataI18n = [ public static $defaultDataI18n = [
'en_EN' => [ 'fr_FR' => [
'locale' => [
'homePageId' => 'accueil',
'page302' => 'none',
'page403' => 'none',
'page404' => 'none',
'legalPageId' => 'none',
'searchPageId' => 'none',
'searchPageLabel' => 'Rechercher',
'sitemapPageLabel' => 'Plan du site',
'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 !',
'cookies' => [
'mainLabel' => 'Ce site utilise des cookies nécessaires à son fonctionnement, ils permettent de fluidifier son fonctionnement par exemple en mémorisant les données de connexion, la langue que vous avez choisie ou la validation de ce message.',
'titleLabel' => 'Cookies essentiels',
'linkLegalLabel' => 'Consulter les mentions légales',
'cookiesFooterText' => 'Cookies',
'buttonValidLabel' => 'J\'ai compris'
]
],
'page' => [
'accueil' => [
'typeMenu' => 'text',
'iconUrl' => '',
'disable' => false,
'content' => 'accueil.html',
'hideTitle' => false,
'homePageId' => true,
'breadCrumb' => false,
'metaDescription' => '',
'metaTitle' => '',
'moduleId' => '',
'modulePosition' => 'bottom',
'parentPageId' => '',
'position' => 1,
'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false,
'title' => 'Accueil',
'shortTitle' => 'Accueil',
'block' => '12',
'barLeft' => '',
'barRight' => '',
'displayMenu' => 'none',
'hideMenuSide' => false,
'hideMenuChildren' => false,
'extraPosition' => false,
'css' => '',
'js' => ''
]
],
'module' => [],
'html' => '<h2>Bienvenue dans cette nouvelle installation de ZwiiCMS. Créez et gérez votre site facilement avec notre système convivial.</h2>'
],
'es' => [
'locale' => [
'homePageId' => 'inicio',
'page302' => 'none',
'page403' => 'none',
'page404' => 'none',
'legalPageId' => 'none',
'searchPageId' => 'none',
'searchPageLabel' => 'none',
'sitemapPageLabel' => 'none',
'legalPageLabel' => 'legales',
"metaDescription" => "Zwii es un CMS sin base de datos que facilita la creación y gestión de un sitio web sin necesidad de conocimientos de programación.",
"title" => "¡Tu sitio en unos clics!",
"cookies" => [
"mainLabel" => "Este sitio web utiliza cookies necesarias para su funcionamiento. Estas cookies permiten optimizar su funcionamiento, por ejemplo, memorizando los datos de conexión, el idioma que has elegido o la validación de este mensaje.",
"titleLabel" => "Cookies esenciales",
"linkLegalLabel" => "Consultar el aviso legal",
"cookiesFooterText" => "Cookies",
"buttonValidLabel" => "Aceptar"
]
],
'page' => [
'inicio' => [
'typeMenu' => 'text',
'iconUrl' => '',
'disable' => false,
'content' => 'inico.html',
'hideTitle' => false,
'homePageId' => true,
'breadCrumb' => false,
'metaDescription' => '',
'metaTitle' => '',
'moduleId' => '',
'modulePosition' => 'bottom',
'parentPageId' => '',
'position' => 1,
'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false,
'title' => 'Página de inicio',
'shortTitle' => 'Página de inicio',
'block' => '12',
'barLeft' => '',
'barRight' => '',
'displayMenu' => 'none',
'hideMenuSide' => false,
'hideMenuChildren' => false,
'extraPosition' => false,
'css' => '',
'js' => ''
]
],
'module' => [],
'html' => '<h2>¡Bienvenido/a a esta nueva instalación de ZwiiCMS!</h2><p>Crea y administra tu sitio web de manera sencilla con nuestro sistema amigable.</p><p>Esta es tu primera página, inicia sesión para crear nuevas.</p>'
],
'default' => [
'locale' => [ 'locale' => [
'homePageId' => 'home', 'homePageId' => 'home',
'page302' => 'none', 'page302' => 'none',
@ -346,6 +773,7 @@ class init extends common
'searchPageId' => 'none', 'searchPageId' => 'none',
'searchPageLabel' => 'none', 'searchPageLabel' => 'none',
'sitemapPageLabel' => 'none', 'sitemapPageLabel' => 'none',
'poweredPageLabel' => 'Powered by',
'legalPageLabel' => 'legals', 'legalPageLabel' => 'legals',
'metaDescription' => 'Zwii is a database-free CMS that makes it easy to create and manage a website without any programming knowledge.', 'metaDescription' => 'Zwii is a database-free CMS that makes it easy to create and manage a website without any programming knowledge.',
'title' => 'Your site in a few clicks!', 'title' => 'Your site in a few clicks!',
@ -373,6 +801,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 1, 'position' => 1,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Home page', 'title' => 'Home page',
'shortTitle' => 'Home', 'shortTitle' => 'Home',
@ -387,12 +816,11 @@ class init extends common
'js' => '' 'js' => ''
] ]
], ],
'html' => 'Welcome in this ZwiiCMS, congratulations this is you first page !' 'module' => [],
'html' => '<h2>Welcome to this new installation of ZwiiCMS.</h2><p>Easily create and manage your website with our user-friendly system.</p><p>This is your first page, log in to create new ones.</p>'
] ]
]; ];
public static $siteTemplate = [
public static $siteData = [
'page' => [ 'page' => [
'accueil' => [ 'accueil' => [
'typeMenu' => 'text', 'typeMenu' => 'text',
@ -409,6 +837,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 1, 'position' => 1,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Accueil', 'title' => 'Accueil',
'shortTitle' => 'Accueil', 'shortTitle' => 'Accueil',
@ -436,6 +865,7 @@ class init extends common
'parentPageId' => 'accueil', 'parentPageId' => 'accueil',
'position' => 1, 'position' => 1,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Page Enfant', 'title' => 'Page Enfant',
'shortTitle' => 'Enfant', 'shortTitle' => 'Enfant',
@ -463,6 +893,7 @@ class init extends common
'modulePosition' => 'bottom', 'modulePosition' => 'bottom',
'position' => 2, 'position' => 2,
'group' => self::GROUP_MEMBER, 'group' => self::GROUP_MEMBER,
'profil' => 1,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Page privée', 'title' => 'Page privée',
'shortTitle' => 'Privée', 'shortTitle' => 'Privée',
@ -490,6 +921,7 @@ class init extends common
'modulePosition' => 'bottom', 'modulePosition' => 'bottom',
'position' => 2, 'position' => 2,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Mise en page', 'title' => 'Mise en page',
'shortTitle' => 'Mise en page', 'shortTitle' => 'Mise en page',
@ -517,6 +949,7 @@ class init extends common
'modulePosition' => 'bottom', 'modulePosition' => 'bottom',
'position' => 3, 'position' => 3,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Barre latérale avec menu', 'title' => 'Barre latérale avec menu',
'shortTitle' => 'Menu latéral', 'shortTitle' => 'Menu latéral',
@ -544,6 +977,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 3, 'position' => 3,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Blog', 'title' => 'Blog',
'shortTitle' => 'Blog', 'shortTitle' => 'Blog',
@ -571,6 +1005,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 4, 'position' => 4,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Galeries d\'images', 'title' => 'Galeries d\'images',
'shortTitle' => 'Galeries', 'shortTitle' => 'Galeries',
@ -599,6 +1034,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 5, 'position' => 5,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => true, 'targetBlank' => true,
'title' => 'Site de Zwii', 'title' => 'Site de Zwii',
'shortTitle' => 'Site de Zwii', 'shortTitle' => 'Site de Zwii',
@ -626,6 +1062,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 6, 'position' => 6,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Contact', 'title' => 'Contact',
'shortTitle' => 'Contact', 'shortTitle' => 'Contact',
@ -653,6 +1090,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 0, 'position' => 0,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Barre latérale', 'title' => 'Barre latérale',
'shortTitle' => 'Barre latérale', 'shortTitle' => 'Barre latérale',
@ -680,6 +1118,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 0, 'position' => 0,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Barre latérale avec menu', 'title' => 'Barre latérale avec menu',
'shortTitle' => 'Barre latérale avec menu', 'shortTitle' => 'Barre latérale avec menu',
@ -706,7 +1145,8 @@ class init extends common
'modulePosition' => 'bottom', 'modulePosition' => 'bottom',
'parentPageId' => '', 'parentPageId' => '',
'position' => 0, 'position' => 0,
'group' => 0, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Mentions légales', 'title' => 'Mentions légales',
'shortTitle' => 'Mentions légales', 'shortTitle' => 'Mentions légales',
@ -735,6 +1175,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 0, 'position' => 0,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Maintenance en cours', 'title' => 'Maintenance en cours',
'shortTitle' => 'Maintenance en cours', 'shortTitle' => 'Maintenance en cours',
@ -763,6 +1204,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 0, 'position' => 0,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Erreur 403', 'title' => 'Erreur 403',
'shortTitle' => 'Erreur 403', 'shortTitle' => 'Erreur 403',
@ -790,6 +1232,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 0, 'position' => 0,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Erreur 404', 'title' => 'Erreur 404',
'shortTitle' => 'Erreur 404', 'shortTitle' => 'Erreur 404',
@ -817,6 +1260,7 @@ class init extends common
'parentPageId' => '', 'parentPageId' => '',
'position' => 7, 'position' => 7,
'group' => self::GROUP_VISITOR, 'group' => self::GROUP_VISITOR,
'profil' => 0,
'targetBlank' => false, 'targetBlank' => false,
'title' => 'Recherche dans le site', 'title' => 'Recherche dans le site',
'shortTitle' => 'Rechercher', 'shortTitle' => 'Rechercher',
@ -855,11 +1299,11 @@ class init extends common
'picturePosition' => 'left', 'picturePosition' => 'left',
'hidePicture' => false, 'hidePicture' => false,
'pictureSize' => 20, 'pictureSize' => 20,
'picturePosition' => 'left',
'publishedOn' => 1548790902, 'publishedOn' => 1548790902,
'state' => true, 'state' => true,
'title' => 'Mon premier article', 'title' => 'Mon premier article',
'userId' => '', // Géré au moment de l'installation 'userId' => '',
// Géré au moment de l'installation
'editConsent' => 'all', 'editConsent' => 'all',
'commentMaxlength' => '500', 'commentMaxlength' => '500',
'commentApproved' => false, 'commentApproved' => false,
@ -875,11 +1319,11 @@ class init extends common
'hidePicture' => false, 'hidePicture' => false,
'picturePosition' => 'right', 'picturePosition' => 'right',
'pictureSize' => 40, 'pictureSize' => 40,
'picturePosition' => 'right',
'publishedOn' => 1550432502, 'publishedOn' => 1550432502,
'state' => true, 'state' => true,
'title' => 'Mon deuxième article', 'title' => 'Mon deuxième article',
'userId' => '', // Géré au moment de l'installation 'userId' => '',
// Géré au moment de l'installation
'editConsent' => 'all', 'editConsent' => 'all',
'commentMaxlength' => '500', 'commentMaxlength' => '500',
'commentApproved' => false, 'commentApproved' => false,
@ -895,11 +1339,11 @@ class init extends common
'hidePicture' => false, 'hidePicture' => false,
'picturePosition' => 'left', 'picturePosition' => 'left',
'pictureSize' => 100, 'pictureSize' => 100,
'picturePosition' => 'left',
'publishedOn' => 1550864502, 'publishedOn' => 1550864502,
'state' => true, 'state' => true,
'title' => 'Mon troisième article', 'title' => 'Mon troisième article',
'userId' => '', // Géré au moment de l'installation 'userId' => '',
// Géré au moment de l'installation
'editConsent' => 'all', 'editConsent' => 'all',
'commentMaxlength' => '500', 'commentMaxlength' => '500',
'commentApproved' => false, 'commentApproved' => false,
@ -1020,9 +1464,20 @@ class init extends common
'page404' => 'none', 'page404' => 'none',
'legalPageId' => 'none', 'legalPageId' => 'none',
'searchPageId' => 'none', 'searchPageId' => 'none',
'poweredPageLabel' => 'Motorisé par',
'searchPageLabel' => 'Rechercher',
'sitemapPageLabel' => 'Plan du site',
'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.', '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 !' 'title' => 'Votre site en quelques clics !',
'cookies' => [
'mainLabel' => 'Ce site utilise des cookies nécessaires à son fonctionnement, ils permettent de fluidifier son fonctionnement par exemple en mémorisant les données de connexion, la langue que vous avez choisie ou la validation de ce message.',
'titleLabel' => 'Cookies essentiels',
'linkLegalLabel' => 'Consulter les mentions légales',
'cookiesFooterText' => 'Cookies',
'buttonValidLabel' => 'J\'ai compris'
] ]
],
]; ];
public static $siteContent = [ public static $siteContent = [

View File

@ -0,0 +1,693 @@
{
"'Ne pas afficher' crée une page orpheline non accessible par le biais des menus.": "\"Nicht anzeigen\" erstellt eine Orphan -Seite, die über Menüs nicht zugegriffen werden kann.",
"'Sauvegarder et télécharger les données du module": "'Speichern und herunterladen Moduldaten",
"1 jour": "1 tag",
"1/4 : Préparation...": "1/4: Vorbereitung ...",
"10 minutes": "10 Minuten",
"10 tentatives": "10 Versuche",
"14 jours": "14 Tage",
"15 minutes": "15 Minuten",
"2 jours": "2 Tage",
"2/4 : Téléchargement...": "2/4: Download ...",
"3 tentatives": "3 Versuche",
"3/4 : Installation...": "3/4: Installation ...",
"4 jours": "4 Tage",
"4/4 : Configuration...": "4/4: Konfiguration ...",
"5 minutes": "5 Minuten",
"5 tentatives": "5 Versuche",
"7 jours": "7 Tage",
"Accueil": "Willkommen",
"Accède au site": "Zugriff auf die Website",
"Accède aux pages réservées": "Zugriff auf gesperrte Seiten",
"Accède aux pages réservées et à un dossier partagé": "Zugriff auf gesperrte Seiten und einen freigegebenen Ordner",
"Accès bloqué %d minutes": "Blockierter Zugang %der Minuten",
"Accès désactivé": "Zugriff deaktiviert",
"Accès interdit, erreur 403": "Zugriff verboten, Fehler 403",
"Action interdite": "Verbotene Aktion",
"Activation obligatoire selon les lois françaises sauf si vous utilisez votre propre système de consentement.": "Obligatorische Aktivierung gemäß den französischen Gesetzen, es sei denn, Sie verwenden Ihr eigenes Einverständnissystem.",
"Activer": "Ermöglichen",
"Activer la journalisation": "Journalisierung aktivieren",
"Actualiser": "Aktualisieren",
"Adaptation": "Anpassung",
"Administrateur": "Administrator",
"Administration": "Verwaltung",
"Adresse SMTP": "Adresse SMTP",
"Adresse du proxy": "Proxy-Adresse",
"Adresse électronique": "E-Mail-Addresse",
"Affectation": "Affektiertheit",
"Affiche le nom de la page parente suivi du nom de la page, le titre ne doit pas être masqué.": "Zeigt den Namen der Parente -Seite an, gefolgt vom Seitennamen, der Titel sollte nicht maskiert werden.",
"Affiche les icônes de gestion du compte et de déconnexion des membres simples connectés": "Zeigt die Symbole zur Kontoverwaltung und Abmeldung von eingeloggten Standardmitgliedern an",
"Afin d'assurer le bon fonctionnement de Zwii, veuillez ne pas fermer cette page avant la fin de l'opération.": "Um das ordnungsgemäße Funktionieren von Zwii zu gewährleisten, schließen Sie diese Seite bitte nicht vor dem Ende der Operation.",
"Aide": "Berater",
"Ajouter": "Hinzufügen",
"Ajouter un profil": "Profil hinzufügen",
"Ajouter un utilisateur": "Fügen Sie einen Benutzer hinzu",
"Ajouter une fonte": "Fügen Sie eine Schriftart hinzu",
"Alignement": "Ausrichtung des Inhalts",
"Aligner la bannière avec le contenu": "Richten Sie das Banner mit dem Inhalt aus",
"Ancien mot de passe": "Altes Passwort",
"Anonymat des adresses IP": "Anonymität von IP -Adressen",
"Apache URL intelligent": "Apache URL intelligent",
"Apache URL intelligentes": "Apache URL intelligentes",
"Apparence": "Aussehen",
"Appliquer": "Anwenden",
"Approuver un commentaire": "Kommentare genehmigen",
"Après": "Nach",
"Après la bannière": "Nach dem Banner",
"Après le contenu de la page": "Nach dem Inhalt der Seite",
"Archive": "Archiv",
"Archive ZIP": "Archiv Reißverschluss",
"Archive copiée dans le dossier Modules du gestionnaire de fichier": "Archiv kopiert in den Dateimodulen des Dateimanagers",
"Archive de thème invalide": "Ungültiges Themenarchiv",
"Archive invalide": "Archive Invalide",
"Archive invalide, l'écriture dans le dossier core est interdite": "Ungültiges Archiv, das Schreiben in der Kerndatei ist verboten",
"Archive invalide, le descripteur est absent": "Ungültiges Archiv, der Deskriptor fehlt",
"Archive invalide, le fichier de classe est absent": "Invalide -Archiv, die Klassendatei fehlt",
"Archive invalide, les dossiers ne correspondent pas au descripteur": "Ungültiges Archiv entsprechen die Dateien nicht dem Deskriptor",
"Archive non spécifiée ou introuvable": "Archiv nicht angegeben oder nicht gefunden",
"Archive à restaurer": "Archiv zur Wiederherstellung",
"Arrière plan": "Hintergrund",
"Arrière plan des blocs": "Hintergrund der Blöcke",
"Arrière plan des champs": "Hintergrund",
"Arrondi des angles": "Rundung der Winkel",
"Au centre": "Im Zentrum",
"Au début": "Anfangs",
"Au milieu au centre": "In der Mitte in der Mitte",
"Au milieu à droite": "In der mittleren rechts",
"Au milieu à gauche": "In der Mitte links",
"Au-dessus du site": "Über der Seite",
"Aucun": "Kein",
"Aucun dossier": "Kein Verzeichnis",
"Aucun fichier journal à télécharger": "Keine Protokolldatei zum Herunterladen",
"Aucun journal à effacer": "Keine Zeitung zum Löschen",
"Aucun menu": "Kein Menü",
"Aucune": "Keine",
"Aucune liste noire à effacer": "Keine schwarze Liste zu löschen",
"Aucune liste noire à télécharger": "Keine schwarze Liste zum Herunterladen",
"Auteur :": "Auteur:",
"Authentification": "Authentifizierung",
"Automatique": "Automatik",
"Autoriser les robots à référencer le site": "Erlauben Sie Robotern, auf die Site zu verweisen",
"Autorisé": "Erlaubt",
"Avant la bannière": "Vor dem Banner",
"Avant le contenu de la page": "Vor dem Inhalt der Seite",
"Background": "Hintergrund",
"Banni": "Verbot",
"Bannière": "Banner",
"Bannière cliquable": "Klickbares Banner",
"Barre 1/3 - page 2/3": "Barre 1/3 - Seite 2/3",
"Barre 1/4 - page 1/2 - barre 1/4": "Barre 1/4 - Seite 1/2 - Barre 1/4",
"Barre 1/4 - page 3/4": "Barre 1/4 - Seite 3/4",
"Barre 2/12 - page 7/12 - barre 3/12": "Barre 2/12 - Seite 7/12 - Barre 3/12",
"Barre 3/12 - page 7/12 - barre 2/12": "Barre 3/12 - Seite 7/12 - Barre 2/12",
"Barre de membre": "Mitgliederleiste",
"Barre latérale": "Seitliche Bar",
"Barre latérale droite :": "Rechte Sidebar:",
"Barre latérale gauche :": "Linke Seitenstange:",
"Barres latérales": "Seitenstangen",
"Bienvenue %s %s": "Willkommen %s %",
"Blocage après échecs": "Blockieren nach Fehlern",
"Blog": "Blog",
"Bords arrondis": "Abgerundete Kanten",
"Bordure des blocs": "Blockgrenze",
"Bordure des champs": "Feldgrenze",
"Bouton Aide": "Hilfeknopf",
"Bouton Standard": "Bouton Standard",
"Bouton de validation": "Validierungstaste",
"Bouton effacement": "Löschen",
"Bouton retour": "Rückgabeknopf",
"Bouton standard": "Bouton Standard",
"Bouton validation": "Bouton -Validierung",
"Boutons": "Boutons",
"Caché": "Versteckt",
"Cachée": "Versteckt",
"Captcha complexe": "Captcha Complexe",
"Captcha à la connexion": "Captcha in Verbindung",
"Captcha, identifiant ou mot de passe incorrects": "Captcha, falsche Kennung oder Passwort",
"Capture d'écran Open Graph": "Graph Screenshot öffnen",
"Capture d'écran générée avec succès": "Erfolgreicher generierter Screenshot",
"Casse": "Gebrochen",
"Catalogue": "Katalog",
"Catégorie": "Kategorie",
"Ce membre pourra téléverser ou télécharger des fichiers dans le dossier 'partage' et ses sous-dossiers": "Dieses Mitglied kann Dateien im Ordner \"Freigeben\" und in seinen Unterordnern festlegen oder herunterladen",
"Cette page ne doit pas apparaître dans l'arborescence du menu. Créez une page orpheline.": "Diese Seite sollte nicht im Menübaum angezeigt werden. Erstellen Sie eine Waisenseite.",
"Cette redirection ne concerne que les pages d'administration du site.": "Diese Umleitung betrifft nur die Verwaltungsseiten der Website.",
"Chaîne Youtube": "Youtube Kanal",
"Chiffres": "Zahlen",
"Cible": "Ziel",
"Cliquez sur une zone afin d'accéder à ses options de personnalisation.": "Klicken Sie auf einen Bereich, um auf die Anpassungsoptionen zuzugreifen.",
"Commentaire": "Kommentar",
"Complète": "Vollständig",
"Compte administrateur": "Administrator",
"Compte de l'utilisateur": "Benutzerkonto",
"Compte verrouillé": "Gesperrt",
"Configuration": "Aufbau",
"Configuration du module": "Konfigurations -DU -Modul",
"Configurer": "Konfigurieren",
"Configurer mon compte": "Konfigurieren Sie mein Konto",
"Confirmation": "Bestätigung",
"Confirmer la suppression de cet utilisateur": "Bestätigen Sie die Löschung dieses Benutzers",
"Confirmer la dissociation du module de cette page": "Bestätigen Sie die Dissoziation des Moduls dieser Seite",
"Confirmer la désinstallation du module": "Bestätigen Sie das Deinstallieren des Moduls",
"Confirmer la suppression de cet utilisateur": "Bestätigen Sie die Löschung dieses Benutzers",
"Confirmer la suppression de cette langue": "Bestätigen Sie das Löschen dieser Sprache",
"Confirmer la suppression de la page": "Bestätigen Sie die Löschung der Seite",
"Confirmer la suppression des données du module": "Bestätigen Sie die Löschung der Moduldaten",
"Confirmez-vous la suppression de cette page ?": "Bestätigen Sie die Löschung dieser Seite?",
"Connexion": "Verbindung",
"Consulter l'aide en ligne": "Online -Hilfe konsultieren",
"Contents": "Inhalt",
"Contenu": "Inhalt",
"Contenu HTML": "HTML enthalten",
"Contenu avancé": "Fortgeschrittene Inhalt",
"Contenu du menu vertical": "Da fällige Vertikale enthalten",
"Contrôle total": "Vollständige Kontrolle",
"Cookies": "Kekse",
"Cookies Zwii": "Kekse Zwii",
"Copie de contenus localisés": "Lokalisierte Inhaltskopie",
"Copie de sites inter-langues": "Kopie von Intersprage-Websites",
"Copie des traductions rédigées": "Kopie der schriftlichen Übersetzungen",
"Copie terminée avec des erreurs": "Kopieren Sie mit Fehlern fertig",
"Copie terminée avec succès": "Erfolgreich abgeschlossen sein",
"Copier": "Kopierer",
"Copier sauvegardes auto": "Kopieren Sie automatische Sicherungen",
"Couleur de fond automatique": "Automatische Hintergrundfarbe",
"Couleur icône haut de page": "Farbe des Icons oben auf der Seite",
"Couleur texte page active": "Textfarbe der aktiven Seite",
"Couleur unie ou papier-peint": "Farbe oder Tapete vereinigte Tapete",
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence.": "Sichtbare Farbe in Abwesenheit eines Bildes. <br /> Der horizontale Cursor reguliert das Transparenzniveau.",
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence. La couleur du texte est automatique.": "Sichtbare Farbe in Abwesenheit eines Bildes. <br /> Der horizontale Cursor reguliert das Transparenzniveau. Die Farbe des Textes ist automatisch.",
"Couleurs": "Farben",
"Dans le site": "In der Seite",
"Dans quelle langue utiliserez-vous Zwii ?": "In welcher Sprache werden Sie Zwii verwenden?",
"Date": "Datum",
"Description": "Beschreibung",
"Disponible si le consentement des cookies est activé.": "Verfügbar, wenn die Cookie-Einwilligung aktiviert ist.",
"Disposition": "Anordnung",
"Données %s copiées vers %s": "Daten %s auf %s kopiert",
"Données des modules": "Module",
"Données importées": "Importierte Daten",
"Dossier": "Verzeichnis",
"Droits sur les dossiers": "Rechte für Verzeichnisse",
"Droits sur les fichiers": "Dateirechte",
"Dupliquer": "Duplizieren",
"Dupliquer la page": "Duplizieren Sie die Seite",
"Déconnecte les sessions ouvertes précédemment sur d'autres navigateurs ou terminaux. Activation recommandée.": "Trennen Sie die offenen Sitzungen zuvor von anderen Browsern oder Terminals. Empfohlene Aktivierung.",
"Déconnecter": "Trennen",
"Déconnexion !": "Trennen!",
"Déconnexion automatique": "Automatische Trennung",
"Définir par défaut": "Als Standard festlegen",
"Dévoiler le mot de passe": "Das Passwort angeben",
"Effacer": "Löschen",
"Effacer la page": "Löschen Sie die Seite",
"Effacer tous les commentaires": "Alle Kommentare löschen",
"Effacer toutes les statistiques": "Delete all statistics",
"Effacer un commentaire": "Kommentar löschen",
"Effacer une catégorie": "Kategorie löschen",
"Emplacement :": "Einstellung:",
"Emplacement dans le menu": "Lage im Menü",
"En bas au centre": "Runter in der Mitte",
"En bas à droite": "Unten rechts",
"En bas à gauche": "Unten nach links",
"En cas de changement de module, les données du module précédent seront supprimées.": "Im Falle einer Moduländerung werden Daten aus dem vorherigen Modul gelöscht.",
"En dessous du site": "Unterhalb der Website",
"En haut au centre": "Top in der Mitte",
"En haut à droite": "Oben rechts",
"En haut à gauche": "An der oberen Ecke links",
"En position libre ajoutez le module en plaçant [MODULE] à l'endroit voulu dans votre page.": "Fügen Sie in der freien Position das Modul hinzu, indem Sie [Modul] dem gewünschten Ort in Ihrer Seite platzieren.",
"En-dehors du site": "Außerhalb der Website",
"Enregistrer": "Registrieren",
"Envoyer un message de confirmation": "Senden Sie eine Bestätigungsnachricht",
"Erreur : sauvegarde non générée !": "Fehler: Nicht erzeugte Sicherung!",
"Erreur d'URL": "URL -Fehler",
"Erreur d'extraction, vérifiez les permissions": "Extraktionsfehler, Berechtigungen überprüfen",
"Erreur de copie": "Fehler kopieren",
"Erreur de copie, vérifiez les permissions": "Fehler kopieren, Berechtigungen überprüfen",
"Erreur de lecture, vérifiez les permissions": "Lesenfehler, Überprüfen Sie die Berechtigungen",
"Erreur inconnue": "unbekannter Fehler",
"Erreur inconnue, le module n'est pas installé": "Unbekannter Fehler, das Modul ist nicht installiert",
"Export CSV": "CSV exportieren",
"Expéditeur": "Absender",
"Extension": "Verlängerung",
"Extraire": "Extrahieren",
"Facebook": "Facebook",
"Famille": "Familie",
"Favicon thème sombre": "Dunkeles Thema Favicon",
"Feuille de style spécifique à la page.": "Stilblatt spezifisch für die Seite.",
"Fichiers": "Dateien",
"Fichiers effacés": "Gelöschte Dateien",
"Fil d'Ariane dans le titre": "Ariane -Thread im Titel",
"Fond du sous-menu": "Untermenü",
"FontId": "Schriftart",
"Fonte": "Quelle",
"Fonte actualisée": "Aktualisieren",
"Fonte créée": "Fonte erstellt",
"Fonte en ligne": "Online -Schmelzen",
"Fonte installée": "Installiertes Gusseisen",
"Fonte non créée, ressource absente !": "Fonte nicht erstellt, abwesende Ressource!",
"Fonte supprimée": "Löschen Schmelzen",
"Fontes": "Quellen",
"Format incorrect": "Format falsch",
"Formulaire": "Formular",
"Fréquence de recherche": "Forschungshäufigkeit",
"Fuseau horaire": "Zeitzone",
"Gabarits de page - Barre latérale": "Seitenvorlage - Seitenleiste",
"Gestion": "Management",
"Gestion des modules": "Modulverwaltung",
"Gestion des thèmes": "Themenmanagement",
"Gestionnaire de fichiers": "Dateimanager",
"Github": "Github",
"Grande": "Groß",
"Grande (220%)": "Grande (220%)",
"Grande (300px)": "Grande (300px)",
"Gras": "Fett",
"Groupe": "Gruppe",
"Groupe associé": "Zugehörige Gruppe",
"Groupe requis pour accéder à la page :": "Gruppe erforderlich, um auf die Seite zuzugreifen:",
"Groupes": "Gruppen",
"Générer sitemap.xml et robots.txt": "Generieren Sie Sitemap.xml und Robots.txt",
"Générer une capture Open Graph": "Erstellen Sie eine offene Graph -Erfassung",
"Gérer les catégories": "Kategorien verwalten",
"Gérer les commentaires": "Kommentare verwalten",
"Gérer les données": "Daten verwalten",
"Hauteur": "Höhe",
"Hauteur de l'image": "Höhe des Bildes",
"Hauteur de l'image sélectionnée": "Höhe des ausgewählten Bildes",
"Hauteur maximale": "Maximale Höhe",
"ID de la chaîne : https://www.youtube.com/channel/[ID].": "Kanal -ID: https://www.youtube.com/channel/).",
"Icône": "Symbol",
"Icône avec bulle de texte": "Symbol mit Textblase",
"Icône haut de page, couleur arrière-plan": "Icon oben auf der Seite, Hintergrundfarbe",
"Identifiant": "Kennung",
"Identifiant (sans espace ni majuscule)": "Kennung (ohne Platz oder Großbuchstaben)",
"Identité": "Identifizieren",
"Identité de la fonte": "Identität des Gusseisen",
"Identité du site": "Standortidentität",
"Il apparaît dans la barre de titre et les partages sur les réseaux sociaux.": "Er erscheint in der Titelleiste und teilt in sozialen Netzwerken.",
"Image": "Bild",
"Image étirée (100% 100%)": "Gestrecktes Bild (100% 100%)",
"Important": "Wichtig",
"Importante": "Wichtig",
"Importation d'utilisateurs": "Import von Benutzern",
"Importation de fichier plat CSV": "CSV Flat File Import",
"Importation effectuée": "Einfuhr",
"Importer": "Importeur",
"Importer dans": "Import in",
"Importer des utilisateurs en masse": "Massenbenutzer importieren",
"Impossible d'ouvrir l'archive": "Das Archiv kann nicht öffnen",
"Impossible de modifier votre propre groupe.": "Ihre eigene Gruppe kann nicht geändert werden.",
"Impossible de soumettre le formulaire, car il contient des erreurs": "Es ist unmöglich, das Formular einzureichen, da es Fehler enthält",
"Impossible de supprimer une page contenant des pages enfants": "Eine Seite mit Kinderseiten kann nicht gelöscht werden",
"Impossible de supprimer votre propre compte": "Ihr eigenes Konto kann nicht gelöscht werden",
"Inclure le contenu du gestionnaire de fichiers": "Fügen Sie den Inhalt des Dateimanagers hinzu",
"Incorrect": "Falsch",
"Informations": "Informationen",
"Instagram": "Instagram",
"Installation terminée": "Installation abgeschlossen",
"Installer": "Installateur",
"Installer depuis le catalogue en ligne": "Installieren Sie aus dem Online -Katalog",
"Installer depuis une archive": "Aus einem Archiv installieren",
"Installer les données d'un module": "Installieren Sie eine Moduldaten",
"Installer ou mettre à jour un module téléchargé": "Installieren oder aktualisieren Sie ein heruntergeladenes Modul",
"Installer un module": "Installieren Sie ein Modul",
"Installer un thème archivé (site ou administration)": "Installieren Sie ein archiviertes Thema (Standort oder Verwaltung)",
"Instructions JS ou jquery spécifiques à la page.": "JS- oder JQuery -Anweisungen, die für die Seite spezifisch sind.",
"Interface": "Schnittstelle",
"Jeton invalide": "Ungültiges Token",
"Journal réinitialisé avec succès": "Erfolgreiches Reset -Journal",
"Journalisation": "Journalisierung",
"L'archive a été déposée dans le gestionnaire de fichiers. Les archives inférieures à la version 9 ne sont pas acceptées.": "Das Archiv wurde im Dateimanager hinterlegt. Archive unter Version 9 werden nicht akzeptiert.",
"L'identifiant est défini lors de la création du compte, il ne peut pas être modifié.": "Die Kennung wird beim Erstellen des Kontos definiert, es kann nicht geändert werden.",
"La carte du site a été mise à jour": "Die Site -Karte wurde aktualisiert",
"La copie de sauvegarde du fichier htaccess n'a pas été restaurée !": "Sicherungskopie der htaccess-Datei wurde nicht wiederhergestellt!",
"La description d'une page participe à son référencement, chaque page doit disposer d'une description différente.": "Die Beschreibung einer Seite nimmt an ihrer Referenzierung teil. Jede Seite muss eine andere Beschreibung haben.",
"La page %s est ouverte par l'utilisateur %s": "Der %s wird vom Benutzer %s geöffnet",
"La page demandée n'existe pas ou est introuvable (erreur 404)": "Die angeforderte Seite existiert nicht oder wird nicht gefunden (Fehler 404)",
"La page est affichée dans un menu horizontal mais pas dans le menu vertical d'une barre latérale.": "Die Seite wird in einem horizontalen Menü, jedoch nicht im vertikalen Menü einer Seitenleiste angezeigt.",
"La première page que vos visiteurs verront.": "Die erste Seite, die Ihre Besucher sehen werden.",
"La règlementation française impose un anonymat de niveau 2": "Französische Vorschriften erfordern Anonymität der Stufe 2",
"La réécriture d'URL n'a pas été restaurée !": "URL-Umschreibung wurde nicht wiederhergestellt!",
"La sauvegarde des fichiers peut prendre du temps. Continuer ?": "Die Sicherung der Dateien kann einige Zeit in Anspruch nehmen. Weitermachen ?",
"La suppression a échoué": "Die Löschung schlug fehl",
"La version installée est plus récente": "Die installierte Version ist neuer",
"La vérification est quotidienne. Option désactivée si la configuration du serveur ne le permet pas.": "Die Überprüfung ist täglich. Option deaktiviert, wenn die Serverkonfiguration dies nicht zulässt.",
"Langue de l'administration": "Verwaltungssprache",
"Langue du site par défaut": "Standardsprache der Website",
"Langue par défaut": "Standard",
"Langues": "SPRACHEN",
"Langues disponibles": "Verfügbare Sprachen",
"Langues installées": "Sprachen installiert",
"Largeur": "Breite",
"Largeur de l'image": "Breite des Bildes",
"Largeur du site": "Breite der Website",
"Le curseur horizontal règle le niveau de transparence, le placer tout à la gauche pour un surlignement invisible.": "Der horizontale Cursor reguliert das Transparenzniveau und platziert ihn links für unsichtbare Highlights.",
"Le curseur horizontal règle le niveau de transparence.": "Der horizontale Cursor reguliert das Transparenzniveau.",
"Le fuseau horaire est utile au bon référencement": "Die Zeitzone ist nützlich für gute SEO",
"Le menu accessoire est aligné à droite de la barre de menu, c'est un emplacement réservé aux drapeaux et au bouton de connexion.": "Das Zubehörmenü ist rechts neben der Menüleiste ausgerichtet. Es ist ein Standort für Flaggen und die Verbindungsschaltfläche.",
"Le menu horizontal intégral": "Das vollständige horizontale Menü",
"Le module %s a été %s": "Das Modul %war %s",
"Le module %s de la page %s a été supprimé": "Das %s -Modul des %s wurde gelöscht",
"Le module %s est désinstallé, il reste peut-être des données dans %s": "Das Modul %S ist deinstalliert, es kann Daten in %s geben",
"Le sous-menu de la page parente": "Das Untermenü der Elternseite",
"Le survol d'une icône de l'écran de connexion affiche temporairement le mot de passe.": "Die Überflucht eines Symbols auf dem Verbindungsbildschirm zeigt das Kennwort vorübergehend an.",
"Le titre court est affiché dans les menus. Il peut être identique au titre de la page.": "Der kurze Titel wird in den Menüs angezeigt. Es kann mit dem Titel der Seite identisch sein.",
"Les langues sélectionnées sont identiques": "Die ausgewählten Sprachen sind identisch",
"Les mentions légales sont obligatoires en France. Une option du pied de page ajoute un lien discret vers cette page.": "Rechtliche Mitteilungen sind in Frankreich obligatorisch. Eine Option der Fußzeile fügt dieser Seite einen diskreten Link hinzu.",
"Les modifications que vous avez apportées ne seront peut-être pas enregistrées.": "Die Änderungen, die Sie vorgenommen haben, werden möglicherweise nicht aufgezeichnet.",
"Les tailles des polices de la bannière, de menu et de pied de page sont proportionnelles à cette taille.": "Die Schriftgrößen des Banners, Menüs und Fußzeile sind proportional zu dieser Größe.",
"Lettres": "Lettres",
"Libre": "Libre",
"Licence :": "Lizenz:",
"Lien de connexion": "Anmeldelink",
"Lien page des mentions légales.": "Link der rechtlichen Hinweise.",
"Liens": "Grundpfandrechte",
"Limitation des tentatives": "Einschränkung der Versuche",
"Limitée au site": "Auf die Website beschränkt",
"Linkedin": "LinkedIn",
"Liste noire": "Schwarze Liste",
"Liste noire réinitialisée avec succès": "Erfolgreiche schwarze Liste erfolgreich zurücksetzen",
"Lors d'une mise à jour automatique, conserve le fichier htaccess de la racine du site.": "Während eines automatischen Updates hält die HTaccess -Datei des Site -Stammes.",
"Léger": "Leicht",
"Légère": "Leicht",
"Maigre": "Mager",
"Maintenance": "Wartung",
"Majuscule à chaque mot": "Capper mit jedem Wort",
"Majuscules": "Großbuchstaben",
"Marges verticales": "Vertikale Ränder",
"Masquer la bannière en écran réduit": "Verstecken Sie das Banner im reduzierten Bildschirm",
"Masquer la page et les pages enfants dans le menu d'une barre latérale": "Verstecken Sie die Seiten- und Kinderseiten im Menü einer Seitenleiste",
"Masquer les pages enfants dans le menu horizontal": "Verstecken Sie Kinderseiten im horizontalen Menü",
"Membre": "Mitglied",
"Membre avec droit de partage": "Mitglied mit Freigaberecht",
"Membre simple": "Einfaches Mitglied",
"Mentions légales": "Impressum",
"Menu": "Speisekarte",
"Menu accessoire": "Zubehörmenü",
"Menu burger dans écran réduit": "Burger-Menü bei reduziertem Bildschirm",
"Menu standard": "Menüstandard",
"Message d'acceptation des Cookies": "Cookie -Akzeptanznachricht",
"Message de consentement aux cookies": "Cookie -Zustimmungsnachricht",
"Mettre à jour": "Aktualisieren",
"Mettre à jour le module orphelin": "Aktualisieren Sie das Orphan -Modul",
"Minuscules": "Winzig",
"Mise en forme des titres": "Formatierende Titel",
"Mise en forme du texte": "Textformatierung",
"Mise en forme du titre": "Titelformatierung",
"Mise en page": "Layout",
"Mise à jour": "Aktualisieren",
"Mise à jour automatisée": "Automatisiertes Update",
"Mise à jour terminée avec succès.": "Erfolgreiches Update abgeschlossen.",
"Modifications enregistrées": "Modifikationen aufgezeichnet",
"Module": "Modul",
"Module de la page": "Seitenmodul",
"Modules": "Module",
"Modules configurés": "Konfigurierte Module",
"Modules installés": "Module installiert",
"Modules orphelins": "Verwaiste Module",
"Mot de passe": "Passwort",
"Mot de passe oublié": "Haben Sie Ihr Passwort vergessen",
"Mot de passe perdu": "Haben Sie Ihr Passwort vergessen",
"Motorisé par": "Angetrieben von",
"Moyen": "Mittel",
"Moyenne": "Durchschnittlich",
"Moyenne (200%)": "Durchschnitt (200%)",
"Moyenne (200px)": "Durchschnitt (200px)",
"Méta-description": "Meta-Schreiben",
"Méta-titre": "Stoffitis",
"Ne pas afficher": "Werden nicht angezeigt",
"Ne pas charger l'exemple de site (utilisateurs avancés)": "Laden Sie das Beispiel einer Website nicht auf (erweiterte Benutzer)",
"Ne pas répéter": "Wiederhole nicht",
"Ne pas saisir les balises": "Geben Sie die Tags nicht ein",
"News": "Nachrichten",
"Niveau 1 (192.168.12.x)": "Stufe 1 (192.168.12.x)",
"Niveau 2 (192.168.x.x)": "Stufe 2 (192.168.x.x)",
"Niveau 3 (192.x.x.x)": "Stufe 3 (192.x.x.x)",
"Nom": "Nom",
"Nom Prénom": "Nachname Vorname",
"Nom du profil": "Profilname",
"Nom utilisateur": "Nutzername",
"Non": "Nicht",
"Non tronquée": "Unbemannt",
"Notre site est actuellement en maintenance. Nous sommes désolés pour la gêne occasionnée et faisons notre possible pour être rapidement de retour.": "Unsere Website befindet sich derzeit in der Wartung. Wir entschuldigen uns für die verursachten Unannehmlichkeiten und geben unser Bestes, um schnell zurück zu sein.",
"Nouveau contenu localisé": "Neue lokalisierte Inhalte",
"Nouveau mot de passe": "Neues Kennwort",
"Nouveau mot de passe enregistré": "Neues aufgezeichnetes Passwort",
"Nouvel utilisateur": "Neuer Benutzer",
"Nouvelle page créée": "Neue Seite erstellt",
"Nouvelle page ou barre latérale": "Neue Seite oder Seitenleiste",
"Obligatoire": "Obligatorisch",
"Ombre": "Ombre",
"Option active en mode déconnecté uniquement, les pages enfants sont visibles et accessibles.": "Aktive Option im getrennten Modus, Kinderseiten sind sichtbar und zugänglich.",
"Option recommandée pour sécuriser la connexion. S'applique à tous les captchas du site. Le captcha simple se limite à une addition de nombres de 0 à 10. Le captcha complexe utilise quatre opérations de nombres de 0 à 20. Activation recommandée.": "Empfohlene Option zur Sicherung der Verbindung. Bewerben Sie sich für alle Captchas der Website. Einfache Captcha ist auf die Zugabe von Zahlen von 0 bis 10 beschränkt. Der komplexe Capha verwendet vier Zahlen von 0 bis 20. Empfohlene Aktivierung.",
"Options": "Optionen",
"Options avancées": "Erweiterte Optionen",
"Origine": "Herkunft",
"Oui": "Oui",
"Page": "Buchseite",
"Page 2/3 - barre 1/3": "Seite 2/3 - Barre 1/3",
"Page 3/4 - barre 1/4": "Seite 3/4 - Barre 1/4",
"Page associée": "Zugeordnete Seite",
"Page de recherche": "Suchseite",
"Page dupliquée": "Doppelte Seite",
"Page et module dupliqués": "Duplizierte Seite und Modul",
"Page inexistante, erreur 404": "Seite nicht vorhanden, Fehler 404",
"Page non cliquable": "Nicht klickbare Seite",
"Page parent": "Seite Elternteil",
"Page standard": "Page Standard",
"Page supprimée": "Gelöschte Seite",
"Pages dans le menu": "Seiten im Menü",
"Pages du site": "Standortseiten",
"Pages et les modules de": "Seiten und Module von",
"Pages orphelines": "Waisenseiten",
"Papier peint": "Hintergrund",
"Par défaut le menu est affiché APRES le contenu de la page. Pour le positionner à un emplacement précis, insérez [MENU] dans le contenu de la page.": "Standardmäßig wird das Menü nach dem Inhalt der Seite angezeigt. Um es an einem bestimmten Ort zu positionieren, fügen Sie [Menü] in den Inhalt der Seite ein.",
"Paramètres": "Einstellungen",
"Paramètres de la localisation": "Standortparameter",
"Paramètres de la sauvegarde": "Backup-Einstellungen",
"Paramètres du profil": "Profil-Einstellungen",
"Paramètres à utiliser lorsque votre hébergeur ne propose pas la fonctionnalité d'envoi de mail.": "Einstellungen, die verwendet werden müssen, wenn Ihr Host die E -Mail -Sendungsfunktionen nicht anbietet.",
"Pas de marge au-dessus et en dessous du site": "Kein Rand über und unter der Website",
"Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.": "Denken Sie daran, den Cache Ihres Browsers zu löschen, wenn sich das Favicon nicht ändert.",
"Permission": "Erlaubnis",
"Permission et référencement": "Erlaubnis und SEO",
"Permissions": "Berechtigungen",
"Permissions sur les dossiers": "Berechtigungen für Verzeichnisse",
"Permissions sur les fichiers": "Berechtigungen für Dateien",
"Permissions sur les pages": "Berechtigungen für Seiten",
"Petite": "Klein",
"Petite (150px)": "Klein (150px)",
"Petite (180%)": "Petite (180%)",
"Pied de page": "Fuß",
"Pinterest": "Pinterest",
"Plan du site": "Seitenverzeichnis",
"Police des titres": "Titel der Polizei",
"Police du texte": "Textpolizei",
"Port SMTP": "Port SMTP",
"Port du proxy": "Hafen des Stellvertreters",
"Position": "Position",
"Position du module": "Position du module",
"Pour définir la page comme barre latérale, choisissez l'option dans la liste.": "Um die Seite als Seitenleiste zu definieren, wählen Sie die Option aus der Liste.",
"Presse Papier": "Zwischenablage",
"Presse papier": "Zwischenablage",
"Profils des groupes": "Gruppenprofile",
"Proportionnelle à la taille définie dans le site.": "Proportional zu dem in der Stelle definierten.",
"Prénom": "Vorname",
"Prénom Nom": "Vorname Name",
"Préparation de la mise à jour": "Vorbereitung des Updates",
"Préserver le fichier htaccess racine": "Bewahren Sie die HTaccess Racine -Datei auf",
"Préserver les comptes des utilisateurs déjà installés": "Bewahren Sie die bereits installierten Benutzerkonten auf",
"Prévenir l'utilisateur par mail": "Verhindern Sie den Benutzer per E -Mail",
"Prévisualiser": "Vorschau",
"Pseudo": "Pseudo",
"Rang 9 > rang 1. Le profil de rang 1 n'est pas modifiable.": "Rang 9 > Rang 1. Das Profil von Rang 1 ist nicht änderbar.",
"Ratio": "Verhältnis",
"Ratio :": "Verhältnis :",
"Recherche": "Suche",
"Recherche dans le site": "Suche auf der Website",
"Rechercher": "Forschen",
"Rechercher une mise à jour en ligne": "Suchen Sie nach einem Online -Update",
"Redirection": "Weiterleitung",
"Redirection vers la connexion": "Umleitung zur Verbindung",
"Renommer": "Umbenennen",
"Renseignez les champs ci-dessous pour finaliser l'installation.": "Finden Sie die folgenden Felder heraus, um die Installation abzuschließen.",
"Responsive (contain)": "Reaktionsschnell (enthalten)",
"Responsive (cover)": "Reaktionsschnell (Cover)",
"Restauration des bases de données absentes": "Wiederherstellung abwesender Datenbanken",
"Restauration effectuée avec succès": "Catering erfolgreich durchgeführt",
"Restaurer": "Wiederherstellen",
"Restaurer les données du site": "Site -Daten wiederherstellen",
"Rester connecté sur ce navigateur": "Bleiben Sie in diesem Browser in Verbindung",
"Retour": "Rückmeldung",
"Rien à importer, erreur de format ou fichier incorrect": "Nichts zu importieren, formatieren Sie Fehler oder eine falsche Datei",
"Rédacteur": "Redakteur",
"Référencement": "SEO",
"Réinitialisation du mot de passe": "Passwort zurücksetzen",
"Réinitialiser avec le thème par défaut": "Mit dem Standardthema zurücksetzen",
"Réinitialiser la feuille de style": "Setzen Sie das Stilblatt zurück",
"Réinitialiser la liste": "Setzen Sie die Liste zurück",
"Réinitialiser le journal": "Setzen Sie die Zeitung zurück",
"Réinstaller": "Neu installieren",
"Répétition": "Wiederholung",
"Réseau": "Netzwerk",
"Réseaux sociaux": "Soziale Netzwerke",
"S'ouvre dans un nouvel onglet": "Öffnet sich in einer neuen Registerkarte",
"SMTP": "SMTP",
"SMTP personnalisé": "Personalisierte SMTP",
"Saisir la clé, puis valider le formulaire avant de cliquer sur le bouton de génération": "Geben Sie die Taste ein und validieren Sie das Formular, bevor Sie auf die Schaltfläche Generation klicken",
"Saisissez le Titre de gestion des cookies.": "Geben Sie den Cookie -Management -Titel ein.",
"Saisissez le message pour les cookies déposés par ZwiiCMS, nécessaires au fonctionnement et qui ne nécessitent pas de consentement.": "Geben Sie die von Zwiicms abgelagerte Meldung für den Betrieb erforderlich und müssen keine Zustimmung erfordern.",
"Saisissez le texte du lien vers les mentions légales,la page doit être définie dans la configuration du site.": "Geben Sie den Link -Text in die rechtlichen Hinweise ein. Die Seite muss in der Site -Konfiguration definiert werden.",
"Saisissez votre ID : https://pinterest.com/[ID].": "Geben Sie Ihre ID ein: https://pinterest.com/).",
"Saisissez votre ID : https://twitter.com/[ID].": "Geben Sie Ihre ID ein: https://twitter.com/).",
"Saisissez votre ID : https://www.facebook.com/[ID].": "Geben Sie Ihre ID ein: https://www.facebook.com/).",
"Saisissez votre ID : https://www.instagram.com/[ID].": "Geben Sie Ihre ID ein: https://www.instagram.com/).",
"Saisissez votre ID Github : https://github.com/[ID].": "Geben Sie Ihre GitHub -ID ein: https://github.com/).",
"Saisissez votre ID Linkedin : https://fr.linkedin.com/in/[ID].": "Geben Sie Ihre LinkedIn -ID ein: https://fr.linkedin.com/in/ style].",
"Saisissez votre ID Utilisateur : https://www.youtube.com/user/[ID].": "Geben Sie Ihre Benutzer -ID ein: https://www.youtube.com/user/).",
"Sauvegarde": "Backup",
"Sauvegarde automatique quotidienne du site": "Tägliche automatische Sicherung der Website",
"Sauvegarde du thème dans le": "Sicherung des Themas in der",
"Sauvegarde générée avec succès": "Erfolgreich erzeugte Backup.",
"Sauvegarder": "Schützen",
"Sauvegarder et télécharger le module": "Speichern und laden Sie das Modul herunter und laden Sie sie herunter",
"Sauvegarder le module dans le gestionnaire de fichiers": "Speichern Sie das Modul im Dateimanager",
"Sauvegarder les données du module dans le gestionnaire de fichiers": "Speichern Sie Moduldaten im Dateimanager",
"Sauvegarder les données du site": "Site -Daten speichern",
"Script dans body": "Skript dans Körper",
"Script dans head": "Skript Dans Kopf",
"Scripts externes": "Skripte externe",
"Se déconnecter": "austragen",
"Service en ligne inaccessible": "Unzugänglicher Online -Service",
"Seul un administrateur peut se connecter lors d'une maintenance": "Nur ein Administrator kann während der Wartung eine Verbindung herstellen",
"Si le contenu du gestionnaire de fichiers est très volumineux, mieux vaut une copie par FTP.": "Wenn der Inhalt des Dateimanagers sehr groß ist, ist es besser, eine Kopie von FTP zu kopieren.",
"Signature": "Unterschrift",
"Site": "Grundstück",
"Site en maintenance": "Seite wird gewartet",
"Size": "Größe",
"Source": "Quelle",
"Standard": "Standard",
"Style": "Stil",
"Suppression interdite": "Löschung verboten",
"Suppression interdite, page active dans la configuration de la langue du site": "Löschen nicht erlaubt, Seite ist in der Sprachkonfiguration der Website aktiv",
"Supprime le point d'interrogation dans les URL, l'option est indisponible avec les autres serveurs Web": "Löscht das Fragezeichen in den URLs, die Option ist mit anderen Webservern nicht verfügbar",
"Supprimer": "LÖSCHEN",
"Supprimer la page": "Löschen Sie die Seite",
"Supprimer le module": "Löschen Sie das Modul",
"Supprimer toutes les sauvegardes automatiques ?": "Alle automatischen Sicherungen entfernen?",
"Sur l'axe horizontal": "Auf der horizontalen Achse",
"Sur l'axe vertical": "Auf der vertikalen Achse",
"Sur les deux axes": "Auf beiden Achsen",
"Sécurité": "Sicherheit",
"Sécurité de la connexion": "Verbindungssicherheit",
"Sécurité désactivée": "Sicherheit deaktiviert",
"Sélectionner un fichier": "Wählen Sie eine Datei aus",
"Sélectionnez au moins un contenu à afficher": "Wählen Sie mindestens einen Inhalt zum Anzeigen aus",
"Sélectionnez la langue à copier vers une langue cible": "Wählen Sie die Sprache aus, um in eine Zielsprache zu kopieren",
"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.": "Wählen Sie ein an ein dunkles Thema adaptiertes Symbol aus. <br> Denken Sie daran, den Cache aus Ihrem Browser zu löschen, wenn sich das Favicon nicht ändert.",
"Sélectionnez une image ou une icône de petite dimension": "Wählen Sie ein Bild oder ein kleines Symbol aus",
"Sélectionnez une langue": "Wähle eine Sprache",
"Sélectionnez une page contenant le module 'Recherche'. Une option du pied de page ajoute un lien discret vers cette page.": "Wählen Sie eine Seite mit dem Modul \"Forschung\" aus. Eine Option der Fußzeile fügt dieser Seite einen diskreten Link hinzu.",
"Sélectionnez une page pour activer": "Wählen Sie eine Seite aus, um sie zu aktivieren",
"Séparateur": "Separator",
"Taille": "Größe",
"Text": "Text",
"Texte": "Text",
"Thème": "Thema",
"Thème de l'administration": "Verwaltungsthema",
"Thème du site": "Site -Thema",
"Thème importé": "Importiertes Thema",
"Thèmes": "Themen",
"Titre": "Titer",
"Titre court": "Kurzer Titel",
"Titre masqué": "Maskierter Titel",
"Titre masqué dans la page": "Maskierter Titel auf der Seite",
"Titres": "Titres",
"Tous les dossiers": "Alle Verzeichnisse",
"Tous les droits d'édition des contenus": "Alle Bearbeitungsrechte für Inhalte",
"Tout Effacer": "Alles löschen",
"Traduction supprimée": "Gelöschte Übersetzung",
"Très grande": "Sehr groß",
"Très grande (240%)": "Sehr groß (240%)",
"Très grande (400px)": "Sehr groß (400px)",
"Très important": "Sehr wichtig",
"Très importante": "Sehr wichtig",
"Très léger": "Sehr leicht",
"Très légère": "Sehr leicht",
"Très petite": "Sehr klein",
"Très petite (100px) ": "Sehr klein (100px)",
"Très petite (160%)": "Sehr klein (160%)",
"Twitter": "Twitter",
"Type de captcha": "Typ de captcha",
"Type de proxy": "Geben Sie de Proxy ein",
"Téléchargement et validation de l'archive": "Laden Sie das Archiv herunter und bestätigen Sie das Archiv",
"Télécharger": "Herunterladen",
"Télécharger la liste": "Laden Sie die Liste herunter",
"Télécharger le journal": "Laden Sie die Zeitung herunter",
"Télécharger le module dans le gestionnaire de fichiers": "Laden Sie das Modul im Dateimanager herunter",
"Téléverser": "Hochladen",
"URL incorrecte": "Falsche URL",
"Un mail a été envoyé pour confirmer la réinitialisation": "Eine E -Mail wurde gesendet, um den Reset zu bestätigen",
"Une archive du dossier /site/data est conservée pendant 30 jours. Activation recommandée": "Ein Archiv der Datei /Site /Daten wird 30 Tage lang aufbewahrt. Empfohlene Aktivierung",
"Une erreur est survenue lors de l'étape :": "Während der Stadium trat ein Fehler auf:",
"Url du fichier de fonte": "URL der Gusseisen -Datei",
"Utilisateur inexistant": "Nicht existierender Benutzer",
"Utilisateur supprimé": "Gelöschter Benutzer",
"Utilisateurs": "Benutzer",
"Valider": "Bestätigen",
"Version": "Ausführung",
"Version n°": "Version N °",
"Vider dossier sauvegardes auto": "Leere automatische Sicherungsdatei",
"Visiteur": "Besucher",
"Vous n'êtes pas autorisé à consulter cette page (erreur 403)": "Sie dürfen diese Seite nicht konsultieren (Fehler 403)",
"Youtube": "Youtube",
"ZwiiCMS - Installation": "ZwiiCMS - Installation",
"actualisé": "Aktualisiert",
"favicon.ico": "Favicon.ico",
"faviconDark.ico": "Favicondark.ico",
"gestionnaire de fichiers": "Dateimanager",
"installé": "Eingerichtet",
"jour": "jour",
"jours": "Tage",
"sauvegardé avec succès": "Erfolgreich gespeichert",
"vers": "gegen",
"À droite": "Nach rechts",
"À gauche": "Nach links",
"À l'emplacement du mot clé [MODULE] dans la page": "Am Ort des Schlüsselworts [Modul] auf der Seite",
"Échec de l'écriture, vérifiez les permissions": "Schreiben, Schreiben, Überprüfen Sie die Berechtigungen",
"Échecs": "Schach",
"Éditer": "Bearbeiten",
"Éditer la page": "Veröffentlichen Sie die Seite",
"Éditer les dialogues": "Bearbeiten Sie die Dialoge",
"Éditer une catégorie": "Kategorie bearbeiten",
"Éditeur": "Editor",
"Éditeur CSS": "CSS -Verlag",
"Éditeur JS": "Verlag JS",
"Éditeur de script %s": "Skript Editor %s",
"Éditeur de script dans Body": "Skripteditor im Körper",
"Éditeur de script dans Head": "Skripteditor im Kopf",
"Éditeur simple": "Einfacher Editor",
"Édition des pages": "Seitenbearbeitung",
"Édition du profil %s": "Profil bearbeiten %s",
"Éléments": "Elemente",
"Étendu sur la page": "Über die Seite ausgebreitet",
"Étiquettes des pages spéciales": "Spezielle Seiten Beschriftungen",
"Dimensions minimales": "Mindestabmessungen",
"Taille maximale du fichier": "Maximale Dateigröße",
"5 Mo pour les images JPEG": "5 MB für JPEG-Bilder",
"1 Mo pour les images PNG": "1 MB für PNG-Bilder",
"Poids": "Gewicht",
"Supprimer ce profil ?": "Dieses Profil löschen?",
"Masqué": "Versteckt",
"Haut de page": "Seitenanfang",
"Bas de page": "Seitenende",
"Petit triangle": "Kleines Dreieck",
"Grand triangle": "Großes Dreieck",
"Flèche": "Pfeil",
"Modèle": "Vorlage",
"Bouton de navigation droit": "Rechte Navigations-Schaltfläche",
"Bouton de navigation gauche": "Linke Navigations-Schaltfläche",
"Groupes / Profils": "Gruppen / Profile",
"Prénom commence par": "Vorname beginnt mit",
"Nom commence par": "Nachname beginnt mit",
"Impossible de réinitialiser le mot de passe de ce compte !": "Das Passwort für dieses Konto kann nicht zurückgesetzt werden!"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,706 @@
{ {
"'Ne pas afficher' crée une page orpheline non accessible par le biais des menus.": "",
"'Sauvegarder et télécharger les données du module": "",
"1 jour": "",
"1/4 : Préparation...": "",
"10 minutes": "",
"10 tentatives": "",
"14 jours": "",
"15 minutes": "",
"2 jours": "",
"2/4 : Téléchargement...": "",
"3 tentatives": "",
"3/4 : Installation...": "",
"4 jours": "",
"4/4 : Configuration...": "",
"5 minutes": "",
"5 tentatives": "",
"7 jours": "",
"Accueil": "",
"Accède au site": "",
"Accède aux pages réservées": "",
"Accède aux pages réservées et à un dossier partagé": "",
"Accès bloqué %d minutes": "",
"Accès désactivé": "",
"Accès interdit, erreur 403": "",
"Action interdite": "",
"Activation obligatoire selon les lois françaises sauf si vous utilisez votre propre système de consentement.": "",
"Activer": "",
"Activer la journalisation": "",
"Actualiser": "",
"Adaptation": "",
"Administrateur": "",
"Administration": "",
"Adresse SMTP": "",
"Adresse du proxy": "",
"Adresse électronique": "",
"Affectation": "",
"Affiche le nom de la page parente suivi du nom de la page, le titre ne doit pas être masqué.": "",
"Affiche les icônes de gestion du compte et de déconnexion des membres simples connectés": "",
"Afin d'assurer le bon fonctionnement de Zwii, veuillez ne pas fermer cette page avant la fin de l'opération.": "",
"Aide": "",
"Ajouter": "",
"Ajouter un profil": "",
"Ajouter un utilisateur": "",
"Ajouter une fonte": "",
"Alignement": "",
"Aligner la bannière avec le contenu": "",
"Ancien mot de passe": "",
"Anonymat des adresses IP": "",
"Apache URL intelligent": "",
"Apache URL intelligentes": "",
"Apparence": "",
"Appliquer": "",
"Approuver un commentaire": "",
"Après": "",
"Après la bannière": "",
"Après le contenu de la page": "",
"Archive": "",
"Archive ZIP": "",
"Archive copiée dans le dossier Modules du gestionnaire de fichier": "",
"Archive de thème invalide": "",
"Archive invalide": "",
"Archive invalide, l'écriture dans le dossier core est interdite": "",
"Archive invalide, le descripteur est absent": "",
"Archive invalide, le fichier de classe est absent": "",
"Archive invalide, les dossiers ne correspondent pas au descripteur": "",
"Archive non spécifiée ou introuvable": "",
"Archive à restaurer": "",
"Arrière plan": "",
"Arrière plan des blocs": "",
"Arrière plan des champs": "",
"Arrondi des angles": "",
"Au centre": "",
"Au début": "",
"Au milieu au centre": "",
"Au milieu à droite": "",
"Au milieu à gauche": "",
"Au-dessus du site": "",
"Aucun": "",
"Aucun dossier": "",
"Aucun fichier journal à télécharger": "",
"Aucun journal à effacer": "",
"Aucun menu": "",
"Aucune": "",
"Aucune liste noire à effacer": "",
"Aucune liste noire à télécharger": "",
"Auteur :": "",
"Authentification": "",
"Automatique": "",
"Autoriser les robots à référencer le site": "",
"Autorisé": "",
"Avant la bannière": "",
"Avant le contenu de la page": "",
"Background": "",
"Banni": "",
"Bannière": "",
"Bannière cliquable": "",
"Barre 1/3 - page 2/3": "",
"Barre 1/4 - page 1/2 - barre 1/4": "",
"Barre 1/4 - page 3/4": "",
"Barre 2/12 - page 7/12 - barre 3/12": "",
"Barre 3/12 - page 7/12 - barre 2/12": "",
"Barre de membre": "",
"Barre latérale": "",
"Barre latérale droite :": "",
"Barre latérale gauche :": "",
"Barres latérales": "",
"Bienvenue %s %s": "",
"Blocage après échecs": "",
"Blog": "",
"Bords arrondis": "",
"Bordure des blocs": "",
"Bordure des champs": "",
"Bouton Aide": "",
"Bouton Standard": "",
"Bouton de validation": "",
"Bouton effacement": "",
"Bouton retour": "",
"Bouton standard": "",
"Bouton validation": "",
"Boutons": "",
"Caché": "",
"Cachée": "",
"Captcha complexe": "",
"Captcha à la connexion": "",
"Captcha, identifiant ou mot de passe incorrects": "",
"Capture d'écran Open Graph": "",
"Capture d'écran générée avec succès": "",
"Casse": "",
"Catalogue": "",
"Catégorie": "",
"Ce membre pourra téléverser ou télécharger des fichiers dans le dossier 'partage' et ses sous-dossiers": "",
"Cette page ne doit pas apparaître dans l'arborescence du menu. Créez une page orpheline.": "",
"Cette redirection ne concerne que les pages d'administration du site.": "",
"Chaîne Youtube": "",
"Chiffres": "",
"Cible": "",
"Cliquez sur une zone afin d'accéder à ses options de personnalisation.": "",
"Commentaire": "",
"Complète": "",
"Compte administrateur": "",
"Compte de l'utilisateur": "",
"Compte verrouillé": "",
"Configuration": "",
"Configuration du module": "",
"Configurer": "",
"Configurer mon compte": "",
"Confirmation": "",
"Confirmer la suppression de cet utilisateur": "",
"Confirmer la dissociation du module de cette page": "",
"Confirmer la désinstallation du module": "",
"Confirmer la suppression de cet utilisateur": "",
"Confirmer la suppression de cette langue": "",
"Confirmer la suppression de la page": "",
"Confirmer la suppression des données du module": "",
"Confirmez-vous la suppression de cette page ?": "",
"Connexion": "",
"Consulter l'aide en ligne": "",
"Contents": "",
"Contenu": "",
"Contenu HTML": "",
"Contenu avancé": "",
"Contenu du menu vertical": "",
"Contrôle total": "",
"Cookies": "",
"Cookies Zwii": "",
"Copie de contenus localisés": "",
"Copie de sites inter-langues": "",
"Copie des traductions rédigées": "",
"Copie terminée avec des erreurs": "",
"Copie terminée avec succès": "",
"Copier": "",
"Copier sauvegardes auto": "",
"Couleur de fond automatique": "",
"Couleur icône haut de page": "",
"Couleur texte page active": "",
"Couleur unie ou papier-peint": "",
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence.": "",
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence. La couleur du texte est automatique.": "",
"Couleurs": "",
"Dans le site": "",
"Dans quelle langue utiliserez-vous Zwii ?": "",
"Date": "",
"Description": "",
"Disponible si le consentement des cookies est activé.": "",
"Disposition": "",
"Données %s copiées vers %s": "",
"Données des modules": "",
"Données importées": "",
"Dossier": "",
"Droits sur les dossiers": "",
"Droits sur les fichiers": "",
"Dupliquer": "",
"Dupliquer la page": "",
"Déconnecte les sessions ouvertes précédemment sur d'autres navigateurs ou terminaux. Activation recommandée.": "",
"Déconnecter": "",
"Déconnexion !": "",
"Déconnexion automatique": "",
"Définir par défaut": "",
"Dévoiler le mot de passe": "",
"Effacer": "",
"Effacer la page": "",
"Effacer tous les commentaires": "",
"Effacer toutes les statistiques": "",
"Effacer un commentaire": "",
"Effacer une catégorie": "",
"Emplacement :": "",
"Emplacement dans le menu": "",
"En bas au centre": "",
"En bas à droite": "",
"En bas à gauche": "",
"En cas de changement de module, les données du module précédent seront supprimées.": "",
"En dessous du site": "",
"En haut au centre": "",
"En haut à droite": "",
"En haut à gauche": "",
"En position libre ajoutez le module en plaçant [MODULE] à l'endroit voulu dans votre page.": "",
"En-dehors du site": "",
"Enregistrer": "",
"Envoyer un message de confirmation": "",
"Erreur : sauvegarde non générée !": "",
"Erreur d'URL": "",
"Erreur d'extraction, vérifiez les permissions": "",
"Erreur de copie": "",
"Erreur de copie, vérifiez les permissions": "",
"Erreur de lecture, vérifiez les permissions": "",
"Erreur inconnue": "",
"Erreur inconnue, le module n'est pas installé": "",
"Export CSV": "",
"Expéditeur": "",
"Extension": "",
"Extraire": "",
"Facebook": "",
"Famille": "",
"Favicon thème sombre": "",
"Feuille de style spécifique à la page.": "",
"Fichiers": "",
"Fichiers effacés": "",
"Fil d'Ariane dans le titre": "",
"Fond du sous-menu": "",
"FontId": "",
"Fonte": "",
"Fonte actualisée": "",
"Fonte créée": "",
"Fonte en ligne": "",
"Fonte installée": "",
"Fonte non créée, ressource absente !": "",
"Fonte supprimée": "",
"Fontes": "",
"Format incorrect": "",
"Formulaire": "",
"Fréquence de recherche": "",
"Fuseau horaire": "",
"Gabarits de page - Barre latérale": "",
"Gestion": "",
"Gestion des modules": "",
"Gestion des thèmes": "",
"Gestionnaire de fichiers": "",
"Github": "",
"Grande": "",
"Grande (220%)": "",
"Grande (300px)": "",
"Gras": "",
"Groupe": "",
"Groupe associé": "",
"Groupe requis pour accéder à la page :": "",
"Groupes": "",
"Générer sitemap.xml et robots.txt": "",
"Générer une capture Open Graph": "",
"Gérer les catégories": "",
"Gérer les commentaires": "",
"Gérer les données": "",
"Hauteur": "",
"Hauteur de l'image": "",
"Hauteur de l'image sélectionnée": "",
"Hauteur maximale": "",
"ID de la chaîne : https://www.youtube.com/channel/[ID].": "",
"Icône": "",
"Icône avec bulle de texte": "",
"Icône haut de page, couleur arrière-plan": "",
"Identifiant": "",
"Identifiant (sans espace ni majuscule)": "",
"Identité": "",
"Identité de la fonte": "",
"Identité du site": "",
"Il apparaît dans la barre de titre et les partages sur les réseaux sociaux.": "",
"Image": "",
"Image étirée (100% 100%)": "",
"Important": "",
"Importante": "",
"Importation d'utilisateurs": "",
"Importation de fichier plat CSV": "",
"Importation effectuée": "",
"Importer": "",
"Importer dans": "",
"Importer des utilisateurs en masse": "",
"Impossible d'ouvrir l'archive": "",
"Impossible de modifier votre propre groupe.": "",
"Impossible de soumettre le formulaire, car il contient des erreurs": "",
"Impossible de supprimer une page contenant des pages enfants": "",
"Impossible de supprimer votre propre compte": "",
"Inclure le contenu du gestionnaire de fichiers": "",
"Incorrect": "",
"Informations": "",
"Instagram": "",
"Installation terminée": "",
"Installer": "",
"Installer depuis le catalogue en ligne": "",
"Installer depuis une archive": "",
"Installer les données d'un module": "",
"Installer ou mettre à jour un module téléchargé": "",
"Installer un module": "",
"Installer un thème archivé (site ou administration)": "",
"Instructions JS ou jquery spécifiques à la page.": "",
"Interface": "",
"Jeton invalide": "",
"Journal réinitialisé avec succès": "",
"Journalisation": "",
"L'archive a été déposée dans le gestionnaire de fichiers. Les archives inférieures à la version 9 ne sont pas acceptées.": "",
"L'identifiant est défini lors de la création du compte, il ne peut pas être modifié.": "",
"La carte du site a été mise à jour": "",
"La copie de sauvegarde du fichier htaccess n'a pas été restaurée !": "",
"La description d'une page participe à son référencement, chaque page doit disposer d'une description différente.": "",
"La page %s est ouverte par l'utilisateur %s": "",
"La page demandée n'existe pas ou est introuvable (erreur 404)": "",
"La page est affichée dans un menu horizontal mais pas dans le menu vertical d'une barre latérale.": "",
"La première page que vos visiteurs verront.": "",
"La règlementation française impose un anonymat de niveau 2": "",
"La réécriture d'URL n'a pas été restaurée !": "",
"La sauvegarde des fichiers peut prendre du temps. Continuer ?": "",
"La suppression a échoué": "",
"La version installée est plus récente": "",
"La vérification est quotidienne. Option désactivée si la configuration du serveur ne le permet pas.": "",
"Langue de l'administration": "",
"Langue du site par défaut": "",
"Langue par défaut": "",
"Langues": "",
"Langues disponibles": "",
"Langues installées": "",
"Largeur": "",
"Largeur de l'image": "",
"Largeur du site": "",
"Le curseur horizontal règle le niveau de transparence, le placer tout à la gauche pour un surlignement invisible.": "",
"Le curseur horizontal règle le niveau de transparence.": "",
"Le fuseau horaire est utile au bon référencement": "",
"Le menu accessoire est aligné à droite de la barre de menu, c'est un emplacement réservé aux drapeaux et au bouton de connexion.": "",
"Le menu horizontal intégral": "",
"Le module %s a été %s": "",
"Le module %s de la page %s a été supprimé": "",
"Le module %s est désinstallé, il reste peut-être des données dans %s": "",
"Le sous-menu de la page parente": "",
"Le survol d'une icône de l'écran de connexion affiche temporairement le mot de passe.": "",
"Le titre court est affiché dans les menus. Il peut être identique au titre de la page.": "",
"Les langues sélectionnées sont identiques": "",
"Les mentions légales sont obligatoires en France. Une option du pied de page ajoute un lien discret vers cette page.": "",
"Les modifications que vous avez apportées ne seront peut-être pas enregistrées.": "",
"Les tailles des polices de la bannière, de menu et de pied de page sont proportionnelles à cette taille.": "",
"Lettres": "",
"Libre": "",
"Licence :": "",
"Lien de connexion": "",
"Lien page des mentions légales.": "",
"Liens": "",
"Limitation des tentatives": "",
"Limitée au site": "",
"Linkedin": "",
"Liste noire": "",
"Liste noire réinitialisée avec succès": "",
"Lors d'une mise à jour automatique, conserve le fichier htaccess de la racine du site.": "",
"Léger": "",
"Légère": "",
"Maigre": "",
"Maintenance": "",
"Majuscule à chaque mot": "",
"Majuscules": "",
"Marges verticales": "",
"Masquer la bannière en écran réduit": "",
"Masquer la page et les pages enfants dans le menu d'une barre latérale": "",
"Masquer les pages enfants dans le menu horizontal": "",
"Membre": "",
"Membre avec droit de partage": "",
"Membre simple": "",
"Mentions légales": "",
"Menu": "",
"Menu accessoire": "",
"Menu burger dans écran réduit": "",
"Menu standard": "",
"Message d'acceptation des Cookies": "",
"Message de consentement aux cookies": "",
"Mettre à jour": "",
"Mettre à jour le module orphelin": "",
"Minuscules": "",
"Mise en forme des titres": "",
"Mise en forme du texte": "",
"Mise en forme du titre": "",
"Mise en page": "",
"Mise à jour": "",
"Mise à jour automatisée": "",
"Mise à jour terminée avec succès.": "",
"Modifications enregistrées": "",
"Module": "",
"Module de la page": "",
"Modules": "",
"Modules configurés": "",
"Modules installés": "",
"Modules orphelins": "",
"Mot de passe": "",
"Mot de passe oublié": "",
"Mot de passe perdu": "",
"Motorisé par": "",
"Moyen": "",
"Moyenne": "",
"Moyenne (200%)": "",
"Moyenne (200px)": "",
"Méta-description": "",
"Méta-titre": "",
"Ne pas afficher": "",
"Ne pas charger l'exemple de site (utilisateurs avancés)": "",
"Ne pas répéter": "",
"Ne pas saisir les balises": "",
"News": "",
"Niveau 1 (192.168.12.x)": "",
"Niveau 2 (192.168.x.x)": "",
"Niveau 3 (192.x.x.x)": "",
"Nom": "",
"Nom Prénom": "",
"Nom du profil": "",
"Nom utilisateur": "",
"Non": "",
"Non tronquée": "",
"Notre site est actuellement en maintenance. Nous sommes désolés pour la gêne occasionnée et faisons notre possible pour être rapidement de retour.": "",
"Nouveau contenu localisé": "",
"Nouveau mot de passe": "",
"Nouveau mot de passe enregistré": "",
"Nouvel utilisateur": "",
"Nouvelle page créée": "",
"Nouvelle page ou barre latérale": "",
"Obligatoire": "",
"Ombre": "",
"Option active en mode déconnecté uniquement, les pages enfants sont visibles et accessibles.": "",
"Option recommandée pour sécuriser la connexion. S'applique à tous les captchas du site. Le captcha simple se limite à une addition de nombres de 0 à 10. Le captcha complexe utilise quatre opérations de nombres de 0 à 20. Activation recommandée.": "",
"Options": "",
"Options avancées": "",
"Origine": "",
"Oui": "",
"Page": "",
"Page 2/3 - barre 1/3": "",
"Page 3/4 - barre 1/4": "",
"Page associée": "",
"Page de recherche": "",
"Page dupliquée": "",
"Page et module dupliqués": "",
"Page inexistante, erreur 404": "",
"Page non cliquable": "",
"Page parent": "",
"Page standard": "",
"Page supprimée": "",
"Pages dans le menu": "",
"Pages du site": "",
"Pages et les modules de": "",
"Pages orphelines": "",
"Papier peint": "",
"Par défaut le menu est affiché APRES le contenu de la page. Pour le positionner à un emplacement précis, insérez [MENU] dans le contenu de la page.": "",
"Paramètres": "",
"Paramètres de la localisation": "",
"Paramètres de la sauvegarde": "",
"Paramètres du profil": "",
"Paramètres à utiliser lorsque votre hébergeur ne propose pas la fonctionnalité d'envoi de mail.": "",
"Pas de marge au-dessus et en dessous du site": "",
"Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.": "",
"Permission": "",
"Permission et référencement": "",
"Permissions": "",
"Permissions sur les dossiers": "",
"Permissions sur les fichiers": "",
"Permissions sur les pages": "",
"Petite": "",
"Petite (150px)": "",
"Petite (180%)": "",
"Pied de page": "",
"Pinterest": "",
"Plan du site": "",
"Police des titres": "",
"Police du texte": "",
"Port SMTP": "",
"Port du proxy": "",
"Position": "",
"Position du module": "",
"Pour définir la page comme barre latérale, choisissez l'option dans la liste.": "",
"Presse Papier": "",
"Presse papier": "",
"Profils des groupes": "",
"Proportionnelle à la taille définie dans le site.": "",
"Prénom": "",
"Prénom Nom": "",
"Préparation de la mise à jour": "",
"Préserver le fichier htaccess racine": "",
"Préserver les comptes des utilisateurs déjà installés": "",
"Prévenir l'utilisateur par mail": "",
"Prévisualiser": "",
"Pseudo": "",
"Rang 9 > rang 1. Le profil de rang 1 n'est pas modifiable.": "",
"Ratio": "",
"Ratio :": "",
"Recherche": "",
"Recherche dans le site": "",
"Rechercher": "",
"Rechercher une mise à jour en ligne": "",
"Redirection": "",
"Redirection vers la connexion": "",
"Renommer": "",
"Renseignez les champs ci-dessous pour finaliser l'installation.": "",
"Responsive (contain)": "",
"Responsive (cover)": "",
"Restauration des bases de données absentes": "",
"Restauration effectuée avec succès": "",
"Restaurer": "",
"Restaurer les données du site": "",
"Rester connecté sur ce navigateur": "",
"Retour": "",
"Rien à importer, erreur de format ou fichier incorrect": "",
"Rédacteur": "",
"Référencement": "",
"Réinitialisation du mot de passe": "",
"Réinitialiser avec le thème par défaut": "",
"Réinitialiser la feuille de style": "",
"Réinitialiser la liste": "",
"Réinitialiser le journal": "",
"Réinstaller": "",
"Répétition": "",
"Réseau": "",
"Réseaux sociaux": "",
"S'ouvre dans un nouvel onglet": "",
"SMTP": "",
"SMTP personnalisé": "",
"Saisir la clé, puis valider le formulaire avant de cliquer sur le bouton de génération": "",
"Saisissez le Titre de gestion des cookies.": "",
"Saisissez le message pour les cookies déposés par ZwiiCMS, nécessaires au fonctionnement et qui ne nécessitent pas de consentement.": "",
"Saisissez le texte du lien vers les mentions légales,la page doit être définie dans la configuration du site.": "",
"Saisissez votre ID : https://pinterest.com/[ID].": "",
"Saisissez votre ID : https://twitter.com/[ID].": "",
"Saisissez votre ID : https://www.facebook.com/[ID].": "",
"Saisissez votre ID : https://www.instagram.com/[ID].": "",
"Saisissez votre ID Github : https://github.com/[ID].": "",
"Saisissez votre ID Linkedin : https://fr.linkedin.com/in/[ID].": "",
"Saisissez votre ID Utilisateur : https://www.youtube.com/user/[ID].": "",
"Sauvegarde": "",
"Sauvegarde automatique quotidienne du site": "",
"Sauvegarde du thème dans le": "",
"Sauvegarde générée avec succès": "",
"Sauvegarder": "",
"Sauvegarder et télécharger le module": "",
"Sauvegarder le module dans le gestionnaire de fichiers": "",
"Sauvegarder les données du module dans le gestionnaire de fichiers": "",
"Sauvegarder les données du site": "",
"Script dans body": "",
"Script dans head": "",
"Scripts externes": "",
"Se déconnecter": "",
"Service en ligne inaccessible": "",
"Seul un administrateur peut se connecter lors d'une maintenance": "",
"Si le contenu du gestionnaire de fichiers est très volumineux, mieux vaut une copie par FTP.": "",
"Signature": "",
"Site": "",
"Site en maintenance": "",
"Size": "",
"Source": "",
"Standard": "",
"Style": "",
"Suppression interdite": "",
"Suppression interdite, page active dans la configuration de la langue du site": "",
"Supprime le point d'interrogation dans les URL, l'option est indisponible avec les autres serveurs Web": "",
"Supprimer": "",
"Supprimer la page": "",
"Supprimer le module": "",
"Supprimer toutes les sauvegardes automatiques ?": "",
"Sur l'axe horizontal": "",
"Sur l'axe vertical": "",
"Sur les deux axes": "",
"Sécurité": "",
"Sécurité de la connexion": "",
"Sécurité désactivée": "",
"Sélectionner un fichier": "",
"Sélectionnez au moins un contenu à afficher": "",
"Sélectionnez la langue à copier vers une langue cible": "",
"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.": "",
"Sélectionnez une image ou une icône de petite dimension": "",
"Sélectionnez une langue": "",
"Sélectionnez une page contenant le module 'Recherche'. Une option du pied de page ajoute un lien discret vers cette page.": "",
"Sélectionnez une page pour activer": "",
"Séparateur": "",
"Taille": "",
"Text": "",
"Texte": "",
"Thème": "",
"Thème de l'administration": "",
"Thème du site": "",
"Thème importé": "",
"Thèmes": "",
"Titre": "",
"Titre court": "",
"Titre masqué": "",
"Titre masqué dans la page": "",
"Titres": "",
"Tous les dossiers": "",
"Tous les droits d'édition des contenus": "",
"Tout Effacer": "",
"Traduction supprimée": "",
"Très grande": "",
"Très grande (240%)": "",
"Très grande (400px)": "",
"Très important": "",
"Très importante": "",
"Très léger": "",
"Très légère": "",
"Très petite": "",
"Très petite (100px) ": "",
"Très petite (160%)": "",
"Twitter": "",
"Type de captcha": "",
"Type de proxy": "",
"Téléchargement et validation de l'archive": "",
"Télécharger": "",
"Télécharger la liste": "",
"Télécharger le journal": "",
"Télécharger le module dans le gestionnaire de fichiers": "",
"Téléverser": "",
"URL incorrecte": "",
"Un mail a été envoyé pour confirmer la réinitialisation": "",
"Une archive du dossier /site/data est conservée pendant 30 jours. Activation recommandée": "",
"Une erreur est survenue lors de l'étape :": "",
"Url du fichier de fonte": "",
"Utilisateur inexistant": "",
"Utilisateur supprimé": "",
"Utilisateurs": "",
"Valider": "",
"Version": "",
"Version n°": "",
"Vider dossier sauvegardes auto": "",
"Visiteur": "",
"Vous n'êtes pas autorisé à consulter cette page (erreur 403)": "",
"Youtube": "",
"ZwiiCMS - Installation": "",
"actualisé": "",
"favicon.ico": "",
"faviconDark.ico": "",
"gestionnaire de fichiers": "",
"installé": "",
"jour": "",
"jours": "",
"sauvegardé avec succès": "",
"vers": "",
"À droite": "",
"À gauche": "",
"À l'emplacement du mot clé [MODULE] dans la page": "",
"Échec de l'écriture, vérifiez les permissions": "",
"Échecs": "",
"Éditer": "",
"Éditer la page": "",
"Éditer les dialogues": "",
"Éditer une catégorie": "",
"Éditeur": "",
"Éditeur CSS": "",
"Éditeur JS": "",
"Éditeur de script %s": "",
"Éditeur de script dans Body": "",
"Éditeur de script dans Head": "",
"Éditeur simple": "",
"Édition des pages": "",
"Édition du profil %s": "",
"Éléments": "",
"Étendu sur la page": "",
"Étiquettes des pages spéciales": "",
"Dimensions minimales": "",
"Taille maximale du fichier": "",
"5 Mo pour les images JPEG": "",
"1 Mo pour les images PNG": "",
"Poids": "",
"Supprimer ce profil ?": "",
"Masqué": "",
"Haut de page": "",
"Bas de page": "",
"Petit triangle": "",
"Grand triangle": "",
"Flèche": "",
"Modèle": "",
"Bouton de navigation droit": "",
"Bouton de navigation gauche": "",
"Groupes / Profils": "",
"Prénom commence par": "",
"Nom commence par": "",
"Impossible de réinitialiser le mot de passe de ce compte !": "",
"Test de la messagerie du site": "",
"Il semblerait que votre messagerie fonctionne correctement !": "",
"Message de test envoyé avec succès": "",
"Message non envoyé": "",
"Validation par clé ⚠️": "",
"La connexion est confirmée à l'aide d'une clé transmise par messagerie. Depuis le groupe sélectionné et les groupes supérieurs.": "",
"Envoi du message d'authentification": "",
"Connexion réussie": "",
"Erreur de mot de passe": "",
"Erreur de captcha": "",
"Clé envoyée par message": "",
"Message de test": "",
"Clé d'authentification envoyée à votre adresse mail %s": ""
} }

View File

@ -1,16 +0,0 @@
{
"languages": {
"fr_FR": {
"version": 12300,
"date": 1677838293
},
"es": {
"version": 12300,
"date": 1677838293
},
"en_EN": {
"version": 12300,
"date": 1677838293
}
}
}

View File

@ -1,24 +0,0 @@
{
"themes": {
"defaut": {
"name": "Le thème par défaut, ambiance bleu et montagne",
"filename": ""
},
"moderne": {
"name": "Thème avec la nouvelle bannière personnalisable",
"filename": "theme_moderne.zip"
},
"affaire": {
"name": "Thème affaire, bannière centre d'appel, ambiance prune",
"filename": "theme_affaire.zip"
},
"black": {
"name": "Thème de nuit, ambiance nocturne",
"filename": "theme_orange_black.zip"
},
"facebook": {
"name": "Thème Facebook ancienne génération, pas de bannière, menu fixe fond bleu",
"filename": "theme_old_facebook.zip"
}
}
}

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-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
/** NE PAS EFFACER
* admin.css
*/

View File

@ -6,7 +6,7 @@
<div class="col6 offset3"> <div class="col6 offset3">
<?php echo template::select('installLanguage', $module::$i18nFiles, [ <?php echo template::select('installLanguage', $module::$i18nFiles, [
'label' => 'Langues installées', 'label' => 'Langues installées',
'selected' => array_key_exists ('fr_FR', $module::$i18nFiles) ? 'fr_FR': reset($module::$i18nFiles), 'selected' => isset(self::$i18nUI) ? self::$i18nUI : 'fr_FR',
]); ?> ]); ?>
</div> </div>
</div> </div>

View File

@ -1 +1,22 @@
/* Vide */ /**
* 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-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
/** NE PAS EFFACER
* admin.css
*/
.title {
font-weight: bold;
}

View File

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

View File

@ -2,17 +2,41 @@
<?php echo helper::translate('Renseignez les champs ci-dessous pour finaliser l\'installation.'); ?> <?php echo helper::translate('Renseignez les champs ci-dessous pour finaliser l\'installation.'); ?>
</p> </p>
<?php echo template::formOpen('installForm'); ?> <?php echo template::formOpen('installForm'); ?>
<h3> <div class="row">
<?php echo helper::translate('Compte administrateur'); ?>
</h3>
<div>
<div class="row">
<div class="col12"> <div class="col12">
<details open>
<summary>
<span class="title">
<?php echo helper::translate('Compte administrateur'); ?>
</span>
</summary>
<div class="row">
<div class="col6">
<?php echo template::text('installFirstname', [
'autocomplete' => 'off',
'label' => 'Prénom'
]); ?>
</div>
<div class="col6">
<?php echo template::text('installLastname', [
'autocomplete' => 'off',
'label' => 'Nom'
]); ?>
</div>
</div>
<div class="row">
<div class="col6">
<?php echo template::text('installId', [ <?php echo template::text('installId', [
'autocomplete' => 'off', 'autocomplete' => 'off',
'label' => 'Identifiant' 'label' => 'Identifiant'
]); ?> ]); ?>
</div> </div>
<div class="col6">
<?php echo template::mail('installMail', [
'autocomplete' => 'off',
'label' => 'Adresse électronique'
]); ?>
</div>
</div> </div>
<div class="row"> <div class="row">
<div class="col6"> <div class="col6">
@ -28,36 +52,18 @@
]); ?> ]); ?>
</div> </div>
</div> </div>
<div class="row"> </details>
<div class="col12">
<?php echo template::mail('installMail', [
'autocomplete' => 'off',
'label' => 'Adresse électronique'
]); ?>
</div>
</div>
<div class="row">
<div class="col6">
<?php echo template::text('installFirstname', [
'autocomplete' => 'off',
'label' => 'Prénom'
]); ?>
</div>
<div class="col6">
<?php echo template::text('installLastname', [
'autocomplete' => 'off',
'label' => 'Nom'
]); ?>
</div>
</div> </div>
</div> </div>
<ul class="accordion" data-speed="150"> <div class="row">
<li class="accordion-item"> <div class="col12">
<h3 class="accordion-title"> <details close>
<?php echo '&#9655; ' . helper::translate('Options avancées'); ?> <summary>
</h3> <span class="title">
<div class="accordion-content"> <?php echo helper::translate('Options avancées'); ?>
<?php if ($this->getUrl(2) === 'fr_FR'): ?> </span>
</summary>
<?php if ($_SESSION['ZWII_UI'] === 'fr_FR'): ?>
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<?php echo template::checkbox('installDefaultData', true, 'Ne pas charger l\'exemple de site (utilisateurs avancés)', [ <?php echo template::checkbox('installDefaultData', true, 'Ne pas charger l\'exemple de site (utilisateurs avancés)', [
@ -66,7 +72,7 @@
?> ?>
</div> </div>
</div> </div>
<?php endif;?> <?php endif; ?>
<div class="row"> <div class="row">
<div class="col3"> <div class="col3">
<?php echo template::select('installProxyType', $module::$proxyType, [ <?php echo template::select('installProxyType', $module::$proxyType, [
@ -88,18 +94,14 @@
</div> </div>
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<?php echo template::select('installTheme', $module::$themes, [
'label' => 'Thème'
]); ?>
<?php echo template::hidden('installLanguage', [ <?php echo template::hidden('installLanguage', [
'value' => $this->getUrl(2) 'value' => $this->getUrl(2)
]); ?> ]); ?>
</div> </div>
</div> </div>
</div> </div>
</li> </div>
</ul> </details>
<div class="row"> <div class="row">
<div class="col2"> <div class="col2">
<?php echo template::button('installPrevious', [ <?php echo template::button('installPrevious', [

View File

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

View File

@ -1,6 +1,16 @@
function step(i, data) { 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'); ?>"]; var errors = [
$(".installUpdateProgressText").hide(), $(".installUpdateProgressText[data-id=" + i + "]").show(), $.ajax({ "<?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({
type: "POST", type: "POST",
url: "<?php echo helper::baseUrl(false); ?>?install/steps", url: "<?php echo helper::baseUrl(false); ?>?install/steps",
data: { data: {
@ -8,13 +18,78 @@ function step(i, data) {
data: data data: data
}, },
success: function (result) { success: function (result) {
setTimeout((function () { setTimeout(function () {
!0 === result.success ? 4 === i ? ($("#installUpdateSuccess").show(), $("#installUpdateEnd").removeClass("disabled"), $("#installUpdateProgress").hide()) : step(i + 1, result.data) : ($("#installUpdateErrorStep").text(errors[i]), $("#installUpdateError").show(), $("#installUpdateEnd").removeClass("disabled"), $("#installUpdateProgress").hide(), console.error(result), $("#installUpdateErrorMessage").text(result.replace(/<[^p].*?>/g, ""))) if (4 === i) {
}), 2e3) $("#installUpdateSuccess").show();
$("body").css("cursor", "default");
$("#installUpdateEnd").removeClass("disabled");
$("#installUpdateProgress").hide();
} else {
step(i + 1, result.data);
}
}, 2000);
}, },
error: function (xhr) { error: function (xhr) {
$("#installUpdateErrorStep").text(errors[1]), $("#installUpdateError").show(), $("#installUpdateEnd").removeClass("disabled"), $("#installUpdateProgress").hide(), console.error(xhr.responseText), $("#installUpdateErrorMessage").text(xhr.responseText.replace(/<[^p].*?>/g, "")) console.log(i);
console.log(xhr.responseText);
console.log(errors);
// Vérification du code d'erreur HTTP pour gérer la déconnexion
if (xhr.status === 401 || xhr.status === 403) {
alert("Votre session a expiré. Veuillez vous reconnecter.");
window.location.href = "?user/login"; // Redirige vers la page de connexion
} else {
// Appel de la fonction de gestion d'erreur
showError(i, xhr.responseText, errors);
} }
}) }
});
} }
$(window).on("load", step(1, null));
function showError(step, message, errors) {
$("body").css("cursor", "default");
$("#installUpdateErrorStep").text(errors[step] + " (étape n°" + step + ")");
$("#installUpdateError").show();
$("#installUpdateEnd").removeClass("disabled");
$("#installUpdateProgress").hide();
// Vérifier si l'accolade ouvrante est trouvée et qu'elle n'est pas en première position
if (typeof message !== 'object') {
// Trouver la position du premier "{" pour repérer le début du tableau
const startOfArray = message.indexOf('{');
if (startOfArray !== -1 && startOfArray > 0) {
// Extraire le message du warning jusqu'au début du tableau
const warningMessage = message.substring(0, startOfArray).trim();
// Extraire le tableau JSON entre les accolades
const jsonString = message.substring(startOfArray);
try {
const jsonData = JSON.parse(jsonString);
// Afficher les résultats si le parsing JSON est réussi
if (jsonData) {
$("#installUpdateErrorMessage").html("<strong>Détails de l'erreur :</strong><br> " +
jsonData.data.replace(/^"(.*)"$/, '$1') +
"<br>" +
warningMessage.replace(/<[^p].*?>/g, ""));
}
} catch (e) {
// Afficher un message générique en cas d'erreur de parsing
console.error("Erreur de parsing JSON : ", e);
$("#installUpdateErrorMessage").html("Une erreur inattendue est survenue lors du traitement des détails de l'erreur.");
}
} else {
// Si pas de JSON détecté, afficher le message brut
$("#installUpdateErrorMessage").html("Message d'erreur : " + message);
}
} else {
$("#installUpdateErrorMessage").html(message);
}
}
$(window).on("load", function () {
step(1, null);
});

View File

@ -1,15 +1,16 @@
<p><strong> <div id="updateContainer">
<?php echo helper::translate('Mise à jour de ZwiiCMS'); ?> <p><strong>
<?php echo helper::translate('Version'); ?>
&nbsp; &nbsp;
<?php echo self::ZWII_VERSION; ?> <?php echo self::ZWII_VERSION; ?>
<?php echo helper::translate('vers ZwiiCMS'); ?> <?php echo helper::translate('vers'); ?>
&nbsp; &nbsp;
<?php echo $module::$newVersion; ?>. <?php echo $module::$newVersion; ?>
</strong></p> </strong></p>
<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.'); ?> <?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.'); ?>
</p> </p>
<div class="row"> <div class="row">
<div class="col9 verticalAlignMiddle"> <div class="col9 verticalAlignMiddle">
<div id="installUpdateProgress"> <div id="installUpdateProgress">
<?php echo template::ico('spin', ['animate' => true]); ?> <?php echo template::ico('spin', ['animate' => true]); ?>
@ -26,15 +27,14 @@
<?php echo helper::translate('4/4 : Configuration...'); ?> <?php echo helper::translate('4/4 : Configuration...'); ?>
</span> </span>
</div> </div>
<div id="installUpdateError" class="colorRed displayNone"> <div id="installUpdateError" class="message colorRed displayNone">
<?php echo template::ico('cancel'); ?> <?php echo template::ico('cancel'); ?>
<strong> <strong>
<?php echo helper::translate('Une erreur est survenue lors de l\'étape :'); ?> <?php echo helper::translate('Une erreur est survenue lors de l\'étape :') . '<br>'; ?>
&nbsp;
<span id="installUpdateErrorStep"> </span>. <span id="installUpdateErrorStep"> </span>.
</strong> </strong>
</div> </div>
<div id="installUpdateSuccess" class="colorGreen displayNone"> <div id="installUpdateSuccess" class="message colorGreen displayNone">
<?php echo template::ico('check'); ?> <?php echo template::ico('check'); ?>
<?php echo helper::translate('Mise à jour terminée avec succès.'); ?> <?php echo helper::translate('Mise à jour terminée avec succès.'); ?>
</div> </div>
@ -47,9 +47,10 @@
'class' => 'disabled' 'class' => 'disabled'
]); ?> ]); ?>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<p><em><span class="colorRed" id="installUpdateErrorMessage"></span></em></p> <p><em><span class="colorRed" id="installUpdateErrorMessage"></span></em></p>
</div> </div>
</div </div>
</div>

View File

@ -8,14 +8,17 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
class translate extends common class language extends common
{ {
// URL langues de l'UI en ligne
const ZWII_UI_URL = 'https://forge.chapril.org/ZwiiCMS-Team/zwiicms-translations/raw/branch/master/v13/';
public static $actions = [ public static $actions = [
'index' => self::GROUP_ADMIN, 'index' => self::GROUP_ADMIN,
'copy' => self::GROUP_ADMIN, 'copy' => self::GROUP_ADMIN,
@ -29,6 +32,7 @@ class translate extends common
// Effacer une langue de contenu ou de l'interface // Effacer une langue de contenu ou de l'interface
'content' => self::GROUP_VISITOR, 'content' => self::GROUP_VISITOR,
'update' => self::GROUP_ADMIN, 'update' => self::GROUP_ADMIN,
'default' => self::GROUP_ADMIN
]; ];
const PAGINATION = '20'; const PAGINATION = '20';
@ -65,49 +69,59 @@ class translate extends common
*/ */
public function update() public function update()
{ {
$lang = $this->getUrl(2);
// Jeton incorrect ou URl avec le code langue incorrecte
if ( if (
$this->getUrl(3) !== $_SESSION['csrf'] && $this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
$lang = $this->getUrl(2);
// Action interdite ou URl avec le code langue incorrecte
if (
array_key_exists($lang, self::$languages) === false array_key_exists($lang, self::$languages) === false
) { ) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'language',
'state' => false, 'state' => false,
'notification' => helper::translate('Action interdite') 'notification' => helper::translate('Action interdite')
]); ]);
} }
// Upload et sauver le fichier de langue // Télécharger le descripteur en ligne
$response = json_decode(helper::getUrlContents(common::ZWII_UI_URL . $lang . '.json'), true); $languageData = helper::getUrlContents(self::ZWII_UI_URL . $lang . '.json');
if ($response !== false) { $descripteur = json_decode(helper::getUrlContents(self::ZWII_UI_URL . 'language.json'), true);
$response = file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($response, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); $success = false;
// Mettre à jour le descripteur if (
$enumsStore = json_decode(helper::getUrlContents(common::ZWII_UI_URL . 'languages.json'), true); $languageData &&
$enums = $this->getData(['languages']); is_array($descripteur['language'][$lang])
$enums = array_merge($enums, [ ) {
$lang => $enumsStore['languages'][$lang] if ($this->setData(['language', $lang, $descripteur['language'][$lang]])) {
]); $success = $this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', $languageData);
$response = (bool) $response && $this->setData(['languages', $enums]); }
} }
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'language',
'notification' => $response ? helper::translate('Copie terminée avec succès') : 'Copie terminée avec des erreurs', 'notification' => $success ? helper::translate('Copie terminée avec succès') : 'Copie terminée avec des erreurs',
'state' => $response 'state' => $success
]); ]);
} }
}
/** /**
* Configuration avancée des langues * Configuration avancée des langues
*/ */
public function copy() public function copy()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Initialisation // Initialisation
$success = false; $success = false;
$copyFrom = $this->getInput('translateFormCopySource'); $copyFrom = $this->getInput('translateFormCopySource');
@ -168,41 +182,21 @@ class translate extends common
public function index() public function index()
{ {
/** // --------------------------------------------------------------------------------------------------
* Met à jour les dictionnaires des langues depuis les modèles installés // Langues du site
*/ // --------------------------------------------------------------------------------------------------
// Langues installées
$installedUI = $this->getData(['languages']);
// Check si la langue est bien disponible sinon la supprime de la BDD
if ($installedUI) {
foreach ($installedUI as $key => $value)
if (file_exists(self::I18N_DIR . $key . '.json' ) === false ) {
$this->deleteData(['languages', $key]);
}
}
// Langues disponibles avec la mise à jour
$store = json_decode(file_get_contents('core/module/install/ressource/i18n/languages.json'), true);
$store = $store['languages'];
foreach($installedUI as $key => $value) {
if (isset($store[$key]) && $store[$key]['version'] > $value['version']) {
$this->setData(['languages', $key, $store[$key]]);
}
}
// Préparation du formulaire
// -------------------------
// Onglet des langues de contenu
foreach (self::$languages as $key => $value) { foreach (self::$languages as $key => $value) {
// tableau des langues installées // tableau des langues installées
if (is_dir(self::DATA_DIR . $key)) { if (is_dir(self::DATA_DIR . $key)) {
if (self::$i18nUI === $key) { if (
file_exists(self::DATA_DIR . $key . '/page.json') &&
file_exists(self::DATA_DIR . $key . '/module.json') &&
file_exists(self::DATA_DIR . $key . '/locale.json')
) {
if (file_exists(self::DATA_DIR . $key . '/.default')) {
$messageLocale = helper::translate('Langue par défaut'); $messageLocale = helper::translate('Langue par défaut');
} elseif (isset($_COOKIE['ZWII_CONTENT']) && $_COOKIE['ZWII_CONTENT'] === $key) { } elseif (isset($_SESSION['ZWII_SITE_CONTENT']) && $_SESSION['ZWII_SITE_CONTENT'] === $key) {
$messageLocale = helper::translate('Langue du site sélectionnée'); $messageLocale = helper::translate('Langue du site sélectionnée');
} else { } else {
$messageLocale = ''; $messageLocale = '';
@ -217,19 +211,22 @@ class translate extends common
'help' => 'Éditer' 'help' => 'Éditer'
]), ]),
template::button('translateContentLanguageLocaleDelete' . $key, [ template::button('translateContentLanguageLocaleDelete' . $key, [
'class' => ' buttonRed' . ($messageLocale ? ' disabled' : ''), 'class' => 'translateDelete buttonRed' . ($messageLocale ? ' disabled' : ''),
'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/locale/' . $key . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/locale/' . $key,
'value' => template::ico('trash'), 'value' => template::ico('trash'),
'help' => 'Supprimer', 'help' => 'Supprimer',
]) ])
]; ];
} }
} }
}
// Activation du bouton de copie // Activation du bouton de copie
self::$siteCopy = count(self::$languagesInstalled) > 1 ? false : true; self::$siteCopy = count(self::$languagesInstalled) > 1 ? false : true;
// -------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------
// Onglet des langues de l'interface // Langues de l'UI
// --------------------------------------------------------------------------------------------------
// Langues attachées à des utilisateurs non effaçables // Langues attachées à des utilisateurs non effaçables
$usersUI = []; $usersUI = [];
@ -239,11 +236,15 @@ class translate extends common
} }
// Langues installées // Langues installées
$installedUI = $this->getData(['languages']); $installedUI = $this->getData(['language']);
if (array_key_exists('language', $installedUI)) {
$installedUI = $installedUI['language'];
}
// Langues disponibles en ligne // Langues disponibles en ligne
$storeUI = json_decode(helper::getUrlContents(common::ZWII_UI_URL . 'languages.json'), true); $storeUI = json_decode(helper::getUrlContents(self::ZWII_UI_URL . 'language.json'), true);
$storeUI = $storeUI['languages']; $storeUI = $storeUI ? $storeUI['language'] : null;
// Construction du tableau à partir des langues disponibles dans le store // Construction du tableau à partir des langues disponibles dans le store
foreach ($installedUI as $file => $value) { foreach ($installedUI as $file => $value) {
@ -253,26 +254,24 @@ class translate extends common
self::$languagesUiInstalled[$file] = [ self::$languagesUiInstalled[$file] = [
template::flag($file, '20 %') . '&nbsp;' . self::$languages[$file], template::flag($file, '20 %') . '&nbsp;' . self::$languages[$file],
$value['version'], $value['version'],
helper::dateUTF8('%d/%m/%Y', $value['date']), helper::dateUTF8('%d/%m/%Y', $value['date'], self::$i18nUI),
//self::$i18nUI === $file ? helper::translate('Interface') : '', //self::$i18nUI === $file ? helper::translate('Interface') : '',
'', '',
/*
template::button('translateContentLanguageUIEdit' . $file, [ template::button('translateContentLanguageUIEdit' . $file, [
'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $file, 'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $file,
'value' => template::ico('pencil'), 'value' => template::ico('pencil'),
'help' => 'Éditer', 'help' => 'Éditer',
'disabled' => 'fr_FR' === $file 'disabled' => 'fr_FR' === $file
]), ]),
*/
template::button('translateContentLanguageUIDownload' . $file, [ template::button('translateContentLanguageUIDownload' . $file, [
'class' => version_compare($installedUI[$file]['version'], $storeUI[$file]['version']) < 0 ? 'buttonGreen' : '', 'class' => isset($storeUI[$file]['version']) && version_compare($installedUI[$file]['version'], $storeUI[$file]['version']) < 0 ? 'buttonGreen' : '',
'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file,
'value' => template::ico('update'), 'value' => template::ico('update'),
'help' => 'Mettre à jour', 'help' => 'Mise à jour',
]), ]),
template::button('translateContentLanguageUIDelete' . $file, [ template::button('translateContentLanguageUIDelete' . $file, [
'class' => 'buttonRed' . (in_array($file, $usersUI) ? ' disabled' : ''), 'class' => 'translateDelete buttonRed' . (in_array($file, $usersUI) ? ' disabled' : ''),
'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/ui/' . $file . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/ui/' . $file,
'value' => template::ico('trash'), 'value' => template::ico('trash'),
'help' => 'Supprimer', 'help' => 'Supprimer',
]), ]),
@ -280,6 +279,7 @@ class translate extends common
} }
} }
// Construction du tableau à partir des langues disponibles dans le store // Construction du tableau à partir des langues disponibles dans le store
if ($storeUI) {
foreach ($storeUI as $file => $value) { foreach ($storeUI as $file => $value) {
// La langue est-elle installée ? // La langue est-elle installée ?
@ -287,22 +287,34 @@ class translate extends common
self::$languagesStore[$file] = [ self::$languagesStore[$file] = [
template::flag($file, '20 %') . '&nbsp;' . self::$languages[$file], template::flag($file, '20 %') . '&nbsp;' . self::$languages[$file],
$value['version'], $value['version'],
helper::dateUTF8('%d/%m/%Y', $value['date']), helper::dateUTF8('%d/%m/%Y', $value['date'], self::$i18nUI),
'', '',
template::button('translateContentLanguageUIDownload' . $file, [ template::button('translateContentLanguageUIDownload' . $file, [
'class' => 'buttonGreen', 'class' => 'buttonGreen',
'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file,
'value' => template::ico('shopping-basket'), 'value' => template::ico('shopping-basket'),
'help' => 'Installer', 'help' => 'Installer',
]) ])
]; ];
} }
} }
}
// Pointer vers la fenêtre
switch ($this->getUrl(1)) {
case 'interface':
setcookie('translateLayout', 'ui', time() + 3600, '/', '', false, false);
break;
case 'site':
setcookie('translateLayout', 'content', time() + 3600, '/', '', false, false);
break;
default:
break;
}
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Multilingue'), 'title' => helper::translate('Langues'),
'view' => 'index' 'view' => 'index'
]); ]);
} }
@ -316,18 +328,25 @@ class translate extends common
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Création du contenu
$lang = $this->getInput('translateAddContent'); $lang = $this->getInput('translateAddContent');
// Stockage dans un sous-dossier localisé // Constructeur pour cette langue
if (!file_exists(self::DATA_DIR . $lang)) { $this->jsonDB($lang);
mkdir(self::DATA_DIR . $lang, 0755);
} // Création du contenu
$this->initData('page', $lang);
$this->initData('module', $lang);
$this->initData('locale', $lang);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'language',
'notification' => helper::translate('Modifications enregistrées'), 'notification' => helper::translate('Modifications enregistrées'),
'state' => true 'state' => true
]); ]);
@ -356,21 +375,24 @@ class translate extends common
*/ */
public function locale() public function locale()
{ {
// Jeton incorrect ou URl avec le code langue incorrecte // Action interdite ou URl avec le code langue incorrecte
$lang = $this->getUrl(2); $lang = $this->getUrl(2);
if ( if (
array_key_exists($lang, self::$languages) === false array_key_exists($lang, self::$languages) === false
) { ) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'language',
'state' => false, 'state' => false,
'notification' => helper::translate('Action interdite') 'notification' => helper::translate('Action interdite')
]); ]);
} }
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Sauvegarder les locales // Sauvegarder les locales
$data = [ $data = [
@ -381,6 +403,7 @@ class translate extends common
'page302' => $this->getInput('localePage302'), 'page302' => $this->getInput('localePage302'),
'legalPageId' => $this->getInput('localeLegalPageId'), 'legalPageId' => $this->getInput('localeLegalPageId'),
'searchPageId' => $this->getInput('localeSearchPageId'), 'searchPageId' => $this->getInput('localeSearchPageId'),
'poweredPageLabel' => empty($this->getInput('localePoweredPageLabel', helper::FILTER_STRING_SHORT)) ? 'Motorisé par' : $this->getInput('localePoweredPageLabel', helper::FILTER_STRING_SHORT),
'searchPageLabel' => empty($this->getInput('localeSearchPageLabel', helper::FILTER_STRING_SHORT)) ? 'Rechercher' : $this->getInput('localeSearchPageLabel', helper::FILTER_STRING_SHORT), 'searchPageLabel' => empty($this->getInput('localeSearchPageLabel', helper::FILTER_STRING_SHORT)) ? 'Rechercher' : $this->getInput('localeSearchPageLabel', helper::FILTER_STRING_SHORT),
'legalPageLabel' => empty($this->getInput('localeLegalPageLabel', helper::FILTER_STRING_SHORT)) ? 'Mentions légales' : $this->getInput('localeLegalPageLabel', helper::FILTER_STRING_SHORT), 'legalPageLabel' => empty($this->getInput('localeLegalPageLabel', helper::FILTER_STRING_SHORT)) ? 'Mentions légales' : $this->getInput('localeLegalPageLabel', helper::FILTER_STRING_SHORT),
'sitemapPageLabel' => empty($this->getInput('localeSitemapPageLabel', helper::FILTER_STRING_SHORT)) ? 'Plan du site' : $this->getInput('localeSitemapPageLabel', helper::FILTER_STRING_SHORT), 'sitemapPageLabel' => empty($this->getInput('localeSitemapPageLabel', helper::FILTER_STRING_SHORT)) ? 'Plan du site' : $this->getInput('localeSitemapPageLabel', helper::FILTER_STRING_SHORT),
@ -398,12 +421,12 @@ class translate extends common
]; ];
// Sauvegarde hors méthodes si la langue n'est pas celle de l'UI // Sauvegarde hors méthodes si la langue n'est pas celle de l'UI
if ($lang === self::$i18nUI) { if ($lang === self::$siteContent) {
// Enregistrer les données par lecture directe du formulaire // Enregistrer les données par lecture directe du formulaire
$this->setData(['locale', $data['locale']]); $this->setData(['locale', $data['locale']]);
} else { } else {
// Sauver sur le disque // Sauver sur le disque
file_put_contents(self::DATA_DIR . $lang . '/locale.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX); $this->secure_file_put_contents(self::DATA_DIR . $lang . '/locale.json', $data);
} }
// Valeurs en sortie // Valeurs en sortie
@ -418,7 +441,7 @@ class translate extends common
//----------------------------------------- //-----------------------------------------
// La locale est-elle celle de la langue de l'UI ? // La locale est-elle celle de la langue de l'UI ?
if ($lang === self::$i18nUI) { if ($lang === self::$siteContent) {
self::$locales[$lang]['locale'] = $this->getData(['locale']); self::$locales[$lang]['locale'] = $this->getData(['locale']);
} else { } else {
// Lire les locales sans passer par les méthodes // Lire les locales sans passer par les méthodes
@ -460,19 +483,22 @@ class translate extends common
public function edit() public function edit()
{ {
$lang = $this->getUrl(2); $lang = $this->getUrl(2);
// Jeton incorrect ou URl avec le code langue incorrecte // Action interdite ou URl avec le code langue incorrecte
if ( if (
array_key_exists($lang, self::$languages) === false array_key_exists($lang, self::$languages) === false
) { ) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'language',
'state' => false, 'state' => false,
'notification' => helper::translate('Action interdite') 'notification' => helper::translate('Action interdite')
]); ]);
} }
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Sauvegarder les champs de la langue // Sauvegarder les champs de la langue
$data = json_decode(file_get_contents(self::I18N_DIR . $lang . '.json'), true); $data = json_decode(file_get_contents(self::I18N_DIR . $lang . '.json'), true);
@ -482,11 +508,11 @@ class translate extends common
$data[$key] = $target; $data[$key] = $target;
} }
} }
file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX); file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($data));
// Mettre à jour le descripteur // Mettre à jour le descripteur
$this->setData([ $this->setData([
'languages', 'language',
$lang, $lang,
[ [
'version' => $this->getInput('translateEditVersion'), 'version' => $this->getInput('translateEditVersion'),
@ -497,7 +523,7 @@ class translate extends common
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), 'notification' => helper::translate('Modifications enregistrées'),
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'language',
'state' => true, 'state' => true,
]); ]);
} }
@ -510,13 +536,18 @@ class translate extends common
} }
// Ajout des champs absents selon la langue de référence // Ajout des champs absents selon la langue de référence
/*
$dataFr = json_decode(file_get_contents(self::I18N_DIR . 'fr_FR.json'), true); $dataFr = json_decode(file_get_contents(self::I18N_DIR . 'fr_FR.json'), true);
foreach ($dataFr as $key => $value) { foreach ($dataFr as $key => $value) {
if (!array_key_exists($key, $data)) { if (!array_key_exists($key, $data)) {
$data[$key] = ''; $data[$key] = '';
} }
} }
file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX); file_put_contents(self::I18N_DIR . $lang . '.json', $data);
*/
// Trier le tableau
asort($data);
// Tableau des chaines à traduire dans la langue sélectionnée // Tableau des chaines à traduire dans la langue sélectionnée
foreach ($data as $key => $value) { foreach ($data as $key => $value) {
@ -539,7 +570,7 @@ class translate extends common
'title' => helper::translate('Éditer les dialogues') . '&nbsp;' . template::flag($lang, '20 %'), 'title' => helper::translate('Éditer les dialogues') . '&nbsp;' . template::flag($lang, '20 %'),
'view' => 'edit', 'view' => 'edit',
'vendor' => [ 'vendor' => [
'flatpickr', 'tablednd'
], ],
]); ]);
} }
@ -549,16 +580,23 @@ class translate extends common
*/ */
public function delete() public function delete()
{ {
// Jeton incorrect ou URl avec le code langue incorrecte
$target = $this->getUrl(2);
$lang = $this->getUrl(3);
if ( if (
$this->getUrl(4) !== $_SESSION['csrf'] $this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|| array_key_exists($lang, self::$languages) === false
) { ) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'access' => false
]);
} else {
// Action interdite ou URl avec le code langue incorrecte
$target = $this->getUrl(2);
$lang = $this->getUrl(3);
if (
array_key_exists($lang, self::$languages) === false
) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'language',
'state' => false, 'state' => false,
'notification' => helper::translate('Action interdite') 'notification' => helper::translate('Action interdite')
]); ]);
@ -568,11 +606,11 @@ class translate extends common
$success = false; $success = false;
// Effacement d'une site dans une langue // Effacement d'une site dans une langue
if (is_dir(self::DATA_DIR . $lang) === true) { if (is_dir(self::DATA_DIR . $lang) === true) {
$success = $this->removeDir(self::DATA_DIR . $lang); $success = $this->deleteDir(self::DATA_DIR . $lang);
} }
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'language',
'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'), 'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'),
'state' => $success 'state' => $success
]); ]);
@ -582,13 +620,12 @@ class translate extends common
$success = false; $success = false;
// Effacement d'une langue de l'interface // Effacement d'une langue de l'interface
if (file_exists(self::I18N_DIR . $lang . '.json') === true) { if (file_exists(self::I18N_DIR . $lang . '.json') === true) {
$this->deleteData(['languages', $lang]); $this->deleteData(['language', $lang]);
$success = unlink(self::I18N_DIR . $lang . '.json'); $success = unlink(self::I18N_DIR . $lang . '.json');
} }
// Effacer la langue dans la base
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'translate', 'redirect' => helper::baseUrl() . 'language',
'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'), 'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'),
'state' => $success 'state' => $success
]); ]);
@ -598,7 +635,50 @@ class translate extends common
break; break;
} }
} }
}
/*
* Modifie la langue du site par défaut
*
*/
public function default()
{
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
// Action interdite ou URl avec le code langue incorrecte
$lang = $this->getUrl(2);
if (
array_key_exists($lang, self::$languages) === false
) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'language',
'state' => false,
'notification' => helper::translate('Action interdite')
]);
}
foreach (self::$languages as $key => $value) {
if (file_exists(self::DATA_DIR . $key . '/.default')) {
unlink(self::DATA_DIR . $key . '/.default');
touch(self::DATA_DIR . $lang . '/.default');
break;
}
}
// Valeurs en sortie
$this->addOutput([
'notification' => helper::translate('Modifications enregistrées'),
'redirect' => helper::baseUrl() . 'language',
'state' => true,
]);
}
}
/* /*
* Traitement du changement de langue * Traitement du changement de langue
@ -612,25 +692,21 @@ class translate extends common
* Changement de la langue si * Changement de la langue si
* différe de la langue active * différe de la langue active
* déjà initialisée * déjà initialisée
* fait partie des lnagues installées * fait partie des langues installées
*/ */
if (
$this->getInput('ZWII_CONTENT') !== $lang
&&
is_dir(self::DATA_DIR . $lang)
&&
array_key_exists($lang, self::$languages) === true
if (
is_dir(self::DATA_DIR . $lang) &&
array_key_exists($lang, self::$languages) === true
) { ) {
// Nettoyer le cookie
helper::deleteCookie('ZWII_CONTENT'); // Stocker la sélection
// Stocker le choix $_SESSION['ZWII_SITE_CONTENT'] = $lang;
setcookie('ZWII_CONTENT', $lang, time() + 3600, helper::baseUrl(false, false), '', true, helper::isHttps());
} }
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . $this->getData(['locale', $this->getUrl(2), 'homePageId']) 'redirect' => helper::baseUrl()
]); ]);
} }

View File

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

View File

@ -3,7 +3,7 @@
<div class="col1"> <div class="col1">
<?php echo template::button('translateFormBack', [ <?php echo template::button('translateFormBack', [
'class' => 'buttonGrey', 'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'translate', 'href' => helper::baseUrl() . 'language',
'value' => template::ico('left') 'value' => template::ico('left')
]); ?> ]); ?>
</div> </div>

View File

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

View File

@ -3,7 +3,7 @@
<div class="col1"> <div class="col1">
<?php echo template::button('translateFormCopyBack', [ <?php echo template::button('translateFormCopyBack', [
'class' => 'buttonGrey', 'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'translate', 'href' => helper::baseUrl() . 'language',
'value' => template::ico('left') 'value' => template::ico('left')
]); ?> ]); ?>
</div> </div>

View File

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

View File

@ -3,7 +3,7 @@
<div class="col1"> <div class="col1">
<?php echo template::button('translateUIFormBack', [ <?php echo template::button('translateUIFormBack', [
'class' => 'buttonGrey', 'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'translate', 'href' => helper::baseUrl() . 'language',
'value' => template::ico('left') 'value' => template::ico('left')
]); ?> ]); ?>
</div> </div>
@ -21,14 +21,14 @@
<div class="col6"> <div class="col6">
<?php echo template::text('translateEditVersion', [ <?php echo template::text('translateEditVersion', [
'label' => 'Version n°', 'label' => 'Version n°',
'value' => $this->getData(['languages', $this->getUrl(2), 'version']) 'value' => $this->getData(['language', $this->getUrl(2), 'version'])
]); ?> ]); ?>
</div> </div>
<div class="col6"> <div class="col6">
<?php echo template::date('translateEditDate', [ <?php echo template::date('translateEditDate', [
'label' => 'Date de publication', 'label' => 'Date de publication',
'type' => 'datetime-local', 'type' => 'datetime-local',
'value' => $this->getData(['languages', $this->getUrl(2), 'date']) 'value' => $this->getData(['language', $this->getUrl(2), 'date'])
]); ?> ]); ?>
</div> </div>
</div> </div>

View File

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

View File

@ -6,7 +6,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -52,7 +52,7 @@ $("#translateContentButton").on("click", function() {
*/ */
$(".translateDelete").on("click", function() { $(".translateDelete").on("click", function() {
var _this = $(this); var _this = $(this);
var message_delete = "<?php echo helper::translate('Confirmer la suppression de cette traduction du site'); ?>"; var message_delete = "<?php echo helper::translate('Confirmer la suppression de cette langue'); ?>";
return core.confirm(message_delete, function() { return core.confirm(message_delete, function() {
$(location).attr("href", _this.attr("href")); $(location).attr("href", _this.attr("href"));
}); });

View File

@ -4,7 +4,7 @@
<?php echo template::button('translateFormBack', [ <?php echo template::button('translateFormBack', [
'class' => 'buttonGrey', 'class' => 'buttonGrey',
'href' => helper::baseUrl(), 'href' => helper::baseUrl(),
'value' => template::ico('left') 'value' => template::ico('home')
]); ?> ]); ?>
</div> </div>
<div class="col1"> <div class="col1">
@ -16,7 +16,6 @@
'help' => 'Consulter l\'aide en ligne' 'help' => 'Consulter l\'aide en ligne'
]);*/?> ]);*/?>
</div> </div>
</div> </div>
<div class="tab"> <div class="tab">
@ -38,7 +37,7 @@
<?php echo helper::translate('Langues installées'); ?> <?php echo helper::translate('Langues installées'); ?>
</h4> </h4>
<?php if ($module::$languagesUiInstalled): ?> <?php if ($module::$languagesUiInstalled): ?>
<?php echo template::table([2, 1, 1, 5, 1, 1], $module::$languagesUiInstalled, ['Langues', 'Version', 'Date', '', '', '']); ?> <?php echo template::table([2, 1, 1, 4, 1, 1, 1], $module::$languagesUiInstalled, ['Langues', 'Version', 'Date', '', '', '', '']); ?>
<?php endif; ?> <?php endif; ?>
</div> </div>
</div> </div>
@ -65,7 +64,7 @@
</h4> </h4>
<div class="col4 offset2"> <div class="col4 offset2">
<?php echo template::button('translateButtonCopyContent', [ <?php echo template::button('translateButtonCopyContent', [
'href' => helper::baseUrl() . 'translate/copy', 'href' => helper::baseUrl() . 'language/copy',
'ico' => 'docs', 'ico' => 'docs',
'disabled' => $module::$siteCopy, 'disabled' => $module::$siteCopy,
'value' => 'Copie de contenus localisés' 'value' => 'Copie de contenus localisés'
@ -73,7 +72,7 @@
</div> </div>
<div class="col4"> <div class="col4">
<?php echo template::button('translateButtonAddContent', [ <?php echo template::button('translateButtonAddContent', [
'href' => helper::baseUrl() . 'translate/add', 'href' => helper::baseUrl() . 'language/add',
'ico' => 'plus', 'ico' => 'plus',
'class' => 'buttonGreen', 'class' => 'buttonGreen',
'value' => 'Nouveau contenu localisé' 'value' => 'Nouveau contenu localisé'

View File

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

View File

@ -3,7 +3,7 @@
<div class="col1"> <div class="col1">
<?php echo template::button('translateFormBack', [ <?php echo template::button('translateFormBack', [
'class' => 'buttonGrey', 'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'translate', 'href' => helper::baseUrl() . 'language',
'value' => template::ico('left') 'value' => template::ico('left')
]); ?> ]); ?>
</div> </div>
@ -107,20 +107,27 @@
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Étiquettes des pages spéciales'); ?> <h4><?php echo helper::translate('Étiquettes des pages spéciales'); ?>
<!--<span id="labelHelpButton" class="helpDisplayButton" title="Cliquer pour consulter l'aide en ligne"> <!--<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']); ?> <?php //echo template::ico('help', ['margin' => 'left']); ?>
</a> </a>
</span>--> </span>-->
</h4> </h4>
<div class="row"> <div class="row">
<div class="col6"> <div class="col4">
<?php echo template::text('localePoweredPageLabel', [
'label' => 'Motorisé par',
'placeholder' => 'Motorisé par',
'value' => $module::$locales[$this->getUrl(2)]['locale']['poweredPageLabel']
]); ?>
</div>
<div class="col4">
<?php echo template::text('localeLegalPageLabel', [ <?php echo template::text('localeLegalPageLabel', [
'label' => 'Mentions légales', 'label' => 'Mentions légales',
'placeholder' => 'Mentions légales', 'placeholder' => 'Mentions légales',
'value' => $module::$locales[$this->getUrl(2)]['locale']['legalPageLabel'] 'value' => $module::$locales[$this->getUrl(2)]['locale']['legalPageLabel']
]); ?> ]); ?>
</div> </div>
<div class="col6"> <div class="col4">
<?php echo template::text('localeSearchPageLabel', [ <?php echo template::text('localeSearchPageLabel', [
'label' => 'Rechercher', 'label' => 'Rechercher',
'placeholder' => 'Rechercher', 'placeholder' => 'Rechercher',
@ -129,14 +136,14 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col6"> <div class="col4 offset2">
<?php echo template::text('localeSitemapPageLabel', [ <?php echo template::text('localeSitemapPageLabel', [
'label' => 'Plan du site', 'label' => 'Plan du site',
'placeholder' => 'Plan du site', 'placeholder' => 'Plan du site',
'value' => $module::$locales[$this->getUrl(2)]['locale']['sitemapPageLabel'], 'value' => $module::$locales[$this->getUrl(2)]['locale']['sitemapPageLabel'],
]); ?> ]); ?>
</div> </div>
<div class="col6"> <div class="col4">
<?php echo template::text('localeCookiesFooterText', [ <?php echo template::text('localeCookiesFooterText', [
'label' => 'Cookies', 'label' => 'Cookies',
'value' => $module::$locales[$this->getUrl(2)]['locale']['cookies']['cookiesFooterText'], 'value' => $module::$locales[$this->getUrl(2)]['locale']['cookies']['cookiesFooterText'],

View File

@ -8,7 +8,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -41,7 +41,7 @@ class maintenance extends common
? '' ? ''
: $this->getData(['page', $this->getData(['locale', 'page302']), 'title']), : $this->getData(['page', $this->getData(['locale', 'page302']), 'title']),
//'content' => $this->getdata(['page',$this->getData(['locale','page302']),'content']), //'content' => $this->getdata(['page',$this->getData(['locale','page302']),'content']),
'content' => $this->getPage($this->getData(['locale', 'page302']), self::$i18nContent), 'content' => $this->getPage($this->getData(['locale', 'page302']), self::$siteContent),
'view' => 'index' 'view' => 'index'
]); ]);
} else { } else {

View File

@ -9,7 +9,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -18,12 +18,13 @@ class page extends common
{ {
public static $actions = [ public static $actions = [
'add' => self::GROUP_MODERATOR, 'add' => self::GROUP_EDITOR,
'delete' => self::GROUP_MODERATOR, 'delete' => self::GROUP_EDITOR,
'edit' => self::GROUP_MODERATOR, 'edit' => self::GROUP_EDITOR,
'duplicate' => self::GROUP_MODERATOR, 'duplicate' => self::GROUP_EDITOR,
'jsEditor' => self::GROUP_MODERATOR, 'jsEditor' => self::GROUP_EDITOR,
'cssEditor' => self::GROUP_MODERATOR 'cssEditor' => self::GROUP_EDITOR,
'register' => self::GROUP_EDITOR,
]; ];
public static $pagesNoParentId = [ public static $pagesNoParentId = [
'' => 'Aucune' '' => 'Aucune'
@ -65,63 +66,78 @@ class page extends common
true => 'Menu accessoire' true => 'Menu accessoire'
]; ];
public static $userProfils = [];
public static $navIconTemplate = [
'dir' => 'Petit triangle',
'open' => 'Grand triangle',
'big' => 'Flèche',
];
public static $navIconPosition = [
'none' => 'Masqué',
'top' => 'Haut de page',
'bottom' => 'Bas de page',
];
/** /**
* Duplication * Duplication
*/ */
public function duplicate() public function duplicate()
{ {
// La session ne correspond pas au site ouvert dans cet onglet
if (
// Contrôle la présence de l'id de langue 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 // Adresse sans le token
$url = explode('&', $this->getUrl(2)); $page = $this->getUrl(2);
// La page n'existe pas // La page n'existe pas
if ($this->getData(['page', $url[0]]) === null) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
$this->getData(['page', $page]) === null
) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'access' => false 'access' => false
]); ]);
} // Jeton incorrect } else {
elseif (!isset($_GET['csrf'])) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0],
'notification' => helper::translate('Jeton invalide')
]);
} elseif ($_GET['csrf'] !== $_SESSION['csrf']) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0],
'notification' => helper::translate('Suppression interdite')
]);
}
// Duplication de la page // Duplication de la page
$pageTitle = $this->getData(['page', $url[0], 'title']); $pageTitle = $this->getData(['page', $page, 'title']);
$pageId = helper::increment(helper::filter($pageTitle, helper::FILTER_ID), $this->getData(['page'])); $pageId = helper::increment(helper::filter($pageTitle, helper::FILTER_ID), $this->getData(['page']));
$pageId = helper::increment($pageId, self::$coreModuleIds); $pageId = helper::increment($pageId, self::$coreModuleIds);
$pageId = helper::increment($pageId, self::$moduleIds); $pageId = helper::increment($pageId, self::$moduleIds);
$data = $this->getData([ $data = $this->getData([
'page', 'page',
$url[0] $page
]); ]);
// Ecriture // Ecriture
$this->setData(['page', $pageId, $data]); $this->setData(['page', $pageId, $data], false);
$notification = helper::translate('Page dupliquée'); $notification = helper::translate('Page dupliquée');
// Duplication du module présent // Duplication du module présent
if ($this->getData(['page', $url[0], 'moduleId'])) { if ($this->getData(['page', $page, 'moduleId'])) {
$data = $this->getData([ $data = $this->getData(['module', $page]);
'module', $this->setData(['module', $pageId, $data], false);
$url[0]
]);
// Ecriture
$this->setData(['module', $pageId, $data]);
$notification = helper::translate('Page et module dupliqués'); $notification = helper::translate('Page et module dupliqués');
} }
// Force la sauvegarde
$this->saveDB('page');
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $pageId, 'redirect' => helper::baseUrl() . 'page/edit/' . $pageId . '/' . self::$siteContent,
'notification' => $notification, 'notification' => $notification,
'state' => true 'state' => true
]); ]);
} }
}
/** /**
@ -129,6 +145,22 @@ class page extends common
*/ */
public function add() public function add()
{ {
// La session ne correspond pas au site ouvert dans cet onglet
if (
// Contrôle la présence de l'id de langue 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
]);
} else {
$pageTitle = 'Nouvelle page'; $pageTitle = 'Nouvelle page';
$pageId = helper::increment(helper::filter($pageTitle, helper::FILTER_ID), $this->getData(['page'])); $pageId = helper::increment(helper::filter($pageTitle, helper::FILTER_ID), $this->getData(['page']));
$this->setData([ $this->setData([
@ -154,6 +186,9 @@ class page extends common
'block' => '12', 'block' => '12',
'barLeft' => '', 'barLeft' => '',
'barRight' => '', 'barRight' => '',
'navLeft' => 'none',
'navRight' => 'none',
'navTemplate' => 'dir',
'displayMenu' => '0', 'displayMenu' => '0',
'hideMenuSide' => false, 'hideMenuSide' => false,
'hideMenuHead' => false, 'hideMenuHead' => false,
@ -163,15 +198,15 @@ class page extends common
] ]
]); ]);
// Creation du contenu de la page // Creation du contenu de la page
if (!is_dir(self::DATA_DIR . self::$i18nContent . '/content')) { if (!is_dir(self::DATA_DIR . self::$siteContent . '/content')) {
mkdir(self::DATA_DIR . self::$i18nContent . '/content', 0755); mkdir(self::DATA_DIR . self::$siteContent . '/content', 0755);
} }
//file_put_contents(self::DATA_DIR . self::$i18nContent . '/content/' . $pageId . '.html', '<p>Contenu de votre nouvelle page.</p>'); //$this->secure_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::$i18nContent); $this->setPage($pageId, '<p>Contenu de votre nouvelle page.</p>', self::$siteContent);
// Met à jour le site map
$this->createSitemap('all'); // Ne met à jour le sitemap pour éviter un warning, de toute manière la nouvelle page doit être éditée.
// Mise à jour de la liste des pages pour TinyMCE // $this->updateSitemap();
$this->listPages();
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . $pageId, 'redirect' => helper::baseUrl() . $pageId,
@ -180,125 +215,112 @@ class page extends common
]); ]);
} }
}
/** /**
* Suppression * Suppression
*/ */
public function delete() public function delete()
{ {
// La session ne correspond pas au site ouvert dans cet onglet
if (
// Contrôle la présence de l'id de langue 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 // $url prend l'adresse sans le token
$url = explode('&', $this->getUrl(2)); $page = $this->getUrl(2);
// La page n'existe pas // La page n'existe pas
if ($this->getData(['page', $url[0]]) === null) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
$this->getData(['page', $page]) === null
) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'access' => false 'access' => false
]); ]);
} // Jeton incorrect
elseif (!isset($_GET['csrf'])) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0],
'notification' => helper::translate('Jeton invalide')
]);
} elseif ($_GET['csrf'] !== $_SESSION['csrf']) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0],
'notification' => helper::translate('Suppression interdite')
]);
} }
// Impossible de supprimer la page d'accueil // Impossible de supprimer la page d'accueil
elseif ($url[0] === $this->getData(['locale', 'homePageId'])) { elseif ($page === $this->getData(['locale', 'homePageId'])) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'config', 'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site') 'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
]); ]);
} }
// Impossible de supprimer la page de recherche affectée // Impossible de supprimer la page affectée
elseif ($url[0] === $this->getData(['locale', 'searchPageId'])) { elseif ($page === $this->getData(['locale', 'searchPageId'])) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'config', 'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site') 'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
]); ]);
} }
// Impossible de supprimer la page des mentions légales affectée // Impossible de supprimer la page affectée
elseif ($url[0] === $this->getData(['locale', 'legalPageId'])) { elseif ($page === $this->getData(['locale', 'legalPageId'])) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'config', 'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site') 'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
]); ]);
} }
// Impossible de supprimer la page des mentions légales affectée // Impossible de supprimer la page affectée
elseif ($url[0] === $this->getData(['locale', 'page404'])) { elseif ($page === $this->getData(['locale', 'page404'])) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'config', 'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site') 'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
]); ]);
} }
// Impossible de supprimer la page des mentions légales affectée // Impossible de supprimer la page affectée
elseif ($url[0] === $this->getData(['locale', 'page403'])) { elseif ($page === $this->getData(['locale', 'page403'])) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'config', 'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site') 'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
]); ]);
} }
// Impossible de supprimer la page des mentions légales affectée // Impossible de supprimer la page affectée
elseif ($url[0] === $this->getData(['locale', 'page302'])) { elseif ($page === $this->getData(['locale', 'page302'])) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'config', 'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site') 'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
]);
}
// Jeton incorrect
elseif (!isset($_GET['csrf'])) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0],
'notification' => helper::translate('Jeton invalide')
]);
} elseif ($_GET['csrf'] !== $_SESSION['csrf']) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0],
'notification' => helper::translate('Suppression interdite')
]); ]);
} }
// Impossible de supprimer une page contenant des enfants // Impossible de supprimer une page contenant des enfants
elseif ($this->getHierarchy($url[0], null)) { elseif ($this->getHierarchy($page, null)) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0], 'redirect' => helper::baseUrl() . 'page/edit/' . $page . '/' . self::$siteContent,
'notification' => helper::translate('Impossible de supprimer une page contenant des pages enfants') 'notification' => helper::translate('Impossible de supprimer une page contenant des pages enfants')
]); ]);
} }
// Suppression // Suppression
else { else {
// Effacer le dossier du module // Effacer le dossier du module
$moduleId = $this->getData(['page', $url[0], 'moduleId']); $moduleId = $this->getData(['page', $page, 'moduleId']);
$modulesData = helper::getModules(); $modulesData = helper::getModules();
if ( if (
array_key_exists($moduleId, $modulesData) array_key_exists($moduleId, $modulesData)
&& is_dir($modulesData[$moduleId]['dataDirectory'] . $url[0]) && is_dir($modulesData[$moduleId]['dataDirectory'] . $page)
) { ) {
$this->removeDir($modulesData[$moduleId]['dataDirectory'] . $url[0]); $this->deleteDir($modulesData[$moduleId]['dataDirectory'] . $page);
} }
// Effacer la page // Effacer la page
$this->deleteData(['page', $url[0]]); $this->deleteData(['page', $page]);
if (file_exists(self::DATA_DIR . self::$i18nContent . '/content/' . $url[0] . '.html')) { if (file_exists(self::DATA_DIR . self::$siteContent . '/content/' . $page . '.html')) {
unlink(self::DATA_DIR . self::$i18nContent . '/content/' . $url[0] . '.html'); unlink(self::DATA_DIR . self::$siteContent . '/content/' . $page . '.html');
} }
$this->deleteData(['module', $url[0]]); $this->deleteData(['module', $page]);
// Met à jour le site map
$this->createSitemap('all'); // Met à jour le sitemap
// Mise à jour de la liste des pages pour TinyMCE $this->updateSitemap();
$this->listPages();
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl(false), 'redirect' => helper::baseUrl(false),
@ -314,8 +336,22 @@ class page extends common
*/ */
public function edit() public function edit()
{ {
// La session ne correspond pas au site ouvert dans cet onglet
if (
// Contrôle la présence de l'id de langue 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 // La page n'existe pas
if ($this->getData(['page', $this->getUrl(2)]) === null) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true ||
$this->getData(['page', $this->getUrl(2)]) === null
) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'access' => false 'access' => false
@ -324,7 +360,10 @@ class page extends common
// La page existe // La page existe
else { else {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Si le Title n'est pas vide, premier test pour positionner la notification du champ obligatoire // Si le Title n'est pas vide, premier test pour positionner la notification du champ obligatoire
if ($this->getInput('pageEditTitle', helper::FILTER_ID, true) !== null && $this->getInput('pageEditTitle') !== '') { if ($this->getInput('pageEditTitle', helper::FILTER_ID, true) !== null && $this->getInput('pageEditTitle') !== '') {
// Génére l'ID si le titre de la page a changé // Génére l'ID si le titre de la page a changé
@ -345,11 +384,13 @@ class page extends common
$pageId = helper::increment($pageId, self::$moduleIds); $pageId = helper::increment($pageId, self::$moduleIds);
// Met à jour les enfants // Met à jour les enfants
foreach ($this->getHierarchy($this->getUrl(2), null) as $childrenPageId) { foreach ($this->getHierarchy($this->getUrl(2), null) as $childrenPageId) {
$this->setData(['page', $childrenPageId, 'parentPageId', $pageId]); $this->setData(['page', $childrenPageId, 'parentPageId', $pageId], false);
} }
// Force la sauvegarde
$this->saveDB('page');
// Change l'id de page dans les données des modules // Change l'id de page dans les données des modules
if ($this->getData(['module', $this->getUrl(2)]) !== null) { 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)]); $this->deleteData(['module', $this->getUrl(2)]);
// Renommer le dossier du module // Renommer le dossier du module
$moduleId = $this->getData(['page', $this->getUrl(2), 'moduleId']); $moduleId = $this->getData(['page', $this->getUrl(2), 'moduleId']);
@ -358,10 +399,12 @@ class page extends common
// Placer la feuille de style dans un dossier au nom de la nouvelle instance // Placer la feuille de style dans un dossier au nom de la nouvelle instance
mkdir($modulesData[$moduleId]['dataDirectory'] . $pageId, 0755); mkdir($modulesData[$moduleId]['dataDirectory'] . $pageId, 0755);
copy($modulesData[$moduleId]['dataDirectory'] . $this->getUrl(2), $modulesData[$moduleId]['dataDirectory'] . $pageId); copy($modulesData[$moduleId]['dataDirectory'] . $this->getUrl(2), $modulesData[$moduleId]['dataDirectory'] . $pageId);
$this->removeDir($modulesData[$moduleId]['dataDirectory'] . $this->getUrl(2)); $this->deleteDir($modulesData[$moduleId]['dataDirectory'] . $this->getUrl(2));
// Mettre à jour le nom de la feuille de style // 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);
} }
// Force la sauvegarde
$this->saveDB('module');
} }
// Si la page correspond à la page d'accueil, change l'id dans la configuration du site // Si la page correspond à la page d'accueil, change l'id dans la configuration du site
if ($this->getData(['locale', 'homePageId']) === $this->getUrl(2)) { if ($this->getData(['locale', 'homePageId']) === $this->getUrl(2)) {
@ -375,26 +418,28 @@ class page extends common
// Supprime l'ancienne page si l'id a changée // Supprime l'ancienne page si l'id a changée
if ($pageId !== $this->getUrl(2)) { if ($pageId !== $this->getUrl(2)) {
$this->deleteData(['page', $this->getUrl(2)]); $this->deleteData(['page', $this->getUrl(2)]);
if (file_exists(self::DATA_DIR . self::$i18nContent . '/content/' . $this->getUrl(2) . '.html')) { if (file_exists(self::DATA_DIR . self::$siteContent . '/content/' . $this->getUrl(2) . '.html')) {
unlink(self::DATA_DIR . self::$i18nContent . '/content/' . $this->getUrl(2) . '.html'); unlink(self::DATA_DIR . self::$siteContent . '/content/' . $this->getUrl(2) . '.html');
} }
} }
// Traitement des pages spéciales affectées dans la config : // Traitement des pages spéciales affectées dans la config :
if ($this->getUrl(2) === $this->getData(['locale', 'legalPageId'])) { if ($this->getUrl(2) === $this->getData(['locale', 'legalPageId'])) {
$this->setData(['locale', 'legalPageId', $pageId]); $this->setData(['locale', 'legalPageId', $pageId], false);
} }
if ($this->getUrl(2) === $this->getData(['locale', 'searchPageId'])) { if ($this->getUrl(2) === $this->getData(['locale', 'searchPageId'])) {
$this->setData(['locale', 'searchPageId', $pageId]); $this->setData(['locale', 'searchPageId', $pageId], false);
} }
if ($this->getUrl(2) === $this->getData(['locale', 'page404'])) { if ($this->getUrl(2) === $this->getData(['locale', 'page404'])) {
$this->setData(['locale', 'page404', $pageId]); $this->setData(['locale', 'page404', $pageId], false);
} }
if ($this->getUrl(2) === $this->getData(['locale', 'page403'])) { if ($this->getUrl(2) === $this->getData(['locale', 'page403'])) {
$this->setData(['locale', 'page403', $pageId]); $this->setData(['locale', 'page403', $pageId], false);
} }
if ($this->getUrl(2) === $this->getData(['locale', 'page302'])) { if ($this->getUrl(2) === $this->getData(['locale', 'page302'])) {
$this->setData(['locale', 'page302', $pageId]); $this->setData(['locale', 'page302', $pageId], false);
} }
// Force la sauvegarde
$this->saveDB('locale');
// Si la page est une page enfant, actualise les positions des autres enfants du parent, sinon actualise les pages sans parents // Si la page est une page enfant, actualise les positions des autres enfants du parent, sinon actualise les pages sans parents
$lastPosition = 1; $lastPosition = 1;
$hierarchy = $this->getInput('pageEditParentPageId') ? $this->getHierarchy($this->getInput('pageEditParentPageId')) : array_keys($this->getHierarchy()); $hierarchy = $this->getInput('pageEditParentPageId') ? $this->getHierarchy($this->getInput('pageEditParentPageId')) : array_keys($this->getHierarchy());
@ -413,7 +458,7 @@ class page extends common
$lastPosition++; $lastPosition++;
} }
// Change la position // Change la position
$this->setData(['page', $hierarchyPageId, 'position', $lastPosition]); $this->setData(['page', $hierarchyPageId, 'position', $lastPosition], false);
// Incrémente pour la prochaine position // Incrémente pour la prochaine position
$lastPosition++; $lastPosition++;
} }
@ -438,30 +483,44 @@ class page extends common
) { ) {
foreach ($this->getHierarchy($pageId) as $parentId => $childId) { foreach ($this->getHierarchy($pageId) as $parentId => $childId) {
if ($this->getData(['page', $childId, 'parentPageId']) === $pageId) { if ($this->getData(['page', $childId, 'parentPageId']) === $pageId) {
$this->setData(['page', $childId, 'position', 0]); $this->setData(['page', $childId, 'position', 0], false);
} }
} }
// Force la sauvegarde
$this->saveDB('page');
} }
// La page est une barre latérale qui a été renommée : changer le nom de la barre dans les pages qui l'utilisent // La page est une barre latérale qui a été renommée : changer le nom de la barre dans les pages qui l'utilisent
if ($this->getinput('pageEditBlock') === 'bar') { if ($this->getinput('pageEditBlock') === 'bar') {
foreach ($this->getHierarchy() as $eachPageId => $parentId) { foreach ($this->getHierarchy() as $eachPageId => $parentId) {
if ($this->getData(['page', $eachPageId, 'barRight']) === $this->getUrl(2)) { 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)) { 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) { foreach ($parentId as $childId) {
if ($this->getData(['page', $childId, 'barRight']) === $this->getUrl(2)) { 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)) { if ($this->getData(['page', $childId, 'barLeft']) === $this->getUrl(2)) {
$this->setData(['page', $childId, 'barLeft', $pageId]); $this->setData(['page', $childId, 'barLeft', $pageId], false);
} }
} }
} }
} }
// Détermine le groupe selon que la page est une barre ou une page standard
$group = $this->getinput('pageEditBlock') !== 'bar' ? $this->getInput('pageEditGroup', helper::FILTER_INT) : 0;
//Détermine le profil d'utilisateur en fonction du groupe sinon le groupe vaut 0
$profil = 0;
if (
$this->getinput('pageEditBlock') !== 'bar' ||
$group === 1 ||
$group === 2
) {
$profil = $this->getInput('pageEditProfil' . $group, helper::FILTER_INT);
}
// Modifie la page ou en crée une nouvelle si l'id a changé // Modifie la page ou en crée une nouvelle si l'id a changé
$this->setData([ $this->setData([
@ -480,13 +539,17 @@ class page extends common
'modulePosition' => $this->getInput('pageModulePosition'), 'modulePosition' => $this->getInput('pageModulePosition'),
'parentPageId' => $this->getInput('pageEditParentPageId'), 'parentPageId' => $this->getInput('pageEditParentPageId'),
'position' => $position, 'position' => $position,
'group' => $this->getinput('pageEditBlock') !== 'bar' ? $this->getInput('pageEditGroup', helper::FILTER_INT) : 0, 'group' => $group,
'profil' => $profil,
'targetBlank' => $this->getInput('pageEditTargetBlank', helper::FILTER_BOOLEAN), 'targetBlank' => $this->getInput('pageEditTargetBlank', helper::FILTER_BOOLEAN),
'title' => $this->getInput('pageEditTitle', helper::FILTER_STRING_SHORT), 'title' => $this->getInput('pageEditTitle', helper::FILTER_STRING_SHORT),
'shortTitle' => $this->getInput('pageEditShortTitle', helper::FILTER_STRING_SHORT, true), 'shortTitle' => $this->getInput('pageEditShortTitle', helper::FILTER_STRING_SHORT, true),
'block' => $this->getinput('pageEditBlock'), 'block' => $this->getinput('pageEditBlock'),
'barLeft' => $barLeft, 'barLeft' => $barLeft,
'barRight' => $barRight, 'barRight' => $barRight,
'navLeft' => $this->getInput('pageEditNavLeft'),
'navRight' => $this->getInput('pageEditNavRight'),
'navTemplate' => $this->getInput('pageEditNavTemplate'),
'displayMenu' => $this->getinput('pageEditDisplayMenu'), 'displayMenu' => $this->getinput('pageEditDisplayMenu'),
'hideMenuSide' => $this->getinput('pageEditHideMenuSide', helper::FILTER_BOOLEAN), 'hideMenuSide' => $this->getinput('pageEditHideMenuSide', helper::FILTER_BOOLEAN),
'hideMenuHead' => $this->getinput('pageEditHideMenuHead', helper::FILTER_BOOLEAN), 'hideMenuHead' => $this->getinput('pageEditHideMenuHead', helper::FILTER_BOOLEAN),
@ -498,16 +561,14 @@ class page extends common
]); ]);
// Creation du contenu de la page // Creation du contenu de la page
if (!is_dir(self::DATA_DIR . self::$i18nContent . '/content')) { if (!is_dir(self::DATA_DIR . self::$siteContent . '/content')) {
mkdir(self::DATA_DIR . self::$i18nContent . '/content', 0755); mkdir(self::DATA_DIR . self::$siteContent . '/content', 0755);
} }
$content = empty($this->getInput('pageEditContent', null)) ? '<p></p>' : str_replace('<p></p>', '<p>&nbsp;</p>', $this->getInput('pageEditContent', null)); $content = empty($this->getInput('pageEditContent', null)) ? '<p></p>' : str_replace('<p></p>', '<p>&nbsp;</p>', $this->getInput('pageEditContent', null));
$this->setPage($pageId, $content, self::$i18nContent); $this->setPage($pageId, $content, self::$siteContent);
// Met à jour le site map // Met à jour le sitemap
$this->createSitemap('all'); $this->updateSitemap();
// Mise à jour de la liste des pages pour TinyMCE
$this->listPages();
// Redirection vers la configuration // Redirection vers la configuration
if ( if (
@ -531,6 +592,9 @@ class page extends common
} }
// Construction du formulaire // Construction du formulaire
// Met à jour le sitemap
$this->updateSitemap();
// Création du sélecteur de modules // Création du sélecteur de modules
self::$moduleIds = []; self::$moduleIds = [];
foreach (helper::getModules() as $key => $values) { foreach (helper::getModules() as $key => $values) {
@ -553,13 +617,20 @@ class page extends common
self::$pagesBarId[$parentPageId] = $this->getData(['page', $parentPageId, 'title']); self::$pagesBarId[$parentPageId] = $this->getData(['page', $parentPageId, 'title']);
} }
} }
// Profils installés
// Met à jour le site map // Profils disponibles
$this->createSitemap('all'); foreach ($this->getData(['profil']) as $profilId => $profilData) {
if ($profilId < self::GROUP_MEMBER) {
// Mise à jour de la liste des pages pour TinyMCE continue;
$this->listPages(); }
if ($profilId === self::GROUP_ADMIN) {
self::$userProfils[$profilId][self::GROUP_ADMIN] = $profilData['name'];
continue;
}
foreach ($profilData as $key => $value) {
self::$userProfils[$profilId][$key] = $profilData[$key]['name'];
}
}
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => $this->getData(['page', $this->getUrl(2), 'title']), 'title' => $this->getData(['page', $this->getUrl(2), 'title']),
@ -577,18 +648,22 @@ class page extends common
public function cssEditor() public function cssEditor()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
$css = $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG); $css = $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageCssEditorContent', helper::FILTER_STRING_LONG);
// Enregistre le CSS // Enregistre le CSS
$this->setData([ $this->setData([
'page', $this->getUrl(2), 'page',
$this->getUrl(2),
'css', 'css',
$css $css
]); ]);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), '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 'state' => true
]); ]);
} }
@ -608,18 +683,22 @@ class page extends common
public function jsEditor() public function jsEditor()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
$js = $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG); $js = $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG) === null ? '' : $this->getInput('pageJsEditorContent', helper::FILTER_STRING_LONG);
// Enregistre le JS // Enregistre le JS
$this->setData([ $this->setData([
'page', $this->getUrl(2), 'page',
$this->getUrl(2),
'js', 'js',
$js $js
]); ]);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), '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 'state' => true
]); ]);
} }
@ -632,4 +711,39 @@ class page extends common
'view' => 'jsEditor' 'view' => 'jsEditor'
]); ]);
} }
/**
* 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 string tableau associatif des pages dans le menu
*/
public function getPageInfo()
{
$p = $this->getData(['page']);
$d = array_map(function ($d) {
unset($d["css"], $d["js"]);
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> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */

View File

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

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -44,3 +44,7 @@
background-color: #00BFFF; background-color: #00BFFF;
} }
#pageEditProfil1Wrapper,
#pageEditProfil2Wrapper {
padding: 0;
}

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @authorFrédéric Tempez <frederic.tempez@outlook.com> * @authorFrédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -15,7 +15,7 @@
/** /**
* Confirmation de suppression * Confirmation de suppression
*/ */
$("#pageEditDelete").on("click", function() { $("#pageEditDelete").on("click", function() {
var _this = $(this); var _this = $(this);
var message_delete = "<?php echo helper::translate('Confirmer la suppression de la page'); ?>"; var message_delete = "<?php echo helper::translate('Confirmer la suppression de la page'); ?>";
return core.confirm(message_delete, function() { return core.confirm(message_delete, function() {
@ -54,19 +54,32 @@ function protectModule() {
*/ */
$( document ).ready(function() { $( document ).ready(function() {
// Changement de profil
$(".pageEditGroupProfil").hide();
$("#pageEditGroupProfil" + $("#pageEditGroup").val()).show();
$("#pageEditGroup").on("change", function () {
$(".pageEditGroupProfil").hide();
$("#pageEditGroupProfil" + $(this).val()).show();
});
/** /**
* Sélection des onglets * Sélection des onglets
*/ */
var pageLayout = getCookie("pageLayout"); var pageLayout = "<?php echo $this->getData(['user', $this->getUser('id'), 'view', 'page']);?>";
if (pageLayout == null) {
// Non défini, valeur par défaut
if (pageLayout == "") {
pageLayout = "content"; pageLayout = "content";
setCookie("pageLayout", "content");
} }
// Tout cacher
$("#pageEditContentContainer").hide(); $("#pageEditContentContainer").hide();
$("#pageEditExtensionContainer").hide(); $("#pageEditExtensionContainer").hide();
$("#pageEditPositionContainer").hide(); $("#pageEditPositionContainer").hide();
$("#pageEditLayoutContainer").hide(); $("#pageEditLayoutContainer").hide();
$("#pageEditPermissionContainer").hide(); $("#pageEditPermissionContainer").hide();
// Afficher la bonne tab
$("#pageEdit" + capitalizeFirstLetter(pageLayout) + "Container").show(); $("#pageEdit" + capitalizeFirstLetter(pageLayout) + "Container").show();
$("#pageEdit" + capitalizeFirstLetter(pageLayout) + "Button").addClass("activeButton"); $("#pageEdit" + capitalizeFirstLetter(pageLayout) + "Button").addClass("activeButton");
@ -183,6 +196,7 @@ $( document ).ready(function() {
$("#pageEditSeoWrapper").slideUp(); $("#pageEditSeoWrapper").slideUp();
$("#pageEditAdvancedWrapper").removeClass("disabled"); $("#pageEditAdvancedWrapper").removeClass("disabled");
$("#pageEditAdvancedWrapper").slideUp(); $("#pageEditAdvancedWrapper").slideUp();
$(".navSelect").slideUp();
/* /*
$("#pageEditBlockLayout").removeClass("col6"); $("#pageEditBlockLayout").removeClass("col6");
$("#pageEditBlockLayout").addClass("col12"); $("#pageEditBlockLayout").addClass("col12");
@ -284,7 +298,6 @@ $( document ).ready(function() {
$("#PageEditPositionButton").removeClass("activeButton"); $("#PageEditPositionButton").removeClass("activeButton");
$("#pageEditLayoutButton").removeClass("activeButton"); $("#pageEditLayoutButton").removeClass("activeButton");
$("#pageEditPermissionButton").removeClass("activeButton"); $("#pageEditPermissionButton").removeClass("activeButton");
setCookie("pageLayout", "content");
}); });
$("#pageEditExtensionButton").on("click", function () { $("#pageEditExtensionButton").on("click", function () {
$("#pageEditContentContainer").hide(); $("#pageEditContentContainer").hide();
@ -297,7 +310,6 @@ $( document ).ready(function() {
$("#PageEditPositionButton").removeClass("activeButton"); $("#PageEditPositionButton").removeClass("activeButton");
$("#pageEditLayoutButton").removeClass("activeButton"); $("#pageEditLayoutButton").removeClass("activeButton");
$("#pageEditPermissionButton").removeClass("activeButton"); $("#pageEditPermissionButton").removeClass("activeButton");
setCookie("pageLayout", "extension");
}); });
$("#PageEditPositionButton").on("click", function () { $("#PageEditPositionButton").on("click", function () {
$("#pageEditContentContainer").hide(); $("#pageEditContentContainer").hide();
@ -310,7 +322,6 @@ $( document ).ready(function() {
$("#PageEditPositionButton").addClass("activeButton"); $("#PageEditPositionButton").addClass("activeButton");
$("#pageEditLayoutButton").removeClass("activeButton"); $("#pageEditLayoutButton").removeClass("activeButton");
$("#pageEditPermissionButton").removeClass("activeButton"); $("#pageEditPermissionButton").removeClass("activeButton");
setCookie("pageLayout", "position");
}); });
$("#pageEditLayoutButton").on("click", function () { $("#pageEditLayoutButton").on("click", function () {
$("#pageEditContentContainer").hide(); $("#pageEditContentContainer").hide();
@ -323,7 +334,6 @@ $( document ).ready(function() {
$("#PageEditPositionButton").removeClass("activeButton"); $("#PageEditPositionButton").removeClass("activeButton");
$("#pageEditLayoutButton").addClass("activeButton"); $("#pageEditLayoutButton").addClass("activeButton");
$("#pageEditPermissionButton").removeClass("activeButton"); $("#pageEditPermissionButton").removeClass("activeButton");
setCookie("pageLayout", "layout");
}); });
$("#pageEditPermissionButton").on("click", function () { $("#pageEditPermissionButton").on("click", function () {
$("#pageEditContentContainer").hide(); $("#pageEditContentContainer").hide();
@ -336,7 +346,6 @@ $( document ).ready(function() {
$("#pageEditPositionButton").removeClass("activeButton"); $("#pageEditPositionButton").removeClass("activeButton");
$("#pageEditLayoutButton").removeClass("activeButton"); $("#pageEditLayoutButton").removeClass("activeButton");
$("#pageEditPermissionButton").addClass("activeButton"); $("#pageEditPermissionButton").addClass("activeButton");
setCookie("pageLayout", "permission");
}); });
/** /**
@ -499,6 +508,7 @@ pageEditBlockDOM.on("change", function() {
$("#pageEditModuleConfig").slideUp(); $("#pageEditModuleConfig").slideUp();
$("#pageEditDisplayMenuWrapper").addClass("disabled"); $("#pageEditDisplayMenuWrapper").addClass("disabled");
$("#pageEditDisplayMenuWrapper").slideDown(); $("#pageEditDisplayMenuWrapper").slideDown();
$(".navSelect").slideUp();
/* /*
$("#pageEditBlockLayout").removeClass("col6"); $("#pageEditBlockLayout").removeClass("col6");
$("#pageEditBlockLayout").addClass("col12"); $("#pageEditBlockLayout").addClass("col12");
@ -519,6 +529,7 @@ pageEditBlockDOM.on("change", function() {
$("#pageEditModuleConfig").slideDown(); $("#pageEditModuleConfig").slideDown();
$("#pageEditDisplayMenuWrapper").removeClass("disabled"); $("#pageEditDisplayMenuWrapper").removeClass("disabled");
$("#pageEditDisplayMenuWrapper").slideUp(); $("#pageEditDisplayMenuWrapper").slideUp();
$(".navSelect").slideDown();
if ($("#pageEditParentPageId").val() !== "") { if ($("#pageEditParentPageId").val() !== "") {
$("#pageEditbreadCrumbWrapper").addClass("disabled"); $("#pageEditbreadCrumbWrapper").addClass("disabled");
$("#pageEditbreadCrumbWrapper").slideDown(); $("#pageEditbreadCrumbWrapper").slideDown();
@ -644,7 +655,7 @@ $("#pageEditParentPageId").on("change", function() {
function buildPagesList(extraPosition) { function buildPagesList(extraPosition) {
var hierarchy = <?php echo json_encode($this->getHierarchy()); ?>; var hierarchy = <?php echo json_encode($this->getHierarchy()); ?>;
var pages = <?php echo json_encode($this->getData(['page'])); ?>; var pages = <?php echo $module->getPageInfo(); ?>;
var positionInitial = <?php echo $this->getData(['page',$this->getUrl(2),"position"]); ?>; var positionInitial = <?php echo $this->getData(['page',$this->getUrl(2),"position"]); ?>;
var extraPosition = $("#pageEditExtraPosition").val(); var extraPosition = $("#pageEditExtraPosition").val();
var positionDOM = $("#pageEditPosition"); var positionDOM = $("#pageEditPosition");
@ -709,30 +720,6 @@ function buildPagesList(extraPosition) {
positionDOM.val(positionSelected); 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 // Define function to capitalize the first letter of a string
function capitalizeFirstLetter(string) { function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1); return string.charAt(0).toUpperCase() + string.slice(1);

View File

@ -1,34 +1,23 @@
<?php echo template::formOpen('pageEditForm'); ?> <?php echo template::formOpen('pageEditForm'); ?>
<div class="row"> <div class="row">
<div class="col1"> <div class="col1">
<?php $href = helper::baseUrl() . $this->getUrl(2); ?> <?php echo template::button('configModulesBack', [
<?php if ($this->getData(['page', $this->getUrl(2), 'moduleId']) === 'redirection' || 'code') $href = helper::baseUrl(); ?>
<?php echo template::button('pageEditBack', [
'class' => 'buttonGrey', 'class' => 'buttonGrey',
'href' => $href, 'href' => helper::baseUrl() . $this->getUrl(2),
'value' => template::ico('home') 'value' => template::ico('left')
]); ?> ]); ?>
</div> </div>
<div class="col1"> <div class="col1 offset7">
<?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">
<?php echo template::button('pageEditDelete', [ <?php echo template::button('pageEditDelete', [
'class' => 'buttonRed', 'class' => 'buttonRed',
'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(2) . '&csrf=' . $_SESSION['csrf'], 'href' => helper::baseUrl() . 'page/delete/' . $this->getUrl(2) . '/' . self::$siteContent,
'value' => template::ico('trash'), 'value' => template::ico('trash'),
'help' => 'Effacer la page' 'help' => 'Effacer la page'
]); ?> ]); ?>
</div> </div>
<div class="col1"> <div class="col1">
<?php echo template::button('pageEditDuplicate', [ <?php echo template::button('pageEditDuplicate', [
'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2) . '&csrf=' . $_SESSION['csrf'], 'href' => helper::baseUrl() . 'page/duplicate/' . $this->getUrl(2) . '/' . self::$siteContent,
'value' => template::ico('clone'), 'value' => template::ico('clone'),
'help' => 'Dupliquer la page' 'help' => 'Dupliquer la page'
]); ?> ]); ?>
@ -39,27 +28,31 @@
]); ?> ]); ?>
</div> </div>
</div> </div>
<div class="tab"> <div class="tab">
<?php echo template::button('pageEditContentButton', [ <?php echo template::button('pageEditContentButton', [
'value' => 'Contenu', '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', 'value' => 'Menu',
'class' => 'buttonTab' 'class' => 'buttonTab',
'href' => helper::baseUrl() . 'page/register/position/' . $this->geturl(2)
]); ?> ]); ?>
<?php echo template::button('pageEditExtensionButton', [ <?php echo template::button('pageEditExtensionButton', [
'value' => 'Extension', 'value' => 'Extension',
'class' => 'buttonTab' 'class' => 'buttonTab',
'href' => helper::baseUrl() . 'page/register/extension/' . $this->geturl(2)
]); ?> ]); ?>
<?php echo template::button('pageEditLayoutButton', [ <?php echo template::button('pageEditLayoutButton', [
'value' => 'Mise en page', 'value' => 'Mise en page',
'class' => 'buttonTab' 'class' => 'buttonTab',
'href' => helper::baseUrl() . 'page/register/layout/' . $this->geturl(2)
]); ?> ]); ?>
<?php echo template::button('pageEditPermissionButton', [ <?php echo template::button('pageEditPermissionButton', [
'value' => 'Permission', 'value' => 'Permission',
'class' => 'buttonTab' 'class' => 'buttonTab',
'href' => helper::baseUrl() . 'page/register/permission/' . $this->geturl(2)
]); ?> ]); ?>
</div> </div>
@ -67,12 +60,8 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Titres'); ?> <h4>
<!--<span id="infoHelpButton" class="helpDisplayButton"> <?php echo helper::translate('Titres'); ?>
<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> </h4>
<div class="row"> <div class="row">
<div class="col8"> <div class="col8">
@ -109,7 +98,7 @@
<div class="col12"> <div class="col12">
<?php echo template::textarea('pageEditContent', [ <?php echo template::textarea('pageEditContent', [
'class' => 'editorWysiwyg', 'class' => 'editorWysiwyg',
'value' => $this->getPage($this->getUrl(2), self::$i18nContent) 'value' => $this->getPage($this->getUrl(2), self::$siteContent)
]); ?> ]); ?>
</div> </div>
</div> </div>
@ -119,12 +108,8 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Emplacement dans le menu'); ?> <h4>
<!--<span id="positionHelpButton" class="helpDisplayButton"> <?php echo helper::translate('Emplacement dans le menu'); ?>
<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> </h4>
<div class="blockContainer"> <div class="blockContainer">
<div class="row"> <div class="row">
@ -135,11 +120,11 @@
]); ?> ]); ?>
</div> </div>
<div class="col4"> <div class="col4">
<?php if ($this->getHierarchy($this->getUrl(2), false)) : ?> <?php if ($this->getHierarchy($this->getUrl(2), false)): ?>
<?php echo template::hidden('pageEditParentPageId', [ <?php echo template::hidden('pageEditParentPageId', [
'value' => $this->getData(['page', $this->getUrl(2), 'parentPageId']) 'value' => $this->getData(['page', $this->getUrl(2), 'parentPageId'])
]); ?> ]); ?>
<?php else : ?> <?php else: ?>
<?php echo template::select('pageEditParentPageId', $module::$pagesNoParentId, [ <?php echo template::select('pageEditParentPageId', $module::$pagesNoParentId, [
'label' => 'Page parent', 'label' => 'Page parent',
'selected' => $this->getData(['page', $this->getUrl(2), 'parentPageId']) 'selected' => $this->getData(['page', $this->getUrl(2), 'parentPageId'])
@ -174,12 +159,8 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Options avancées'); ?> <h4>
<!--<span id="advancedHelpButton" class="helpDisplayButton"> <?php echo helper::translate('Options avancées'); ?>
<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> </h4>
<div class="blockContainer"> <div class="blockContainer">
<div class="row"> <div class="row">
@ -194,7 +175,8 @@
'help' => 'Sélectionnez une image ou une icône de petite dimension', 'help' => 'Sélectionnez une image ou une icône de petite dimension',
'language' => $this->getData(['user', $this->getUser('id'), 'language']), 'language' => $this->getData(['user', $this->getUser('id'), 'language']),
'label' => 'Icône', '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>
</div> </div>
@ -221,7 +203,8 @@
<div class="row"> <div class="row">
<div class="col6"> <div class="col6">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Module'); ?> <h4>
<?php echo helper::translate('Module'); ?>
</h4> </h4>
<div class="row"> <div class="row">
<div class="col10"> <div class="col10">
@ -258,7 +241,9 @@
</div> </div>
<div class="col6"> <div class="col6">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Contenu avancé');?></h4> <h4>
<?php echo helper::translate('Contenu avancé'); ?>
</h4>
<div class="row"> <div class="row">
<div class="col6 offset3"> <div class="col6 offset3">
<?php echo template::button('pageEditCssEditor', [ <?php echo template::button('pageEditCssEditor', [
@ -286,12 +271,8 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Mise en page'); ?> <h4>
<!--<span id="layoutHelpButton" class="helpDisplayButton"> <?php echo helper::translate('Mise en page'); ?>
<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> </h4>
<div class="blockContainer"> <div class="blockContainer">
<div class="row"> <div class="row">
@ -308,21 +289,21 @@
</div> </div>
<div class="col6"> <div class="col6">
<!-- Sélection des barres latérales --> <!-- Sélection des barres latérales -->
<?php if ($this->getHierarchy($this->getUrl(2), false, true)) : ?> <?php if ($this->getHierarchy($this->getUrl(2), false, true)): ?>
<?php echo template::hidden('pageEditBarLeft', [ <?php echo template::hidden('pageEditBarLeft', [
'value' => $this->getData(['page', $this->getUrl(2), 'barLeft']) 'value' => $this->getData(['page', $this->getUrl(2), 'barLeft'])
]); ?> ]); ?>
<?php else : ?> <?php else: ?>
<?php echo template::select('pageEditBarLeft', $module::$pagesBarId, [ <?php echo template::select('pageEditBarLeft', $module::$pagesBarId, [
'label' => 'Barre latérale gauche :', 'label' => 'Barre latérale gauche :',
'selected' => $this->getData(['page', $this->getUrl(2), 'barLeft']) 'selected' => $this->getData(['page', $this->getUrl(2), 'barLeft'])
]); ?> ]); ?>
<?php endif; ?> <?php endif; ?>
<?php if ($this->getHierarchy($this->getUrl(2), false, true)) : ?> <?php if ($this->getHierarchy($this->getUrl(2), false, true)): ?>
<?php echo template::hidden('pageEditBarRight', [ <?php echo template::hidden('pageEditBarRight', [
'value' => $this->getData(['page', $this->getUrl(2), 'barRight']) 'value' => $this->getData(['page', $this->getUrl(2), 'barRight'])
]); ?> ]); ?>
<?php else : ?> <?php else: ?>
<?php echo template::select('pageEditBarRight', $module::$pagesBarId, [ <?php echo template::select('pageEditBarRight', $module::$pagesBarId, [
'label' => 'Barre latérale droite :', 'label' => 'Barre latérale droite :',
'selected' => $this->getData(['page', $this->getUrl(2), 'barRight']) 'selected' => $this->getData(['page', $this->getUrl(2), 'barRight'])
@ -335,6 +316,26 @@
]); ?> ]); ?>
</div> </div>
</div> </div>
<div class="row navSelect">
<div class="col4">
<?php echo template::select('pageEditNavLeft', $module::$navIconPosition, [
'label' => 'Bouton de navigation gauche',
'selected' => $this->getData(['page', $this->getUrl(2), 'navLeft']),
]); ?>
</div>
<div class="col4">
<?php echo template::select('pageEditNavTemplate', $module::$navIconTemplate, [
'label' => 'Modèle',
'selected' => $this->getData(['page', $this->getUrl(2), 'navTemplate']),
]); ?>
</div>
<div class="col4">
<?php echo template::select('pageEditNavRight', $module::$navIconPosition, [
'label' => 'Bouton de navigation droit',
'selected' => $this->getData(['page', $this->getUrl(2), 'navRight']),
]); ?>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -345,21 +346,38 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Permission et référencement');?> <h4>
<!--<span id="seoHelpButton" class="helpDisplayButton"> <?php echo helper::translate('Permission et référencement'); ?>
<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> </h4>
<div class="blockContainer"> <div class="blockContainer">
<div class="row"> <div class="row">
<div class='col6'> <div class='col6'>
<?php echo template::select('pageEditGroup', self::$groupPublics, [ <?php echo template::select('pageEditGroup', self::$groupPublics, [
'label' => 'Groupe requis pour accéder à la page :', 'label' => 'Groupe minimal pour accéder à la page',
'selected' => $this->getData(['page', $this->getUrl(2), 'group']) 'selected' => $this->getData(['page', $this->getUrl(2), 'group']),
'help' => 'Les groupes de niveau supérieur accèdent à la page.'
]); ?> ]); ?>
</div> </div>
<div class="col6">
<div class="pageEditGroupProfil displayNone"
id="pageEditGroupProfil<?php echo self::GROUP_MEMBER; ?>">
<?php echo template::select('pageEditProfil' . self::GROUP_MEMBER, $module::$userProfils[self::GROUP_MEMBER], [
'label' => 'Profil minimal pour accéder à la page',
'selected' => $this->getData(['page', $this->getUrl(2), 'profil']),
'help' => 'Les profils de niveau supérieur accèdent à la page.',
]); ?>
</div>
<div class="pageEditGroupProfil displayNone"
id="pageEditGroupProfil<?php echo self::GROUP_EDITOR; ?>">
<?php echo template::select('pageEditProfil' . self::GROUP_EDITOR, $module::$userProfils[self::GROUP_EDITOR], [
'label' => 'Profil minimal pour accéder à la page',
'selected' => $this->getData(['page', $this->getUrl(2), 'profil']),
'help' => 'Les profils de niveau supérieur accèdent à la page.',
]); ?>
</div>
</div>
</div>
<div class="row">
<div class='col12'> <div class='col12'>
<?php echo template::text('pageEditMetaTitle', [ <?php echo template::text('pageEditMetaTitle', [
'label' => 'Méta-titre', 'label' => 'Méta-titre',
@ -377,5 +395,4 @@
</div> </div>
</div> </div>
</div> </div>
<?php echo template::formClose(); ?> <?php echo template::formClose(); ?>

View File

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

View File

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

View File

@ -9,7 +9,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -21,14 +21,8 @@ class plugin extends common
'index' => self::GROUP_ADMIN, 'index' => self::GROUP_ADMIN,
'delete' => self::GROUP_ADMIN, 'delete' => self::GROUP_ADMIN,
'save' => self::GROUP_ADMIN, 'save' => self::GROUP_ADMIN,
// Sauvegarde le module dans un fichier ZIP ou dans le gestionnaire
'dataExport' => self::GROUP_ADMIN,
// Fonction muette d'exportation
'dataImport' => self::GROUP_ADMIN,
// les données d'un module
'dataDelete' => self::GROUP_ADMIN,
'store' => self::GROUP_ADMIN, 'store' => self::GROUP_ADMIN,
'item' => self::GROUP_ADMIN, //'item' => self::GROUP_ADMIN,
// détail d'un objet // détail d'un objet
'upload' => self::GROUP_ADMIN, 'upload' => self::GROUP_ADMIN,
// Téléverser catalogue // Téléverser catalogue
@ -62,28 +56,29 @@ class plugin extends common
public function delete() public function delete()
{ {
// Jeton incorrect // Action interdite
if ($this->getUrl(3) !== $_SESSION['csrf']) { if ($this->getUser('permission', __CLASS__, __FUNCTION__) !== true) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'plugin', 'access' => false
'state' => false,
'notification' => helper::translate('Action interdite')
]); ]);
} else { } else {
// Suppression des dossiers // Suppression des dossiers
$infoModules = helper::getModules(); $infoModules = helper::getModules();
$module = $this->getUrl(2); $module = $this->getUrl(2);
//Liste des dossiers associés au module non effacés //Liste des dossiers associés au module non effacés
if ($this->removeDir('./module/' . $module) === true) { if (
is_dir('./module/' . $module) &&
$this->deleteDir('./module/' . $module) === true
) {
$success = true; $success = true;
$notification = 'Module ' . $module . ' désinstallé'; $notification = 'Module ' . $module . ' désinstallé';
if (($infoModules[$this->getUrl(2)]['dataDirectory'])) { if (($infoModules[$this->getUrl(2)]['dataDirectory'])) {
if ( if (
is_dir($infoModules[$this->getUrl(2)]['dataDirectory']) is_dir($infoModules[$this->getUrl(2)]['dataDirectory'])
&& !$this->removeDir($infoModules[$this->getUrl(2)]['dataDirectory'])
) { ) {
$notification = sprintf(helper::translate('Le module %s est désinstallé, il reste peut-être des données dans %s'), $module, $infoModules[$this->getUrl(2)]['dataDirectory']); $s = $this->deleteDir($infoModules[$this->getUrl(2)]['dataDirectory']);
$notification = $s === false ? sprintf(helper::translate('Le module %s est désinstallé, il reste peut-être des données dans %s'), $module, $infoModules[$this->getUrl(2)]['dataDirectory']) : $notification;
} }
} }
} else { } else {
@ -136,7 +131,7 @@ class plugin extends common
$module = json_decode(file_get_contents(self::TEMP_DIR . $tempFolder . 'enum.json'), true); $module = json_decode(file_get_contents(self::TEMP_DIR . $tempFolder . 'enum.json'), true);
} else { } else {
// Message de retour // Message de retour
$this->removeDir(self::TEMP_DIR . $tempFolder); $this->deleteDir(self::TEMP_DIR . $tempFolder);
$zip->close(); $zip->close();
return ([ return ([
'success' => false, 'success' => false,
@ -151,7 +146,7 @@ class plugin extends common
// Vérification de la présence des dossier décrits // Vérification de la présence des dossier décrits
if (!is_dir(self::TEMP_DIR . $tempFolder . $src)) { if (!is_dir(self::TEMP_DIR . $tempFolder . $src)) {
// Message de retour // Message de retour
$this->removeDir(self::TEMP_DIR . $tempFolder); $this->deleteDir(self::TEMP_DIR . $tempFolder);
$zip->close(); $zip->close();
return ([ return ([
'success' => false, 'success' => false,
@ -161,7 +156,7 @@ class plugin extends common
// Interdire l'écriture dans le dossier core // Interdire l'écriture dans le dossier core
if (strstr($dest, 'core') !== false) { if (strstr($dest, 'core') !== false) {
// Message de retour // Message de retour
$this->removeDir(self::TEMP_DIR . $tempFolder); $this->deleteDir(self::TEMP_DIR . $tempFolder);
$zip->close(); $zip->close();
return ([ return ([
'success' => false, 'success' => false,
@ -176,7 +171,7 @@ class plugin extends common
*/ */
if (!file_exists(self::TEMP_DIR . $tempFolder . $module['name'] . '.php')) { if (!file_exists(self::TEMP_DIR . $tempFolder . $module['name'] . '.php')) {
// Message de retour // Message de retour
$this->removeDir(self::TEMP_DIR . $tempFolder); $this->deleteDir(self::TEMP_DIR . $tempFolder);
$zip->close(); $zip->close();
return ([ return ([
'success' => false, 'success' => false,
@ -209,7 +204,7 @@ class plugin extends common
$installOk = true; $installOk = true;
} else { } else {
// Message de retour // Message de retour
$this->removeDir(self::TEMP_DIR . $tempFolder); $this->deleteDir(self::TEMP_DIR . $tempFolder);
$zip->close(); $zip->close();
return ([ return ([
'success' => false, 'success' => false,
@ -229,12 +224,12 @@ class plugin extends common
if (!is_dir(self::TEMP_DIR . $tempFolder . $src)) { if (!is_dir(self::TEMP_DIR . $tempFolder . $src)) {
mkdir(self::TEMP_DIR . $tempFolder . $src); mkdir(self::TEMP_DIR . $tempFolder . $src);
} }
$success = $success && $this->copyDir(self::TEMP_DIR . $tempFolder . $src, $dest); $success = $success || $this->copyDir(self::TEMP_DIR . $tempFolder . $src, $dest);
} }
} }
// Message de retour // Message de retour
$t = isset($versionInstalled) ? helper::translate('actualisé') : helper::translate('installé'); $t = isset($versionInstalled) ? helper::translate('actualisé') : helper::translate('installé');
$this->removeDir(self::TEMP_DIR . $tempFolder); $this->deleteDir(self::TEMP_DIR . $tempFolder);
$zip->close(); $zip->close();
return ([ return ([
'success' => $success, 'success' => $success,
@ -243,13 +238,14 @@ class plugin extends common
: helper::translate('Erreur inconnue, le module n\'est pas installé') : helper::translate('Erreur inconnue, le module n\'est pas installé')
]); ]);
} else { } else {
// Supprimer le dossier temporaire
$this->deleteDir(self::TEMP_DIR . $tempFolder);
$zip->close();
return ([ return ([
'success' => false, 'success' => false,
'notification' => helper::translate('Erreur inconnue, le module n\'est pas installé') 'notification' => helper::translate('Erreur inconnue, le module n\'est pas installé')
]); ]);
// Supprimer le dossier temporaire
$this->removeDir(self::TEMP_DIR . $tempFolder);
$zip->close();
} }
} else { } else {
// Message de retour // Message de retour
@ -266,7 +262,11 @@ class plugin extends common
public function upload() public function upload()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) {
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Installation d'un module // Installation d'un module
$checkValidMaj = $this->getInput('configModulesCheck', helper::FILTER_BOOLEAN); $checkValidMaj = $this->getInput('configModulesCheck', helper::FILTER_BOOLEAN);
$zipFilename = $this->getInput('configModulesInstallation', helper::FILTER_STRING_SHORT); $zipFilename = $this->getInput('configModulesInstallation', helper::FILTER_STRING_SHORT);
@ -291,13 +291,11 @@ class plugin extends common
*/ */
public function uploadItem() public function uploadItem()
{ {
// Jeton incorrect // Action interdite
if ($this->getUrl(3) !== $_SESSION['csrf']) { if ($this->getUser('permission', __CLASS__, __FUNCTION__) !== true) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'store', 'access' => false
'state' => false,
'notification' => helper::translate('Action interdite')
]); ]);
} else { } else {
// Récupérer le module en ligne // Récupérer le module en ligne
@ -316,7 +314,7 @@ class plugin extends common
mkdir(self::FILE_DIR . 'source/modules', 0755); mkdir(self::FILE_DIR . 'source/modules', 0755);
} }
// Sauver les données du fichiers // Sauver les données du fichiers
file_put_contents(self::FILE_DIR . 'source/modules/' . $moduleFile, $moduleData); $this->secure_file_put_contents(self::FILE_DIR . 'source/modules/' . $moduleFile, $moduleData);
// Installation directe // Installation directe
if (file_exists(self::FILE_DIR . 'source/modules/' . $moduleFile)) { if (file_exists(self::FILE_DIR . 'source/modules/' . $moduleFile)) {
@ -332,6 +330,7 @@ class plugin extends common
'state' => $r['success'] 'state' => $r['success']
]); ]);
} }
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Catalogue de modules'), 'title' => helper::translate('Catalogue de modules'),
@ -379,11 +378,11 @@ class plugin extends common
$store[$key]['category'], $store[$key]['category'],
'<a href="' . self::BASEURL_STORE . self::MODULE_STORE . $key . '" target="_blank" >' . $store[$key]['title'] . '</a>', '<a href="' . self::BASEURL_STORE . self::MODULE_STORE . $key . '" target="_blank" >' . $store[$key]['title'] . '</a>',
$store[$key]['version'], $store[$key]['version'],
helper::dateUTF8('%d %B %Y', $store[$key]['versionDate']), helper::dateUTF8('%d %B %Y', $store[$key]['versionDate'], self::$i18nUI),
implode(' - ', $pageInfos), implode(' - ', $pageInfos),
template::button('moduleExport' . $key, [ template::button('moduleExport' . $key, [
'class' => $class, 'class' => $class,
'href' => helper::baseUrl() . $this->getUrl(0) . '/uploadItem/' . $key . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/uploadItem/' . $key,
'value' => $ico, 'value' => $ico,
'help' => $help 'help' => $help
]) ])
@ -405,7 +404,7 @@ class plugin extends common
{ {
$store = json_decode(helper::getUrlContents(self::BASEURL_STORE . self::MODULE_STORE . 'list'), true); $store = json_decode(helper::getUrlContents(self::BASEURL_STORE . self::MODULE_STORE . 'list'), true);
self::$storeItem = $store[$this->getUrl(2)]; self::$storeItem = $store[$this->getUrl(2)];
self::$storeItem['fileDate'] = helper::dateUTF8('%d %B %Y', self::$storeItem['fileDate']); self::$storeItem['fileDate'] = helper::dateUTF8('%d %B %Y', self::$storeItem['fileDate'], self::$i18nUI);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Module ' . self::$storeItem['title']), 'title' => helper::translate('Module ' . self::$storeItem['title']),
@ -413,16 +412,30 @@ class plugin extends common
]); ]);
} }
/**
* Retourne le contenu du store en ligne
* @return mixed
*/
public static function getStore() {
$store = json_decode(helper::getUrlContents(self::BASEURL_STORE . self::MODULE_STORE . 'list'), true);
return $store;
}
/** /**
* Gestion des modules * Gestion des modules
*/ */
public function index() public function index()
{ {
$i18nSites = [];
// Tableau des langues rédigées // Tableau des langues rédigées
foreach (self::$languages as $key => $value) { foreach (self::$languages as $key => $value) {
// tableau des langues installées // tableau des langues installées
if (is_dir(self::DATA_DIR . $key)) { if (
is_dir(self::DATA_DIR . $key)
&& file_exists(self::DATA_DIR . $key . '/page.json')
&& file_exists(self::DATA_DIR . $key . '/module.json')
) {
$i18nSites[$key] = $value; $i18nSites[$key] = $value;
} }
} }
@ -432,10 +445,11 @@ class plugin extends common
// Parcourir les langues du site traduit et recherche les modules affectés à des pages // Parcourir les langues du site traduit et recherche les modules affectés à des pages
$pagesInfos = []; $pagesInfos = [];
foreach ($i18nSites as $keyi18n => $valuei18n) { foreach ($i18nSites as $keyi18n => $valuei18n) {
// Clés moduleIds dans les pages de la langue // Clés moduleIds dans les pages de la langue
$pages = json_decode(file_get_contents(self::DATA_DIR . $keyi18n . '/' . 'page.json'), true); $pages = json_decode(file_get_contents(self::DATA_DIR . $keyi18n . '/page.json'), true);
// Extraire les clés des modules // Extraire les clés des modules
$pagesModules[$keyi18n] = array_filter(helper::arrayColumn($pages['page'], 'moduleId', 'SORT_DESC'), 'strlen'); $pagesModules[$keyi18n] = array_filter(helper::arrayColumn($pages['page'], 'moduleId', 'SORT_DESC'), 'strlen');
@ -443,7 +457,6 @@ class plugin extends common
// Générer la liste des pages avec module de la langue par défaut // Générer la liste des pages avec module de la langue par défaut
foreach ($pagesModules[$keyi18n] as $key => $value) { foreach ($pagesModules[$keyi18n] as $key => $value) {
if (!empty($value)) { if (!empty($value)) {
$pagesInfos[$keyi18n][$key]['pageId'] = $key; $pagesInfos[$keyi18n][$key]['pageId'] = $key;
$pagesInfos[$keyi18n][$key]['title'] = $pages['page'][$key]['title']; $pagesInfos[$keyi18n][$key]['title'] = $pages['page'][$key]['title'];
$pagesInfos[$keyi18n][$key]['moduleId'] = $value; $pagesInfos[$keyi18n][$key]['moduleId'] = $value;
@ -476,7 +489,7 @@ class plugin extends common
$infoModules[$key]['delete'] === true $infoModules[$key]['delete'] === true
? template::button('moduleDelete' . $key, [ ? template::button('moduleDelete' . $key, [
'class' => 'moduleDelete buttonRed', 'class' => 'moduleDelete buttonRed',
'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $key . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/' . $key,
'value' => template::ico('trash'), 'value' => template::ico('trash'),
'help' => 'Supprimer le module' 'help' => 'Supprimer le module'
]) ])
@ -497,12 +510,12 @@ class plugin extends common
$infoModules[$key]['version'], $infoModules[$key]['version'],
'', '',
template::button('moduleSave' . $key, [ template::button('moduleSave' . $key, [
'href' => helper::baseUrl() . $this->getUrl(0) . '/save/filemanager/' . $key . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/save/filemanager/' . $key,
'value' => template::ico('download-cloud'), 'value' => template::ico('download-cloud'),
'help' => 'Sauvegarder le module dans le gestionnaire de fichiers' 'help' => 'Sauvegarder le module dans le gestionnaire de fichiers'
]), ]),
template::button('moduleDownload' . $key, [ template::button('moduleDownload' . $key, [
'href' => helper::baseUrl() . $this->getUrl(0) . '/save/download/' . $key . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/save/download/' . $key,
'value' => template::ico('download'), 'value' => template::ico('download'),
'help' => 'Sauvegarder et télécharger le module' 'help' => 'Sauvegarder et télécharger le module'
]) ])
@ -528,19 +541,19 @@ class plugin extends common
$infoModules[$pagesInfos[$keyi18n][$keyPage]['moduleId']]['version'], $infoModules[$pagesInfos[$keyi18n][$keyPage]['moduleId']]['version'],
template::flag($keyi18n, '20px') . '&nbsp<a href ="' . helper::baseUrl() . $keyPage . '" target="_blank">' . $pagesInfos[$keyi18n][$keyPage]['title'] . ' (' . $keyPage . ')</a>', template::flag($keyi18n, '20px') . '&nbsp<a href ="' . helper::baseUrl() . $keyPage . '" target="_blank">' . $pagesInfos[$keyi18n][$keyPage]['title'] . ' (' . $keyPage . ')</a>',
template::button('dataExport' . $keyPage, [ template::button('dataExport' . $keyPage, [
'href' => helper::baseUrl() . $this->getUrl(0) . '/dataExport/filemanager/' . self::$i18nContent . '/' . $pagesInfos[$keyi18n][$keyPage]['moduleId'] . '/' . $keyPage . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/dataExport/filemanager/' . self::$siteContent . '/' . $pagesInfos[$keyi18n][$keyPage]['moduleId'] . '/' . $keyPage,
// appel de fonction vaut exécution, utiliser un paramètre // appel de fonction vaut exécution, utiliser un paramètre
'value' => template::ico('download-cloud'), 'value' => template::ico('download-cloud'),
'help' => 'Sauvegarder les données du module dans le gestionnaire de fichiers' 'help' => 'Sauvegarder les données du module dans le gestionnaire de fichiers'
]), ]),
template::button('dataExport' . $keyPage, [ template::button('dataExport' . $keyPage, [
'href' => helper::baseUrl() . $this->getUrl(0) . '/dataExport/download/' . self::$i18nContent . '/' . $pagesInfos[$keyi18n][$keyPage]['moduleId'] . '/' . $keyPage . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/dataExport/download/' . self::$siteContent . '/' . $pagesInfos[$keyi18n][$keyPage]['moduleId'] . '/' . $keyPage,
// appel de fonction vaut exécution, utiliser un paramètre // appel de fonction vaut exécution, utiliser un paramètre
'value' => template::ico('download'), 'value' => template::ico('download'),
'help' => 'Sauvegarder et télécharger les données du module' 'help' => 'Sauvegarder et télécharger les données du module'
]), ]),
template::button('dataDelete' . $keyPage, [ template::button('dataDelete' . $keyPage, [
'href' => helper::baseUrl() . $this->getUrl(0) . '/dataDelete/' . self::$i18nContent . '/' . $pagesInfos[$keyi18n][$keyPage]['moduleId'] . '/' . $keyPage . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/dataDelete/' . self::$siteContent . '/' . $pagesInfos[$keyi18n][$keyPage]['moduleId'] . '/' . $keyPage,
// appel de fonction vaut exécution, utiliser un paramètre // appel de fonction vaut exécution, utiliser un paramètre
'value' => template::ico('trash'), 'value' => template::ico('trash'),
'class' => 'buttonRed dataDelete', 'class' => 'buttonRed dataDelete',
@ -553,6 +566,9 @@ class plugin extends common
} }
} }
// Désactive l'icône rouge
$this->setData(['core', 'updateModuleAvailable', false]);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Gestion des modules'), 'title' => helper::translate('Gestion des modules'),
@ -566,18 +582,15 @@ class plugin extends common
*/ */
public function save() public function save()
{ {
// Jeton incorrect // Action interdite
if ($this->getUrl(4) !== $_SESSION['csrf']) { if ($this->getUser('permission', __CLASS__, __FUNCTION__) !== true) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'plugin', 'access' => false
'state' => false,
'notification' => helper::translate('Action interdite')
]); ]);
} else { } else {
// Créer un dossier temporaire // Créer un dossier temporaire
$tmpFolder = self::TEMP_DIR . uniqid(); $tmpFolder = self::TEMP_DIR . uniqid() . '/';
if (!is_dir($tmpFolder)) { if (!is_dir($tmpFolder)) {
mkdir($tmpFolder, 0755); mkdir($tmpFolder, 0755);
} }
@ -587,273 +600,43 @@ class plugin extends common
// Descripteur de l'archive // Descripteur de l'archive
$infoModule = helper::getModules(); $infoModule = helper::getModules();
//Nom de l'archive
$fileName = $moduleId . $infoModule[$moduleId]['version'] . '.zip';
// Régénération du module //Nom de l'archive
$success = file_put_contents(self::MODULE_DIR . $moduleId . '/enum.json', json_encode($infoModule[$moduleId], JSON_UNESCAPED_UNICODE)); $fileName = $moduleId . str_replace('.', '-', $infoModule[$moduleId]['version']) . '.zip';
// Régénération du descripteur du module
file_put_contents(self::MODULE_DIR . $moduleId . '/enum.json', json_encode($infoModule[$moduleId], JSON_UNESCAPED_UNICODE));
// Construire l'archive // Construire l'archive
$this->makeZip(self::TEMP_DIR . $fileName, self::MODULE_DIR . $moduleId); $this->makeZip($tmpFolder . $fileName, self::MODULE_DIR . $moduleId);
switch ($action) { switch ($action) {
case 'filemanager': case 'filemanager':
if (!file_exists(self::FILE_DIR . 'source/modules')) { if (is_dir(self::FILE_DIR . 'source/modules') === false) {
mkdir(self::FILE_DIR . 'source/modules'); mkdir(self::FILE_DIR . 'source/modules');
} }
$success = $success && copy(self::TEMP_DIR . $fileName, self::FILE_DIR . 'source/modules/' . $moduleId . '.zip'); $success = copy($tmpFolder . $fileName, self::FILE_DIR . 'source/modules/' . $fileName);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'plugin', 'redirect' => helper::baseUrl() . 'plugin',
'notification' => $success ? helper::translate('Archive copiée dans le dossier Modules du gestionnaire de fichier') : helper::translate('Erreur de copie'), 'notification' => $success ? helper::translate('Archive copiée dans le dossier Modules du gestionnaire de fichier') : helper::translate('Erreur de copie'),
'state' => $success 'state' => $success
]); ]);
// Nettoyage
unlink(self::TEMP_DIR . $fileName);
$this->removeDir($tmpFolder);
break; break;
case 'download': case 'download':
default:
// Téléchargement du ZIP // Téléchargement du ZIP
header('Content-Description: File Transfer'); header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream'); header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary'); header('Content-Transfer-Encoding: binary');
header('Content-Disposition: attachment; filename="' . $fileName . '"'); header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Content-Length: ' . filesize(self::TEMP_DIR . $fileName)); header('Content-Length: ' . filesize($tmpFolder . $fileName));
readfile(self::TEMP_DIR . $fileName); readfile($tmpFolder . $fileName);
// Nettoyage du dossier
unlink(self::TEMP_DIR . $fileName);
exit(); exit();
} }
}
}
/*
* Détacher un module d'une page en supprimant les données du module
* 2 : i18n id
* 3 : moduleId
* 4 : pageId
* 5 : CSRF
*/
public function dataDelete()
{
// Jeton incorrect
if ($this->getUrl(5) !== $_SESSION['csrf']) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'plugin',
'state' => false,
'notification' => helper::translate('Action interdite')
]);
} else {
$this->setData(['page', $this->getUrl(4), 'moduleId', '']);
$this->deleteData(['module', $this->getUrl(4)]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'plugin',
'notification' => sprintf(helper::translate('Le module %s de la page %s a été supprimé'), $this->getUrl(3), $this->getUrl(4)),
'state' => true
]);
}
}
/*
* Export des données d'un module
* Structure de l'adresse reçue
* 2 : i18n id
* 3 : moduleId
* 4 : pageId
* 5 : CSRF
*/
public function dataExport()
{
// Jeton incorrect
if ($this->getUrl(6) !== $_SESSION['csrf']) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'plugin',
'state' => false,
'notification' => helper::translate('Action interdite')
]);
} else {
// Créer un dossier temporaire
$tmpFolder = self::TEMP_DIR . uniqid();
if (!is_dir($tmpFolder)) {
mkdir($tmpFolder, 0755);
}
$action = $this->getUrl(2);
$lang = $this->getUrl(3);
$moduleId = $this->getUrl(4);
$pageId = $this->getUrl(5);
// DOnnèes du module de la page sélectionnée
$moduleData = $this->getData(['module', $pageId]);
// Descripteur du module
$infoModules = helper::getModules();
$infoModule = $infoModules[$moduleId];
// Copier les données et le descripteur
$success = file_put_contents($tmpFolder . '/module.json', json_encode($moduleData, JSON_UNESCAPED_UNICODE)) === false ? false : true;
$success = $success && is_int(file_put_contents($tmpFolder . '/enum.json', json_encode([$moduleId => $infoModule], JSON_UNESCAPED_UNICODE)));
// Le dossier du module s'il existe
if (is_dir(self::DATA_DIR . $moduleId . '/' . $pageId)) {
// Copier le dossier des données
$success = $success && $this->copyDir(self::DATA_DIR . '/' . $moduleId . '/' . $pageId, $tmpFolder . '/dataDirectory');
}
// Création du zip
$fileName = $lang . '-' . $moduleId . '-' . $pageId . '.zip';
$this->makeZip(self::TEMP_DIR . $fileName, $tmpFolder);
// Gestion de l'action
if ($success) {
switch ($action) {
case 'filemanager':
if (!file_exists(self::FILE_DIR . 'source/modules')) {
mkdir(self::FILE_DIR . 'source/modules');
}
if (file_exists(self::TEMP_DIR . $fileName)) {
$success = $success && copy(self::TEMP_DIR . $fileName, self::FILE_DIR . 'source/modules/data' . $moduleId . '.zip');
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'plugin',
'notification' => $success ? helper::translate('Données copiées dans le dossier Module du gestionnaire de fichier') : helper::translate('Erreur de copie'),
'state' => $success
]);
// Nettoyage // Nettoyage
unlink(self::TEMP_DIR . $fileName); unlink(self::TEMP_DIR . $fileName);
$this->removeDir($tmpFolder); $this->deleteDir($tmpFolder);
}
break;
case 'download':
default:
if (file_exists(self::TEMP_DIR . $fileName)) {
// Téléchargement du ZIP
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary');
header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Content-Length: ' . filesize(self::TEMP_DIR . $fileName));
readfile(self::TEMP_DIR . $fileName);
// Nettoyage du dossier
unlink(self::TEMP_DIR . $fileName);
exit();
}
}
} else {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'plugin',
'notification' => helper::translate('Erreur inconnue'),
'state' => false
]);
}
}
}
/*
* Importer des données d'un module externes ou interne à module.json
*/
public function dataImport()
{
// Soumission du formulaire d'importation du module dans une page libre
if ($this->isPost()) {
// Récupérer le fichier et le décompacter
$zipFilename = $this->getInput('pluginImportFile', helper::FILTER_STRING_SHORT, true);
$pageId = $this->getInput('pluginImportPage', null, true);
$tmpFolder = uniqid();
// Extraction dans un dossier temporaire
mkdir(self::TEMP_DIR . $tmpFolder, 0755);
$zip = new ZipArchive();
if ($zip->open(self::FILE_DIR . 'source/' . $zipFilename) === TRUE) {
$zip->extractTo(self::TEMP_DIR . $tmpFolder);
}
// Lire le descripteur
$descripteur = json_decode(file_get_contents(self::TEMP_DIR . $tmpFolder . '/enum.json'), true);
$moduleId = array_key_first($descripteur);
// Lecture des données du module
$moduleData = json_decode(file_get_contents(self::TEMP_DIR . $tmpFolder . '/module.json'), true);
// Chargement des données du module importé
$this->setData(['module', $pageId, $moduleData]);
// Intégration des données du module importé dans la page
$this->setData(['page', $pageId, 'moduleId', $moduleId]);
// Copie des fichiers d'accompagnement
// Le dossier du module s'il existe
if (is_dir($tmpFolder . '/dataDirectory')) {
// Copier le dossier des données
$this->copyDir($tmpFolder . '/dataDirectory', self::DATA_DIR . '/' . $moduleId . '/' . $pageId);
}
// Supprimer le dossier temporaire
$this->removeDir(self::TEMP_DIR . $tmpFolder);
$zip->close();
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'plugin',
'state' => true,
'notification' => helper::translate('Données importées')
]);
}
// Bouton d'importation des données d'un module spécifique
if (count(explode('/', $this->getUrl())) === 6) {
// Jeton incorrect
if ($this->getUrl(3) !== $_SESSION['csrf']) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'plugin',
'state' => false,
'notification' => helper::translate('Action interdite')
]);
}
// Traitement
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'plugin',
'state' => true,
'notification' => helper::translate('Données importées')
]);
}
/**
* Liste des pages sans module
* et ne sont pas des barres latérales
*/
self::$pagesList = $this->getHierarchy(null, null, null);
foreach (self::$pagesList as $page => $value) {
if (
$this->getData(['page', $page, 'block']) === 'bar' ||
//$this->getData(['page',$page,'disable']) === true ||
$this->getData(['page', $page, 'moduleId']) !== ''
) {
unset(self::$pagesList[$page]);
} else {
self::$pagesList[$page] = $page;
} }
} }
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Importer des données de module'),
'view' => 'dataImport'
]);
}
} }

View File

@ -1,37 +0,0 @@
<?php echo template::formOpen('pluginImportForm'); ?>
<div class="row">
<div class="col1">
<?php echo template::button('pluginImportBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'plugin',
'value' => template::ico('left')
]); ?>
</div>
<div class="col2 offset9">
<?php echo template::submit('pluginImportSubmit', [
'value' => 'Appliquer'
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4><?php echo helper::translate('Installer les données d\'un module'); ?>
</h4>
<div class="row">
<div class="col6">
<?php echo template::file('pluginImportFile', [
'language' => $this->getData(['user', $this->getUser('id'), 'language']),
'label' => 'Archive ZIP',
'type' => 2
]); ?>
</div>
<div class="col6">
<?php echo template::select('pluginImportPage', $module::$pagesList, [
'label' => 'Importer dans' . template::flag('selected', '20px')
]); ?>
</div>
</div>
</div>
</div>
</div>

View File

@ -7,7 +7,7 @@
* @author Rémi Jean <remi.jean@outlook.com> * @author Rémi Jean <remi.jean@outlook.com>
* @copyright Copyright (C) 2008-2018, Rémi Jean * @copyright Copyright (C) 2008-2018, Rémi Jean
* @author Frédéric Tempez <frederic.tempez@outlook.com> * @author Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -17,31 +17,3 @@
* admin.css * admin.css
*/ */
/* Style the tab */
.tab {
margin-top: 1.8em;
overflow: hidden;
text-align: center;
}
.tab ~ .tabContent {
margin-top: -10px;
}
.buttonTab {
display: inline-block;
transition: 0.3s;
border-radius: 10px 10px 0px 0px;
width: 200px;
margin: 0 1px;
}
.buttonTab:hover {
filter: saturate(200%);
}
.activeButton {
background-color: #00BFFF;
}

View File

@ -1,13 +0,0 @@
/**
* 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
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
function setCookie(name,value,days){var expires="";if(days){var date=new Date;date.setTime(date.getTime()+24*days*60*60*1e3),expires="; expires="+date.toUTCString()}document.cookie=name+"="+(value||"")+expires+"; path=/; samesite=lax"}function getCookie(name){for(var nameEQ=name+"=",ca=document.cookie.split(";"),i=0;i<ca.length;i++){for(var c=ca[i];" "==c.charAt(0);)c=c.substring(1,c.length);if(0==c.indexOf(nameEQ))return c.substring(nameEQ.length,c.length)}return null}function capitalizeFirstLetter(string){return string.charAt(0).toUpperCase()+string.slice(1)}$(document).ready((function(){var pluginLayout=getCookie("pluginLayout");null==pluginLayout&&(pluginLayout="module",setCookie("pluginLayout","module")),console.log(pluginLayout),$("#moduleContainer").hide(),$("#dataContainer").hide(),$("#"+pluginLayout+"Container").show(),$("#plugin"+capitalizeFirstLetter(pluginLayout)+"Button").addClass("activeButton")})),$(".moduleDelete").on("click",(function(){var _this=$(this),message_delete="<?php echo helper::translate('Confirmer la désinstallation du module'); ?>";return core.confirm(message_delete,(function(){$(location).attr("href",_this.attr("href"))}))})),$(".dataDelete").on("click",(function(){var _this=$(this),message_unlink="<?php echo helper::translate('Confirmer la dissociation du module de cette page'); ?>";return core.confirm(message_unlink,(function(){$(location).attr("href",_this.attr("href"))}))})),$("#pluginModuleButton").on("click",(function(){$("#dataContainer").hide(),$("#moduleContainer").show(),$("#pluginModuleButton").addClass("activeButton"),$("#pluginDataButton").removeClass("activeButton"),setCookie("pluginLayout","module")})),$("#pluginDataButton").on("click",(function(){$("#moduleContainer").hide(),$("#dataContainer").show(),$("#pluginModuleButton").removeClass("activeButton"),$("#pluginDataButton").addClass("activeButton"),setCookie("pluginLayout","data")}));

View File

@ -3,7 +3,7 @@
<?php echo template::button('configModulesBack', [ <?php echo template::button('configModulesBack', [
'class' => 'buttonGrey', 'class' => 'buttonGrey',
'href' => helper::baseUrl(), 'href' => helper::baseUrl(),
'value' => template::ico('left') 'value' => template::ico('home')
]); ?> ]); ?>
</div> </div>
<div class="col1"> <div class="col1">
@ -13,7 +13,7 @@
'value' => template::ico('help'), 'value' => template::ico('help'),
'class' => 'buttonHelp', 'class' => 'buttonHelp',
'help' => 'Consulter l\'aide en ligne' 'help' => 'Consulter l\'aide en ligne'
]);*/ ?> ]);*/?>
</div> </div>
<div class="col1 offset8"> <div class="col1 offset8">
<?php echo template::button('pluginModulesStore', [ <?php echo template::button('pluginModulesStore', [
@ -30,70 +30,31 @@
]); ?> ]); ?>
</div> </div>
</div> </div>
<div class="tab"> <?php if ($module::$modulesInstalled): ?>
<?php echo template::button('pluginModuleButton', [
'value' => 'Modules installés',
'class' => ' buttonTab'
]); ?>
<?php echo template::button('pluginDataButton', [
'value' => 'Données des modules',
'class' => 'buttonTab'
]); ?>
</div>
<div class="tabContent" id="moduleContainer">
<?php if ($module::$modulesInstalled) : ?>
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Sauvegarde'); ?> <h4>
<?php echo helper::translate('Sauvegarde'); ?>
</h4> </h4>
<?php echo template::table([2, 2, 1, 5, 1, 1], $module::$modulesInstalled, ['Module', 'Identifiant', 'Version', '', '', '']); ?> <?php echo template::table([2, 2, 1, 5, 1, 1], $module::$modulesInstalled, ['Module', 'Identifiant', 'Version', '', '', '']); ?>
</div> </div>
</div> </div>
</div> </div>
<?php else : ?> <?php else: ?>
<?php echo template::speech('Aucun module installé.'); ?> <?php echo template::speech('Aucun module installé.'); ?>
<?php endif; ?> <?php endif; ?>
<?php if ($module::$modulesOrphan) : ?> <?php if ($module::$modulesOrphan): ?>
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('Modules orphelins'); ?> <h4>
<?php echo helper::translate('Modules orphelins'); ?>
</h4> </h4>
<?php echo template::table([2, 2, 1, 6, 1], $module::$modulesOrphan, ['Module', 'Identifiant', 'Version', '', '']); ?> <?php echo template::table([2, 2, 1, 6, 1], $module::$modulesOrphan, ['Module', 'Identifiant', 'Version', '', '']); ?>
</div> </div>
</div> </div>
</div> </div>
<?php else : ?> <?php else: ?>
<?php echo template::speech('Aucun module orphelin.'); ?> <?php echo template::speech('Aucun module orphelin.'); ?>
<?php endif; ?> <?php endif; ?>
</div>
<div class="tabContent displayNone" id="dataContainer">
<?php if ($module::$modulesData) : ?>
<div class="row">
<div class="col12">
<div class="block">
<h4>
<?php echo helper::translate('Modules configurés'); ?>
</h4>
<div class="row">
<div class="col1 offset11">
<?php echo template::button('configModuledataImport', [
'href' => helper::baseUrl() . 'plugin/dataImport',
'value' => template::ico('upload'),
"help" => 'Importer des données de module dans une page libre'
]); ?>
</div>
</div>
<div class="row">
<div class="col12">
<?php echo template::table([4, 1, 4, 1, 1, 1], $module::$modulesData, ['Module', 'Version', 'Page associée', '', '', '']); ?>
</div>
</div>
</div>
</div>
</div>
<?php else : ?>
<?php echo template::speech('Aucune donnée de module.'); ?>
<?php endif; ?>
</div>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,7 +11,7 @@
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
* @copyright : Frédéric Tempez <frederic.tempez@outlook.com> * @copyright : Frédéric Tempez <frederic.tempez@outlook.com>
* @copyright Copyright (C) 2018-2023, Frédéric Tempez * @copyright Copyright (C) 2018-2025, Frédéric Tempez
*/ */
class theme extends common class theme extends common
@ -31,7 +31,7 @@ class theme extends common
'export' => self::GROUP_ADMIN, 'export' => self::GROUP_ADMIN,
'import' => self::GROUP_ADMIN, 'import' => self::GROUP_ADMIN,
'save' => self::GROUP_ADMIN, 'save' => self::GROUP_ADMIN,
'fonts' => self::GROUP_ADMIN, 'font' => self::GROUP_ADMIN,
'fontAdd' => self::GROUP_ADMIN, 'fontAdd' => self::GROUP_ADMIN,
'fontEdit' => self::GROUP_ADMIN, 'fontEdit' => self::GROUP_ADMIN,
'fontDelete' => self::GROUP_ADMIN 'fontDelete' => self::GROUP_ADMIN
@ -47,7 +47,7 @@ class theme extends common
]; ];
public static $containerWides = [ public static $containerWides = [
'container' => 'Limitée au site', 'container' => 'Limitée au site',
'none' => 'Etendue sur la page' 'none' => 'Étendu sur la page'
]; ];
public static $footerblocks = [ public static $footerblocks = [
1 => [ 1 => [
@ -78,11 +78,11 @@ class theme extends common
'bold' => 'Gras' 'bold' => 'Gras'
]; ];
public static $footerHeights = [ public static $footerHeights = [
'0px' => 'Nulles (0px)', '0px' => '0px',
'5px' => 'Très petites (5px)', '5px' => '5px',
'10px' => 'Petites (10px)', '10px' => '10px',
'15px' => 'Moyennes (15px)', '15px' => '15px',
'20px' => 'Grandes (20px)' '20px' => '20px'
]; ];
public static $footerPositions = [ public static $footerPositions = [
'hide' => 'Caché', 'hide' => 'Caché',
@ -90,30 +90,31 @@ class theme extends common
'body' => 'En dessous du site' 'body' => 'En dessous du site'
]; ];
public static $footerFontSizes = [ public static $footerFontSizes = [
'.8em' => 'Très petite (80%)', '.8em' => '80%',
'.9em' => 'Petite (90%)', '.9em' => '90%',
'1em' => 'Standard (100%)', '1em' => 'Standard (100%)',
'1.1em' => 'Moyenne (110%)', '1.1em' => '110%',
'1.2em' => 'Grande (120%)', '1.2em' => '120%',
'1.3em' => 'Très grande (130%)' '1.3em' => '130%'
]; ];
public static $headerFontSizes = [ public static $headerFontSizes = [
'1.6em' => 'Très petite (160%)', '1.6em' => '160%',
'1.8em' => 'Petite (180%)', '1.8em' => '180%',
'2em' => 'Moyenne (200%)', '2em' => '200%',
'2.2em' => 'Grande (220%)', '2.2em' => '220%',
'2.4vmax' => 'Très grande (240%)' '2.4vmax' => '240%'
]; ];
public static $headerHeights = [ public static $headerHeights = [
'unset' => 'Libre', // texte dynamique cf header.js.php 'unset' => 'Libre',
'100px' => 'Très petite (100px) ', // texte dynamique cf header.js.php
'150px' => 'Petite (150px)', '100px' => '100px',
'200px' => 'Moyenne (200px)', '150px' => '150px',
'300px' => 'Grande (300px)', '200px' => '200px',
'400px' => 'Très grande (400px)', '300px' => '300px',
'400px' => '400px',
]; ];
public static $headerPositions = [ public static $headerPositions = [
'body' => 'Au dessus du site', 'body' => 'Au-dessus du site',
'site' => 'Dans le site', 'site' => 'Dans le site',
'hide' => 'Cachée' 'hide' => 'Cachée'
]; ];
@ -133,12 +134,12 @@ class theme extends common
'bottom right' => 'En bas à droite' 'bottom right' => 'En bas à droite'
]; ];
public static $menuFontSizes = [ public static $menuFontSizes = [
'.8em' => 'Très petite (80%)', '.8em' => '80%',
'.9em' => 'Petite (90%)', '.9em' => '90%',
'1em' => 'Standard (100%)', '1em' => 'Standard (100%)',
'1.1em' => 'Moyenne (110%)', '1.1em' => '110%',
'1.2em' => 'Grande (120%)', '1.2em' => '120%',
'1.3em' => 'Très grande (130%)' '1.3em' => '130%'
]; ];
public static $menuHeights = [ public static $menuHeights = [
'5px 10px' => 'Très petite', '5px 10px' => 'Très petite',
@ -210,10 +211,10 @@ class theme extends common
'capitalize' => 'Majuscule à chaque mot' 'capitalize' => 'Majuscule à chaque mot'
]; ];
public static $siteWidths = [ public static $siteWidths = [
'750px' => 'Petite (750 pixels)', '750px' => '750 pixels',
'960px' => 'Moyenne (960 pixels)', '960px' => '960 pixels',
'1170px' => 'Grande (1170 pixels)', '1170px' => '1170 pixels',
'100%' => 'Fluide (100%)' '100%' => '100%',
]; ];
public static $headerWide = [ public static $headerWide = [
'auto auto' => 'Automatique', 'auto auto' => 'Automatique',
@ -248,8 +249,13 @@ class theme extends common
public function admin() public function admin()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->setData(['admin', [ $this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
$this->setData([
'admin',
[
'backgroundColor' => $this->getInput('adminBackgroundColor'), 'backgroundColor' => $this->getInput('adminBackgroundColor'),
'colorTitle' => $this->getInput('adminColorTitle'), 'colorTitle' => $this->getInput('adminColorTitle'),
'colorText' => $this->getInput('adminColorText'), 'colorText' => $this->getInput('adminColorText'),
@ -263,7 +269,9 @@ class theme extends common
'fontTitle' => $this->getInput('adminFontTitle'), 'fontTitle' => $this->getInput('adminFontTitle'),
'backgroundBlockColor' => $this->getInput('adminBackGroundBlockColor'), 'backgroundBlockColor' => $this->getInput('adminBackGroundBlockColor'),
'borderBlockColor' => $this->getInput('adminBorderBlockColor'), 'borderBlockColor' => $this->getInput('adminBorderBlockColor'),
]]); 'width' => $this->getInput('adminSiteWidth'),
]
]);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), 'notification' => helper::translate('Modifications enregistrées'),
@ -291,9 +299,12 @@ class theme extends common
public function advanced() public function advanced()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Enregistre le CSS // Enregistre le CSS
file_put_contents(self::DATA_DIR . 'custom.css', $this->getInput('themeAdvancedCss', null)); $this->secure_file_put_contents(self::DATA_DIR . 'custom.css', $this->getInput('themeAdvancedCss', null));
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), 'notification' => helper::translate('Modifications enregistrées'),
@ -317,8 +328,14 @@ class theme extends common
public function body() public function body()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->setData(['theme', 'body', [ $this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
$this->setData([
'theme',
'body',
[
'backgroundColor' => $this->getInput('themeBodyBackgroundColor'), 'backgroundColor' => $this->getInput('themeBodyBackgroundColor'),
'image' => $this->getInput('themeBodyImage'), 'image' => $this->getInput('themeBodyImage'),
'imageAttachment' => $this->getInput('themeBodyImageAttachment'), 'imageAttachment' => $this->getInput('themeBodyImageAttachment'),
@ -327,7 +344,8 @@ class theme extends common
'imageSize' => $this->getInput('themeBodyImageSize'), 'imageSize' => $this->getInput('themeBodyImageSize'),
'toTopbackgroundColor' => $this->getInput('themeBodyToTopBackground'), 'toTopbackgroundColor' => $this->getInput('themeBodyToTopBackground'),
'toTopColor' => $this->getInput('themeBodyToTopColor') 'toTopColor' => $this->getInput('themeBodyToTopColor')
]]); ]
]);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), 'notification' => helper::translate('Modifications enregistrées'),
@ -351,7 +369,10 @@ class theme extends common
public function footer() public function footer()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
if ( if (
$this->getInput('themeFooterCopyrightPosition') === 'hide' && $this->getInput('themeFooterCopyrightPosition') === 'hide' &&
$this->getInput('themeFooterSocialsPosition') === 'hide' && $this->getInput('themeFooterSocialsPosition') === 'hide' &&
@ -364,7 +385,10 @@ class theme extends common
'state' => false 'state' => false
]); ]);
} else { } else {
$this->setData(['theme', 'footer', [ $this->setData([
'theme',
'footer',
[
'backgroundColor' => $this->getInput('themeFooterBackgroundColor'), 'backgroundColor' => $this->getInput('themeFooterBackgroundColor'),
'copyrightAlign' => $this->getInput('themeFooterCopyrightAlign'), 'copyrightAlign' => $this->getInput('themeFooterCopyrightAlign'),
'height' => $this->getInput('themeFooterHeight'), 'height' => $this->getInput('themeFooterHeight'),
@ -391,10 +415,11 @@ class theme extends common
'displaySearch' => $this->getInput('themeFooterDisplaySearch', helper::FILTER_BOOLEAN), 'displaySearch' => $this->getInput('themeFooterDisplaySearch', helper::FILTER_BOOLEAN),
'memberBar' => $this->getInput('themeFooterMemberBar', helper::FILTER_BOOLEAN), 'memberBar' => $this->getInput('themeFooterMemberBar', helper::FILTER_BOOLEAN),
'template' => $this->getInput('themeFooterTemplate') 'template' => $this->getInput('themeFooterTemplate')
]]); ]
]);
// Sauvegarder la configuration localisée // Sauvegarder la configuration localisée
$this->setData(['locale', 'legalPageId', $this->getInput('configLegalPageId')]); $this->setData(['locale', 'legalPageId', $this->getInput('configLegalPageId')], false);
$this->setData(['locale', 'searchPageId', $this->getInput('configSearchPageId')]); $this->setData(['locale', 'searchPageId', $this->getInput('configSearchPageId')]);
// Valeurs en sortie // Valeurs en sortie
@ -437,7 +462,10 @@ class theme extends common
public function header() public function header()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Modification des URL des images dans la bannière perso // Modification des URL des images dans la bannière perso
$featureContent = $this->getInput('themeHeaderText', null); $featureContent = $this->getInput('themeHeaderText', null);
/** /**
@ -453,7 +481,10 @@ class theme extends common
} }
// Sauvegarder // Sauvegarder
$this->setData(['theme', 'header', [ $this->setData([
'theme',
'header',
[
'backgroundColor' => $this->getInput('themeHeaderBackgroundColor'), 'backgroundColor' => $this->getInput('themeHeaderBackgroundColor'),
'font' => $this->getInput('themeHeaderFont'), 'font' => $this->getInput('themeHeaderFont'),
'fontSize' => $this->getInput('themeHeaderFontSize'), 'fontSize' => $this->getInput('themeHeaderFontSize'),
@ -475,21 +506,24 @@ class theme extends common
'feature' => $this->getInput('themeHeaderFeature'), 'feature' => $this->getInput('themeHeaderFeature'),
'featureContent' => $featureContent, 'featureContent' => $featureContent,
'featureFiles' => $files 'featureFiles' => $files
]]); ]
], false);
// Modification de la position du menu selon la position de la bannière // Modification de la position du menu selon la position de la bannière
if ($this->getData(['theme', 'header', 'position']) == 'site') { if ($this->getData(['theme', 'header', 'position']) == 'site') {
$this->setData(['theme', 'menu', 'position', str_replace('body-', 'site-', $this->getData(['theme', 'menu', 'position']))]); $this->setData(['theme', 'menu', 'position', str_replace('body-', 'site-', $this->getData(['theme', 'menu', 'position']))], false);
} }
if ($this->getData(['theme', 'header', 'position']) == 'body') { if ($this->getData(['theme', 'header', 'position']) == 'body') {
$this->setData(['theme', 'menu', 'position', str_replace('site-', 'body-', $this->getData(['theme', 'menu', 'position']))]); $this->setData(['theme', 'menu', 'position', str_replace('site-', 'body-', $this->getData(['theme', 'menu', 'position']))], false);
} }
// Menu accroché à la bannière qui devient cachée // Menu accroché à la bannière qui devient cachée
if ( if (
$this->getData(['theme', 'header', 'position']) == 'hide' && $this->getData(['theme', 'header', 'position']) == 'hide' &&
in_array($this->getData(['theme', 'menu', 'position']), ['body-first', 'site-first', 'body-first', 'site-second']) in_array($this->getData(['theme', 'menu', 'position']), ['body-first', 'site-first', 'body-first', 'site-second'])
) { ) {
$this->setData(['theme', 'menu', 'position', 'site']); $this->setData(['theme', 'menu', 'position', 'site'], false);
} }
// Force la sauvegarde
$this->saveDB('theme');
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), 'notification' => helper::translate('Modifications enregistrées'),
@ -534,8 +568,14 @@ class theme extends common
public function menu() public function menu()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->setData(['theme', 'menu', [ $this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
$this->setData([
'theme',
'menu',
[
'backgroundColor' => $this->getInput('themeMenuBackgroundColor'), 'backgroundColor' => $this->getInput('themeMenuBackgroundColor'),
'backgroundColorSub' => $this->getInput('themeMenuBackgroundColorSub'), 'backgroundColorSub' => $this->getInput('themeMenuBackgroundColorSub'),
'font' => $this->getInput('themeMenuFont'), 'font' => $this->getInput('themeMenuFont'),
@ -558,7 +598,8 @@ class theme extends common
'memberBar' => $this->getInput('themeMenuMemberBar', helper::FILTER_BOOLEAN), 'memberBar' => $this->getInput('themeMenuMemberBar', helper::FILTER_BOOLEAN),
'burgerLogo' => $this->getInput('themeMenuBurgerLogo'), 'burgerLogo' => $this->getInput('themeMenuBurgerLogo'),
'burgerContent' => $this->getInput('themeMenuBurgerContent') 'burgerContent' => $this->getInput('themeMenuBurgerContent')
]]); ]
]);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), 'notification' => helper::translate('Modifications enregistrées'),
@ -583,56 +624,55 @@ class theme extends common
/** /**
* Options des fontes * Options des fontes
*/ */
public function fonts() public function font()
{ {
// Toutes les fontes installées sont chargées // Toutes les fontes installées sont chargées
$this->setFonts('all'); $this->setFonts('all');
// Polices liées au thème admin
$fonts['Titre (admin)'] = $this->getData(['admin', 'fontTitle']);
$fonts['Texte (admin)'] = $this->getData(['admin', 'fontText']);
// Polices liées au thème // Polices liées au thème
$used = [ $fonts['Bannière'] = $this->getData(['theme', 'header', 'font']);
'Bannière' => $this->getData(['theme', 'header', 'font']), $fonts['Menu'] = $this->getData(['theme', 'menu', 'font']);
'Menu' => $this->getData(['theme', 'menu', 'font']), $fonts['Titre'] = $this->getData(['theme', 'title', 'font']);
'Titre ' => $this->getData(['theme', 'title', 'font']), $fonts['Texte'] = $this->getData(['theme', 'text', 'font']);
'Texte' => $this->getData(['theme', 'text', 'font']), $fonts['Pied de page'] = $this->getData(['theme', 'footer', 'font']);
'Pied de page' => $this->getData(['theme', 'footer', 'font']),
'Titre (admin)' => $this->getData(['admin', 'fontTitle']),
'Admin (texte)' => $this->getData(['admin', 'fontText'])
];
// Récupérer le détail des fontes installées // Récupérer le détail des fontes installées
//$f = $this->getFonts(); //$f = $this->getFonts();
$f['files'] = $this->getData(['fonts', 'files']); $f['files'] = $this->getData(['font', 'files']);
$f['imported'] = $this->getData(['fonts', 'imported']); $f['imported'] = $this->getData(['font', 'imported']);
$f['websafe'] = self::$fontsWebSafe; $f['websafe'] = self::$fontsWebSafe;
// Parcourir les fontes disponibles et construire le tableau pour le formulaire // Parcourir les fontes disponibles et construire le tableau pour le formulaire
foreach ($f as $type => $typeValue) { foreach ($f as $type => $typeValue) {
if (is_array($typeValue)) { if (is_array($typeValue)) {
foreach ($typeValue as $fontId => $fontValue) { foreach ($typeValue as $fontId => $fontValue) {
// Fontes utilisées par les thèmes // Recherche les correspondances
$fontUsed[$fontId] = ''; $result = array_filter($fonts, function ($value) use ($fontId) {
foreach ($used as $key => $value) { return $value == $fontId;
if ($value === $fontId) { });
$fontUsed[$fontId] .= $key . '<br/>'; $keyResults = array_keys($result);
} // Préparation du tableau
}
self::$fontsDetail[] = [ self::$fontsDetail[] = [
$fontId, $fontId,
'<span style="font-family:' . $f[$type][$fontId]['font-family'] . '">' . $f[$type][$fontId]['name'] . '</span>', '<span style="font-family:' . $f[$type][$fontId]['font-family'] . '">' . $f[$type][$fontId]['name'] . '</span>',
$f[$type][$fontId]['font-family'], $f[$type][$fontId]['font-family'],
$fontUsed[$fontId], empty($keyResults) ? '' : '<span class="fontsList">' . implode('<br />', $keyResults) . '</span>',
$type, $type,
$type !== 'websafe' ? template::button('themeFontEdit' . $fontId, [ $type !== 'websafe' ? template::button('themeFontEdit' . $fontId, [
'class' => 'themeFontEdit', 'class' => 'themeFontEdit',
'href' => helper::baseUrl() . $this->getUrl(0) . '/fontEdit/' . $type . '/' . $fontId . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/fontEdit/' . $type . '/' . $fontId,
'value' => template::ico('pencil'), 'value' => template::ico('pencil'),
'disabled' => !empty($fontUsed[$fontId]) //'disabled' => !empty($fontUsed[$fontId])
]) ])
: '', : '',
$type !== 'websafe' ? template::button('themeFontDelete' . $fontId, [ $type !== 'websafe' ? template::button('themeFontDelete' . $fontId, [
'class' => 'themeFontDelete buttonRed', 'class' => 'themeFontDelete buttonRed',
'href' => helper::baseUrl() . $this->getUrl(0) . '/fontDelete/' . $type . '/' . $fontId . '/' . $_SESSION['csrf'], 'href' => helper::baseUrl() . $this->getUrl(0) . '/fontDelete/' . $type . '/' . $fontId,
'value' => template::ico('cancel'), 'value' => template::ico('cancel'),
'disabled' => !empty($fontUsed[$fontId]) 'disabled' => !empty($fontUsed[$fontId])
]) ])
@ -645,7 +685,10 @@ class theme extends common
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Fontes'), 'title' => helper::translate('Fontes'),
'view' => 'fonts' 'view' => 'font',
'vendor' => [
'datatables'
]
]); ]);
} }
@ -655,12 +698,15 @@ class theme extends common
public function fontAdd() public function fontAdd()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Type d'import en ligne ou local // Type d'import en ligne ou local
$type = $this->getInput('fontAddUrl', helper::FILTER_BOOLEAN) ? 'imported' : 'files'; $type = $this->getInput('fontAddUrl', helper::FILTER_BOOLEAN) ? 'imported' : 'files';
$type === 'files' ? 'imported' : 'files'; $type === 'files' ? 'imported' : 'files';
$ressource = $type === 'imported' ? $this->getInput('fontAddUrl', null) : $this->getInput('fontAddFile', null); $resource = $type === 'imported' ? $this->getInput('fontAddUrl', null) : $this->getInput('fontAddFile', null);
if (!empty($ressource)) { if (!empty($resource)) {
$fontId = $this->getInput('fontAddFontId', null, true); $fontId = $this->getInput('fontAddFontId', null, true);
$fontName = $this->getInput('fontAddFontName', null, true); $fontName = $this->getInput('fontAddFontName', null, true);
$fontFamilyName = $this->getInput('fontAddFontFamilyName', null, true); $fontFamilyName = $this->getInput('fontAddFontFamilyName', null, true);
@ -669,34 +715,42 @@ class theme extends common
$fontFamilyName = str_replace('"', '\'', $fontFamilyName); $fontFamilyName = str_replace('"', '\'', $fontFamilyName);
// Supprime la fonte si elle existe dans le type inverse // Supprime la fonte si elle existe dans le type inverse
if (is_array($this->getData(['fonts', $type, $fontId]))) { if (is_array($this->getData(['font', $type, $fontId]))) {
$this->deleteData(['fonts', $type, $fontId]); $this->deleteData(['font', $type, $fontId]);
} }
// Paramètres de la sortie vrai par défaut, c'est une fonte en ligne
$success = true;
// Copier la fonte si le nom du fichier est fourni
if (!is_dir(self::DATA_DIR . 'font/')) {
mkdir(self::DATA_DIR . 'font/');
}
if (
$type === 'files' &&
file_exists(self::FILE_DIR . 'source/' . $resource)
) {
$success = copy(self::FILE_DIR . 'source/' . $resource, self::DATA_DIR . 'font/' . basename($resource));
}
// Stocker la fonte // Stocker la fonte
$this->setData([ $this->setData([
'fonts', 'font',
$type, $type,
$fontId, [ $fontId,
[
'name' => $fontName, 'name' => $fontName,
'font-family' => $fontFamilyName, 'font-family' => $fontFamilyName,
'resource' => $ressource // Stocke l'URL our lien vers la fonte dans data
'resource' => $type === 'imported' ? $resource : self::DATA_DIR . 'font/' . basename($resource),
] ]
]); ]);
// Copier la fonte si le nom du fichier est fourni
if (
$type === 'files' &&
file_exists(self::FILE_DIR . 'source/' . $ressource)
) {
copy(self::FILE_DIR . 'source/' . $ressource, self::DATA_DIR . 'fonts/' . $ressource);
}
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Fonte créée'), 'notification' => $success ? helper::translate('Fonte actualisée') : helper::translate('Fonte non créée, ressource absente !'),
'redirect' => helper::baseUrl() . 'theme/fonts', 'redirect' => helper::baseUrl() . 'theme/font',
'state' => true 'state' => $success
]); ]);
} else { } else {
// Valeurs en sortie // Valeurs en sortie
@ -721,11 +775,14 @@ class theme extends common
public function fontEdit() public function fontEdit()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Type d'import en ligne ou local // Type d'import en ligne ou local
$type = $this->getInput('fontEditUrl', helper::FILTER_BOOLEAN) ? 'imported' : 'files'; $type = $this->getInput('fontEditUrl', helper::FILTER_BOOLEAN) ? 'imported' : 'files';
$ressource = $type === 'imported' ? $this->getInput('fontEditUrl', null) : $this->getInput('fontEditFile', null);
$fontId = $this->getInput('fontEditFontId', null, true); $fontId = $this->getInput('fontEditFontId', null, true);
$resource = $this->getData(['font', $type, $fontId, 'resource']);
$fontName = $this->getInput('fontEditFontName', null, true); $fontName = $this->getInput('fontEditFontName', null, true);
$fontFamilyName = $this->getInput('fontEditFontFamilyName', null, true); $fontFamilyName = $this->getInput('fontEditFontFamilyName', null, true);
@ -733,32 +790,27 @@ class theme extends common
$fontFamilyName = str_replace('"', '\'', $fontFamilyName); $fontFamilyName = str_replace('"', '\'', $fontFamilyName);
// Supprime la fonte si elle existe dans le type inverse // Supprime la fonte si elle existe dans le type inverse
if (is_array($this->getData(['fonts', $type, $fontId]))) { if (is_array($this->getData(['font', $type, $fontId]))) {
$this->deleteData(['fonts', $type, $fontId]); $this->deleteData(['font', $type, $fontId]);
} }
// Stocker les fontes // Stocker les fontes
$this->setData([ $this->setData([
'fonts', 'font',
$type, $type,
$fontId, [ $fontId,
[
'name' => $fontName, 'name' => $fontName,
'font-family' => $fontFamilyName, 'font-family' => $fontFamilyName,
'resource' => $ressource 'resource' => $resource
] ]
]); ]);
// Copier la fonte si le nom du fichier est fourni
if (
$type === 'files' &&
file_exists(self::FILE_DIR . 'source/' . $ressource)
) {
copy(self::FILE_DIR . 'source/' . $ressource, self::DATA_DIR . 'fonts/' . $ressource);
}
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Fonte actualisée'), 'notification' => helper::translate('Fonte actualisée'),
'redirect' => helper::baseUrl() . 'theme/fonts', 'redirect' => helper::baseUrl() . 'theme/font',
'state' => true 'state' => true
]); ]);
} }
@ -774,31 +826,34 @@ class theme extends common
*/ */
public function fontDelete() public function fontDelete()
{ {
// Jeton incorrect // Action interdite
if ($this->getUrl(4) !== $_SESSION['csrf']) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'theme/fonts', 'access' => false
'notification' => helper::translate('Action interdite')
]); ]);
} }
// Suppression // Suppression
else { else {
// Effacer la fonte de la base // Effacer la fonte de la base
$this->deleteData(['fonts', $this->getUrl(2), $this->getUrl(3)]); $this->deleteData(['font', $this->getUrl(2), $this->getUrl(3)]);
// Effacer le fichier existant // Effacer le fichier existant
if ( if (
$this->getUrl(2) === 'file' && $this->getUrl(2) === 'files' &&
file_exists(self::DATA_DIR . $this->getUrl(2)) file_exists($this->getData(['font', 'files', $this->getUrl(3), 'resource']))
) { ) {
unlink(self::DATA_DIR . $this->getUrl(2));
unlink($this->getData(['font', 'files', $this->getUrl(3), 'resource']));
} }
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'theme/fonts', 'redirect' => helper::baseUrl() . 'theme/font',
'notification' => helper::translate('Fonte supprimée'), 'notification' => helper::translate('Fonte supprimée'),
'state' => true 'state' => true
]); ]);
@ -811,16 +866,18 @@ class theme extends common
*/ */
public function reset() public function reset()
{ {
// $url prend l'adresse sans le token // Action interdite
$url = explode('&', $this->getUrl(2));
if ( if (
isset($_GET['csrf']) $this->getUser('permission', __CLASS__, __FUNCTION__) !== true
and $_GET['csrf'] === $_SESSION['csrf']
) { ) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
// Réinitialisation // Réinitialisation
$redirect = ''; $redirect = '';
switch ($url[0]) { switch ($this->getUrl(2)) {
case 'admin': case 'admin':
$this->initData('admin', self::$i18nUI); $this->initData('admin', self::$i18nUI);
$redirect = helper::baseUrl() . 'theme/admin'; $redirect = helper::baseUrl() . 'theme/admin';
@ -843,11 +900,6 @@ class theme extends common
'redirect' => $redirect, 'redirect' => $redirect,
'state' => true 'state' => true
]); ]);
} else {
// Valeurs en sortie
$this->addOutput([
'notification' => helper::translate('Jeton incorrect')
]);
} }
} }
@ -858,33 +910,58 @@ class theme extends common
public function site() public function site()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
$this->setData(['theme', 'title', [ $this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
$this->setData([
'theme',
'title',
[
'font' => $this->getInput('themeTitleFont'), 'font' => $this->getInput('themeTitleFont'),
'textColor' => $this->getInput('themeTitleTextColor'), 'textColor' => $this->getInput('themeTitleTextColor'),
'fontWeight' => $this->getInput('themeTitleFontWeight'), 'fontWeight' => $this->getInput('themeTitleFontWeight'),
'textTransform' => $this->getInput('themeTitleTextTransform') 'textTransform' => $this->getInput('themeTitleTextTransform')
]]); ]
$this->setData(['theme', 'text', [ ], false);
$this->setData([
'theme',
'text',
[
'font' => $this->getInput('themeTextFont'), 'font' => $this->getInput('themeTextFont'),
'fontSize' => $this->getInput('themeTextFontSize'), 'fontSize' => $this->getInput('themeTextFontSize'),
'textColor' => $this->getInput('themeTextTextColor'), 'textColor' => $this->getInput('themeTextTextColor'),
'linkColor' => $this->getInput('themeTextLinkColor') 'linkColor' => $this->getInput('themeTextLinkColor')
]]); ]
$this->setData(['theme', 'site', [ ], false);
$this->setData([
'theme',
'site',
[
'backgroundColor' => $this->getInput('themeSiteBackgroundColor'), 'backgroundColor' => $this->getInput('themeSiteBackgroundColor'),
'radius' => $this->getInput('themeSiteRadius'), 'radius' => $this->getInput('themeSiteRadius'),
'shadow' => $this->getInput('themeSiteShadow'), 'shadow' => $this->getInput('themeSiteShadow'),
'width' => $this->getInput('themeSiteWidth'), 'width' => $this->getInput('themeSiteWidth'),
'margin' => $this->getInput('themeSiteMargin', helper::FILTER_BOOLEAN) 'margin' => $this->getInput('themeSiteMargin', helper::FILTER_BOOLEAN)
]]); ]
$this->setData(['theme', 'button', [ ], false);
$this->setData([
'theme',
'button',
[
'backgroundColor' => $this->getInput('themeButtonBackgroundColor') 'backgroundColor' => $this->getInput('themeButtonBackgroundColor')
]]); ]
$this->setData(['theme', 'block', [ ], false);
$this->setData([
'theme',
'block',
[
'backgroundColor' => $this->getInput('themeBlockBackgroundColor'), 'backgroundColor' => $this->getInput('themeBlockBackgroundColor'),
'borderColor' => $this->getInput('themeBlockBorderColor') 'borderColor' => $this->getInput('themeBlockBorderColor')
]]); ]
], false);
// Force la sauvegarde
$this->saveDB('theme');
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), 'notification' => helper::translate('Modifications enregistrées'),
@ -912,7 +989,10 @@ class theme extends common
*/ */
public function manage() public function manage()
{ {
if ($this->isPost()) { if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
$zipFilename = $this->getInput('themeManageImport', helper::FILTER_STRING_SHORT, true); $zipFilename = $this->getInput('themeManageImport', helper::FILTER_STRING_SHORT, true);
$data = $this->import(self::FILE_DIR . 'source/' . $zipFilename); $data = $this->import(self::FILE_DIR . 'source/' . $zipFilename);
@ -925,7 +1005,8 @@ class theme extends common
'notification' => $data['notification'], 'notification' => $data['notification'],
'state' => $data['success'], 'state' => $data['success'],
'view' => 'manage' 'view' => 'manage'
]);; ]);
;
} }
} }
// Valeurs en sortie // Valeurs en sortie
@ -943,6 +1024,15 @@ class theme extends common
public function import($zipName = '') public function import($zipName = '')
{ {
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
if ( if (
$zipName !== '' && $zipName !== '' &&
@ -979,7 +1069,7 @@ class theme extends common
// Substitution des fontes Google // Substitution des fontes Google
if ($modele = 'theme') { if ($modele = 'theme') {
$c = $this->subFonts(self::DATA_DIR . 'theme.json'); $c = $this->subFont(self::DATA_DIR . 'theme.json');
// Un remplacement nécessite la régénération de la feuille de style // Un remplacement nécessite la régénération de la feuille de style
if ( if (
$c > 0 $c > 0
@ -989,7 +1079,7 @@ class theme extends common
} }
} }
if ($modele = 'admin') { if ($modele = 'admin') {
$c = $this->subFonts(self::DATA_DIR . 'admin.json'); $c = $this->subFont(self::DATA_DIR . 'admin.json');
// Un remplacement nécessite la régénération de la feuille de style // Un remplacement nécessite la régénération de la feuille de style
if ( if (
$c > 0 $c > 0
@ -1007,7 +1097,7 @@ class theme extends common
$notification = helper::translate('Archive de thème invalide'); $notification = helper::translate('Archive de thème invalide');
} }
// Supprimer le dossier temporaire même si le thème est invalide // Supprimer le dossier temporaire même si le thème est invalide
$this->removeDir(self::TEMP_DIR . $tempFolder); $this->deleteDir(self::TEMP_DIR . $tempFolder);
$zip->close(); $zip->close();
} else { } else {
// erreur à l'ouverture // erreur à l'ouverture
@ -1019,6 +1109,7 @@ class theme extends common
return (['success' => false, 'notification' => helper::translate('Archive non spécifiée ou introuvable')]); return (['success' => false, 'notification' => helper::translate('Archive non spécifiée ou introuvable')]);
} }
}
@ -1027,6 +1118,15 @@ class theme extends common
*/ */
public function export() public function export()
{ {
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
// Make zip // Make zip
$zipFilename = $this->zipTheme($this->getUrl(2)); $zipFilename = $this->zipTheme($this->getUrl(2));
// Téléchargement du ZIP // Téléchargement du ZIP
@ -1040,12 +1140,22 @@ class theme extends common
unlink(self::TEMP_DIR . $zipFilename); unlink(self::TEMP_DIR . $zipFilename);
exit(); exit();
} }
}
/** /**
* Export du thème * Export du thème
*/ */
public function save() public function save()
{ {
// Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
// Make zip // Make zip
$zipFilename = $this->zipTheme($this->getUrl(2)); $zipFilename = $this->zipTheme($this->getUrl(2));
// Téléchargement du ZIP // Téléchargement du ZIP
@ -1057,11 +1167,12 @@ class theme extends common
unlink(self::TEMP_DIR . $zipFilename); unlink(self::TEMP_DIR . $zipFilename);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => '<b>' . $zipFilename . '</b>'. helper::translate('sauvegardé avec succès'), 'notification' => '<b>' . $zipFilename . '</b>' . helper::translate('sauvegardé avec succès'),
'redirect' => helper::baseUrl() . 'theme/manage', 'redirect' => helper::baseUrl() . 'theme/manage',
'state' => true 'state' => true
]); ]);
} }
}
/** /**
* construction du zip Fonction appelée par export() et save() * construction du zip Fonction appelée par export() et save()
@ -1078,14 +1189,14 @@ class theme extends common
$zip->addFile(self::DATA_DIR . 'admin.json', self::DATA_DIR . 'admin.json'); $zip->addFile(self::DATA_DIR . 'admin.json', self::DATA_DIR . 'admin.json');
$zip->addFile(self::DATA_DIR . 'admin.css', self::DATA_DIR . 'admin.css'); $zip->addFile(self::DATA_DIR . 'admin.css', self::DATA_DIR . 'admin.css');
// Ajoute les fontes // Ajoute les fontes
$zip->addEmptyDir(self::DATA_DIR . 'fonts'); $zip->addEmptyDir(self::DATA_DIR . 'font');
$fonts = $this->getData(['fonts', 'files']); $fonts = $this->getData(['font', 'files']);
foreach ($fonts as $fontId => $fontName) { foreach ($fonts as $fontId => $fontName) {
$zip->addFile(self::DATA_DIR . 'fonts/' . $fontName, self::DATA_DIR . 'fonts/' . $fontName); $zip->addFile(self::DATA_DIR . 'font/' . $fontName, self::DATA_DIR . 'font/' . $fontName);
} }
if (file_exists(self::DATA_DIR . 'fonts/fonts.html')) { if (file_exists(self::DATA_DIR . 'font/font.html')) {
$zip->addFile(self::DATA_DIR . 'fonts/fonts.html', self::DATA_DIR . 'fonts/fonts.html'); $zip->addFile(self::DATA_DIR . 'font/font.html', self::DATA_DIR . 'font/font.html');
} }
break; break;
case 'theme': case 'theme':
@ -1116,14 +1227,16 @@ class theme extends common
} }
} }
// Ajoute les fontes // Ajoute les fontes
$zip->addEmptyDir(self::DATA_DIR . 'fonts'); $zip->addEmptyDir(self::DATA_DIR . 'font');
$fonts = $this->getData(['fonts', 'files']); $fonts = $this->getData(['font', 'files']);
foreach ($fonts as $fontId => $fontName) { foreach ($fonts as $fontId => $fontInfo) {
$zip->addFile(self::DATA_DIR . 'fonts/' . $fontName, self::DATA_DIR . 'fonts/' . $fontName); $zip->addFile($fontInfo['resource'], $fontInfo['resource']);
} }
if (file_exists(self::DATA_DIR . 'fonts/fonts.html')) { if (file_exists(self::DATA_DIR . 'font/font.html')) {
$zip->addFile(self::DATA_DIR . 'font/font.html', self::DATA_DIR . 'font/font.html');
$zip->addFile(self::DATA_DIR . 'fonts/fonts.html', self::DATA_DIR . 'fonts/fonts.html'); }
if (file_exists(self::DATA_DIR . 'font/font.css')) {
$zip->addFile(self::DATA_DIR . 'font/font.css', self::DATA_DIR . 'font/font.css');
} }
break; break;
} }
@ -1138,7 +1251,7 @@ class theme extends common
* @param string $file, nom du fichier json à convertir * @param string $file, nom du fichier json à convertir
* @return int nombre de substitution effectuées * @return int nombre de substitution effectuées
*/ */
private function subFonts($file) private function subFont($file)
{ {
// Tableau de substitution des fontes // Tableau de substitution des fontes
$fonts = [ $fonts = [
@ -1181,7 +1294,7 @@ class theme extends common
} }
// Sauvegarder la chaîne modifiée // Sauvegarder la chaîne modifiée
if ($count > 0) { if ($count > 0) {
file_put_contents($file, $data); $this->secure_file_put_contents($file, $data);
} }
// Retourner le nombre d'occurrences // Retourner le nombre d'occurrences
return ($count); return ($count);
@ -1197,8 +1310,8 @@ class theme extends common
* id - nom * id - nom
* id - font-family - resource * id - font-family - resource
*/ */
$f['files'] = $this->getData(['fonts', 'files']); $f['files'] = $this->getData(['font', 'files']);
$f['imported'] = $this->getData(['fonts', 'imported']); $f['imported'] = $this->getData(['font', 'imported']);
$f['websafe'] = self::$fontsWebSafe; $f['websafe'] = self::$fontsWebSafe;
// Construit un tableau avec leur ID et leur famille // Construit un tableau avec leur ID et leur famille
foreach (['websafe', 'imported', 'files'] as $type) { foreach (['websafe', 'imported', 'files'] as $type) {
@ -1236,12 +1349,12 @@ class theme extends common
$fontsInstalled = array_unique($fontsInstalled); $fontsInstalled = array_unique($fontsInstalled);
/** /**
* Chargement des polices en ligne dans un fichier fonts.html inclus dans main.php * Chargement des polices en ligne dans un fichier font.html inclus dans main.php
*/ */
$gf = false; $gf = false;
$fileContent = '<!-- Fontes personnalisées -->'; $fileContent = '<!-- Fontes personnalisées -->';
if (!empty($this->getData(['fonts', 'imported']))) { if (!empty($this->getData(['font', 'imported']))) {
foreach ($this->getData(['fonts', 'imported']) as $fontId => $fontValue) { foreach ($this->getData(['font', 'imported']) as $fontId => $fontValue) {
if ( if (
($scope === 'user' && in_array($fontId, $fontsInstalled)) ($scope === 'user' && in_array($fontId, $fontsInstalled))
|| $scope === 'all' || $scope === 'all'
@ -1265,30 +1378,30 @@ class theme extends common
* Fontes installées localement * Fontes installées localement
*/ */
$fileContentCss = ''; $fileContentCss = '';
if (!empty($this->getData(['fonts', 'files']))) { if (!empty($this->getData(['font', 'files']))) {
foreach ($this->getData(['fonts', 'files']) as $fontId => $fontValue) { foreach ($this->getData(['font', 'files']) as $fontId => $fontValue) {
if ( if (
($scope === 'user' && in_array($fontId, $fontsInstalled)) ($scope === 'user' && in_array($fontId, $fontsInstalled))
|| $scope === 'all' || $scope === 'all'
) { ) {
if (file_exists(self::DATA_DIR . 'fonts/' . $fontValue['resource'])) { if (file_exists($fontValue['resource'])) {
// Extension // Extension
$path_parts = pathinfo(helper::baseUrl(false) . self::DATA_DIR . 'fonts/' . $fontValue['resource']); $path_parts = pathinfo(helper::baseUrl(false) . self::DATA_DIR . 'font/' . $fontValue['resource']);
// Chargement de la police // Chargement de la police
$fileContentCss .= '@font-face {'; $fileContentCss .= '@font-face {';
$fileContentCss .= 'font-family:"' . $fontValue['name'] . '";'; $fileContentCss .= 'font-family:"' . $fontValue['name'] . '";';
$fileContentCss .= 'src: url("' . $fontValue['resource'] . '") format("' . $path_parts['extension'] . '");'; $fileContentCss .= 'src: url("' . helper::baseUrl(false) . $fontValue['resource'] . '") format("' . $path_parts['extension'] . '");';
$fileContentCss .= '}'; $fileContentCss .= '}';
// Préchargement // Préchargement
//$fileContent = '<link rel="preload" href="' . self::DATA_DIR . 'fonts/' . $fontValue['resource'] . '" type="font/woff" crossorigin="anonymous" as="font">' . $fileContent; //$fileContent = '<link rel="preload" href="' . self::DATA_DIR . 'font/' . $fontValue['resource'] . '" type="font/woff" crossorigin="anonymous" as="font">' . $fileContent;
} }
} }
} }
} }
// Enregistre la personnalisation // Enregistre la personnalisation
file_put_contents(self::DATA_DIR . 'fonts/fonts.html', $fileContent); $this->secure_file_put_contents(self::DATA_DIR . 'font/font.html', $fileContent);
// Enregistre la personnalisation // Enregistre la personnalisation
file_put_contents(self::DATA_DIR . 'fonts/fonts.css', $fileContentCss); $this->secure_file_put_contents(self::DATA_DIR . 'font/font.css', $fileContentCss);
} }
} }

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