Compare commits

..

1291 Commits

Author SHA1 Message Date
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
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
dfceb941db changes 2024-09-06 19:00:49 +02:00
9db6e5ac13 changes 2024-09-06 18:52:45 +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
6daeb9e474 13400 changes 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
c78b43f7b0 Warning à la création d'une nouvelle page 2024-09-06 18:42:02 +02:00
5986e8a378 Revert plugin 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
e49b5c16c1 Limitation dimension champs CSS et Script 2023-03-14 15:04:43 +01:00
78b9374d2b Merge branch 'master' into 12400 2023-03-14 14:50:23 +01:00
df24c95a5d Merge branch '12302' 2023-03-14 14:46:40 +01:00
9b21690c27 Revert "Revert "Bug variable""
This reverts commit 6bbb602f6f.
2023-03-14 14:29:56 +01:00
18a49b9005 changes 2023-03-14 14:25:25 +01:00
2c8767478c baseUrlQs 2023-03-14 14:22:34 +01:00
2628a6a782 Comment baserUrlQs 2023-03-14 14:17:37 +01:00
6bbb602f6f Revert "Bug variable"
This reverts commit bfde3e6be9.
2023-03-14 13:56:53 +01:00
bfde3e6be9 Bug variable 2023-03-14 13:50:28 +01:00
839d965d82 Revert "12302 avec tarte au citron"
This reverts commit 55815b60d1.
2023-03-14 13:38:03 +01:00
55815b60d1 12302 avec tarte au citron 2023-03-14 13:37:19 +01:00
a9cda0a75b Amélioration reponse installation auto 2023-03-14 13:11:02 +01:00
9f2c9ac149 Obfuscation 12.3.02 2023-03-14 11:33:45 +01:00
c2ea537b2c empty paragraph 2023-03-13 15:19:28 +01:00
8cd9e993d9 comment obfuscation 2023-03-13 15:16:54 +01:00
36d5723e4d Merge branch '12300' 2023-03-12 10:45:16 +01:00
3dbbcee4dc Minification is back 2023-03-12 10:30:23 +01:00
762b89af38 Version 12.3.01 2023-03-12 10:17:31 +01:00
b39c74c3de Livraison des langues 2023-03-12 10:14:16 +01:00
3b073186d4 Update enum.json 2023-03-12 10:08:49 +01:00
048575f4eb fr_FR vide 2023-03-12 09:59:42 +01:00
9e33266c95 Simplification aide bar 2023-03-11 18:55:28 +01:00
26ad49dd85 Merge branch '12300' into 12400 2023-03-11 18:49:40 +01:00
1c954b0e9e Amélioration des dialogues 2023-03-11 18:41:25 +01:00
b038c8adf6 account edit 2023-03-11 17:50:26 +01:00
a3ceda9653 Merge branch '12300' into 12400 2023-03-11 17:14:55 +01:00
98db071fea Fix check installed language version 2023-03-11 17:10:34 +01:00
cb63315eea Code drapeau gr 2023-03-11 17:07:29 +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
003ffebf10 fontAdd simplification 2023-03-10 14:13:21 +01:00
1746ff7919 Merge branch '12300' into 12400 2023-03-10 14:11:36 +01:00
7669918abb bug font edit 2023-03-10 14:10:31 +01:00
508ec87c96 better json save 2023-03-10 13:59:46 +01:00
0a8a8ecd72 save function 2023-03-10 13:48:27 +01:00
5edb042dd3 Merge branch '12300' into 12400 2023-03-10 11:35:16 +01:00
2b329979c2 json_encode 2023-03-10 11:34:24 +01:00
6b12d9746f Merge branch '12300' into 12400 2023-03-10 11:29:55 +01:00
c4e150af97 json_encode 2023-03-10 11:29:43 +01:00
487d21b696 Merge branch '12300' into 12400 2023-03-10 10:20:58 +01:00
566a083dec Langues site 2023-03-10 10:20:21 +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
7c15d8efd0 Vendors languages 2023-03-10 08:51:29 +01:00
e74b515366 Merge branch '12300' into 12400 2023-03-09 08:07:51 +01:00
1569912204 Class structure 2023-03-09 08:07:34 +01:00
a22d013776 Move class files 2023-03-08 16:10:23 +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
8384602674 RFM data-lity 2023-03-08 15:59:02 +01:00
c069f384c1 Update module languages 2023-03-08 15:54:04 +01:00
b22f4cdc3e Traduction Gérer les fichiers 2023-03-08 15:00:41 +01:00
142b93e946 Libellés hauteur et largeur 2023-03-08 09:48:19 +01:00
3b193134d2 Largeur et non Hardeur 2023-03-08 09:36:56 +01:00
52461041e1 alt icones 2023-03-07 16:45:55 +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
edac937b35 Fix positionnement des boutons de retour 2023-03-07 14:55:00 +01:00
d7bf8fb9b0 Fix style not shown 2023-03-07 11:38:48 +01:00
e17559a87c Fix default param 2023-03-07 11:05:41 +01:00
9b73143b2c Merge branch '12300' into 12400 2023-03-07 11:01:29 +01:00
bb28ded0e7 Fix UTF-8 minification 2023-03-07 09:41:03 +01:00
690b862cce Répartition des classes 2023-03-07 09:32:04 +01:00
3ba76bde35 Check htaccess 2023-03-07 07:13:22 +01:00
a5593535a0 Merge branch '12300' into 12400 2023-03-06 17:39:09 +01:00
1a40d5f4c5 HTML output 2023-03-06 15:41:48 +01:00
b2c25db925 Merge branch '12300' into 12400 2023-03-06 15:24:11 +01:00
c7b414770c Bug style css dans news 2023-03-06 15:23:25 +01:00
822a71b264 Merge branch '12300' into 12400 2023-03-05 17:03:07 +01:00
100d3dd3e3 alt nom de l'icone isolée 2023-03-05 16:52:17 +01:00
e601461101 Merge branch '12300' into 12400 2023-03-05 16:28:44 +01:00
ceddacdd31 pre_update delete old languages 2023-03-04 10:07:57 +01:00
de1d4a6eac preupdate cleaning 2023-03-04 09:52:00 +01:00
29d4d2d7ac Merge branch '12300' into 12400 2023-03-03 21:16:21 +01:00
13a99b1193 Traduction admin 2023-03-03 16:38:42 +01:00
c824bf2e5a Nouvelles chaines de traduction 2023-03-03 16:35:49 +01:00
67fc3740f5 Simplification des libellés 2023-03-03 11:14:03 +01:00
e4d3b100a8 Libellés dans le thème 2023-03-03 09:03:27 +01:00
a1e1b9dace Sécurise la réinitialisation des BDD 2023-03-02 21:12:45 +01:00
00a1f57665 linter 2023-03-02 21:07:25 +01:00
63b17453dd Nettoyage du sossier cotnenant trop de langues dans TinyCME, la mise à jour installe les langues nécessaires. 2023-03-02 15:22:55 +01:00
0449dd7936 Merge branch '12300' into 12400 2023-03-02 14:47:48 +01:00
adee18094b cookie UI 2023-03-02 14:47:41 +01:00
137d901078 Merge branch '12300' into 12400 2023-03-02 14:27:40 +01:00
117d67f9c4 Install depreciation 2023-03-02 14:26:45 +01:00
482de27ef8 gr_GR 2023-03-02 14:17:12 +01:00
5c29625d31 typo 2023-03-02 10:15:55 +01:00
3fd4aecd90 12.2.04 2023-03-02 10:07:01 +01:00
cb77280d73 12.2.04 bug avec la langue grecque 2023-03-02 09:47:06 +01:00
185f501e77 12300 delete disabled language from database 2023-03-02 09:27:45 +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
b9ce213df5 minify languages 2023-02-27 15:28:42 +01:00
59e5f6edf3 Modules tr_TR 2023-02-27 15:16:30 +01:00
69fc0b6973 Typos 2023-02-27 15:03:01 +01:00
ec477de8d8 Fix install sitemap 2023-02-27 14:33:03 +01:00
c77d677874 Delete Ukrainien 2023-02-26 10:03:14 +01:00
58398f9918 Changes 2023-02-25 22:49:35 +01:00
b7c6113759 Mise à jour et langue des messages d'erreur phpmailer 2023-02-25 22:45:40 +01:00
fbe047c877 core sendmail fix 2023-02-25 22:17:17 +01:00
7eebe5e6ef smtp password safety 2023-02-25 22:06:12 +01:00
0dd310970f Add from to phpmailer 2023-02-25 22:00:24 +01:00
4fb4d17210 Bug install foreign language 2023-02-25 19:43:44 +01:00
137e839a91 BUG config smtp mailer 2023-02-25 19:11:05 +01:00
df6a0fd25c Copier 2023-02-23 22:54:53 +01:00
71fa697db8 Fix translate error
Remove optional lang
2023-02-23 22:44:24 +01:00
f24f77f32f Bug initialisation 2023-02-23 22:14:26 +01:00
78f0d66299 Install smtp from
Bug install theme cause news database
2023-02-23 22:00:51 +01:00
21c87bb42d tous les commentaires 2023-02-23 20:19:54 +01:00
3be8f32909 from option 2023-02-23 16:02:06 +01:00
73a799b722 Normalisation themes;json 2023-02-22 08:54:33 +01:00
d1e69faf6d Theme moderne 2023-02-21 18:23:50 +01:00
7e7277653a Bug cookie langue 2023-02-21 15:16:41 +01:00
3ec47fb236 Bug fonte admin 2023-02-21 14:58:36 +01:00
ca945ed16c Clean cookie prev install 2023-02-21 14:20:30 +01:00
019c548b57 bug langauge select in theme 2023-02-20 18:42:16 +01:00
f204b3020f Bug langue installation 2023-02-20 15:22:58 +01:00
cc09d23c36 langues 2023-02-20 15:22:21 +01:00
1b909a1783 Traduction messages footer 2023-02-20 11:56:27 +01:00
2dbe718e9e Langues triées 2023-02-20 11:29:21 +01:00
fda3249d50 timestamp 2023-02-20 11:27:08 +01:00
da37da7b7d tarduction des messages internes au core 2023-02-20 11:25:15 +01:00
971ebf1133 Traduction Obligatoire 2023-02-19 18:01:28 +01:00
d13e8888d9 Langue version du 19/2 2023-02-19 18:01:05 +01:00
82d7783316 Default page content 2023-02-19 17:44:52 +01:00
b343de6058 Bug login in french 2023-02-19 17:42:02 +01:00
0c65c0d11e Delete help buttons from theme
positions buttons
2023-02-18 22:47:01 +01:00
2f88ac9a7e Bug lang select with theme open 2023-02-18 22:30:00 +01:00
32f70918b7 Bog edit date 2023-02-18 09:11:23 +01:00
9c2cea92b7 Bugs de slash 2023-02-18 08:57:08 +01:00
573e67e790 Bug gen theme 2023-02-18 08:51:02 +01:00
4d96900c8c update error 2023-02-18 08:44:01 +01:00
9d7e10604b bug pre update fresh install
bug slash
2023-02-18 08:41:01 +01:00
9395321f4a add meta 2023-02-17 17:15:19 +01:00
044cc48bfd Merge branch '12300' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS into 12300 2023-02-17 16:28:23 +01:00
78488cdc95 News date format 2023-02-17 16:28:10 +01:00
b715329633 Blog and news add zero seconds 2023-02-17 16:28:10 +01:00
fb9448cf8e $installedUI empty 2023-02-17 16:28:10 +01:00
fb0ce1d36b Version des modules 2023-02-17 16:28:09 +01:00
9aee55b2c7 changes 2023-02-17 16:28:09 +01:00
8d2389e033 Remplacement de flatPickr 2023-02-17 16:28:09 +01:00
465fde6611 Codemirror greck support 2023-02-17 16:24:11 +01:00
4babff486e News date format 2023-02-17 14:35:42 +01:00
38a9ff25e3 Blog and news add zero seconds 2023-02-17 14:30:36 +01:00
b04d0b6ce3 $installedUI empty 2023-02-17 13:55:29 +01:00
56ea9917ec Version des modules 2023-02-17 11:11:53 +01:00
16e75fee79 changes 2023-02-17 11:01:05 +01:00
f92653b202 Remplacement de flatPickr 2023-02-17 10:59:25 +01:00
29b825bfbb Edition avec accent et suppression 2023-02-16 22:15:35 +01:00
8ba07abe32 blog settings 2023-02-16 21:42:38 +01:00
3370c9c9d6 DateVersion 12300 2023-02-16 21:37:23 +01:00
b68c4c6d0e Merge branch '12204' into 12300 2023-02-16 21:28:18 +01:00
c088bb523b $inlineScript non défini 2023-02-16 21:27:50 +01:00
0a937cdcae TinyMCE sticky toolbar fix icons 2023-02-16 16:03:14 +01:00
2646805a77 codeMirror languages + language select in TinyMCE 2023-02-16 14:50:01 +01:00
2f8c5a099b changes 2023-02-16 14:07:18 +01:00
42ec86a189 Merge branch '12204' into 12300 2023-02-16 14:01:20 +01:00
aa50495555 Js include in page okay 2023-02-16 11:52:40 +01:00
a3fdb3bc1e Edition de page ok 2023-02-15 19:52:33 +01:00
5844a57d8c changes 2023-02-15 19:33:02 +01:00
ab186d190e showInLine style Function 2023-02-15 19:29:12 +01:00
c58a222887 CSS ok barre and page avec plugin 2023-02-15 19:12:13 +01:00
8eff28c8e3 CSS page and bar ok 2023-02-15 19:01:16 +01:00
a734c972cd include CSS WIP 2023-02-15 18:36:30 +01:00
c670443132 showFontes 2023-02-15 18:17:24 +01:00
9544c3305d Fix css if page with module WIP 2023-02-14 16:53:28 +01:00
6c815eeec1 add meta 2023-02-14 11:20:46 +01:00
f6530fd011 Add deutsch 2023-02-14 10:50:58 +01:00
eb82c960aa Delete sync file 2023-02-14 09:44:31 +01:00
be9bb5c671 Module form et francisation de eMail
Module redirection
2023-02-14 09:34:18 +01:00
618ba0da6b Blog et news amélioration des traductions 2023-02-14 08:47:02 +01:00
63c22bacfa Gallerie amélioration des traductions 2023-02-14 08:26:45 +01:00
e1c587ebf5 clean sync files 2023-02-13 21:16:36 +01:00
0dae6dc5c7 changes 2023-02-13 20:37:59 +01:00
abf25824e9 12300 remove GA from tui 2023-02-13 20:30:20 +01:00
ff03aaa957 FlatPick i10n 2023-02-13 15:57:15 +01:00
c182530fb0 check news 2023-02-13 15:35:16 +01:00
188e86a489 Blog translations check 2023-02-13 15:33:47 +01:00
fcdc757441 Traductions gallery 2023-02-13 15:29:39 +01:00
da42e3bf9e Gallery translations 2023-02-13 15:24:28 +01:00
8a70730dda "Options de configurations" 2023-02-13 15:06:43 +01:00
dcc9b4b9d8 Draft 2023-02-13 14:47:26 +01:00
a1c19bbf04 al_GR !! 2023-02-13 14:43:39 +01:00
5bc5e52936 12300 module news traductions 2023-02-13 14:39:09 +01:00
3670b432e3 translations /12300 2023-02-13 14:17:43 +01:00
07695c957f Merge branch '12204' into 12300 2023-02-13 13:23:49 +01:00
36692b8f35 12204 Bug déclaration langue dans la balise html 2023-02-13 13:23:36 +01:00
cf3fd7b832 Rename module gr_GR to el_GR 2023-02-12 18:12:13 +01:00
03bfbdd9a7 elèGR missing 2023-02-12 17:55:58 +01:00
cc01d8728e Renmae gr_GR to el_GR to be tested 2023-02-12 17:52:18 +01:00
f0515d6369 Nettoyage de langues 2023-02-12 17:41:49 +01:00
993c283778 news okay 2023-02-12 17:24:35 +01:00
f159f0b304 News WIP 2023-02-12 11:14:07 +01:00
c3d95644f0 Blog setup frame 2023-02-11 10:07:08 +01:00
98b05f8b8b Blog tables date 2023-02-11 10:02:44 +01:00
0a49bd1738 coquille 2023-02-10 22:47:51 +01:00
862f8f3496 Blog 6.5
Article okay
option select sizes
2023-02-10 22:45:26 +01:00
ed46aeb65a Blog 6.5
Index date and time format okay
Update to 6.5 okay
2023-02-10 22:37:51 +01:00
aa0b152b67 12300 user import template 2023-02-10 22:27:08 +01:00
46482b7d2b Blog date and time format WIP 2023-02-10 17:19:38 +01:00
2b68bb2659 12300
Les id des modules sont affichées dans le sélecteur de module
Avertissement d'effacemet de module
2023-02-10 15:52:49 +01:00
e8cb55ab08 Delete showDate form core 2023-02-10 15:26:06 +01:00
0c0cd2a2a4 12300 2023-02-10 15:05:10 +01:00
1c550d3f31 delete registration 2023-02-10 14:55:27 +01:00
15dea9bd1b delete download 2023-02-10 14:51:33 +01:00
a8d8fb658f supp slider 2023-02-10 14:43:08 +01:00
2f3a39ad2c Merge branch '12204' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS into 12204 2023-02-10 14:15:52 +01:00
cece24b60a 12204 Nettoyage de commentaires 2023-02-10 14:15:28 +01:00
566f123c2d 12204 Nettoyage de commentaires 2023-02-10 14:15:01 +01:00
c8a546f6e9 php 8.2 testing 2023-02-10 11:25:52 +01:00
056ce8421a utf8 encode replacement 2023-02-10 11:25:42 +01:00
c48da3d7f9 Responsive File Manage
imagecreatetruecolor imagefilledrectangle required int and not float
UTF8_encode
2023-02-10 11:25:05 +01:00
bc43689d41 checkup exit message 2023-02-10 10:42:42 +01:00
b9194c223c compatibilité php 8.1 max 2023-02-10 10:41:57 +01:00
eb9a894c0a 12204 mise à jour depuis 11.5.12 sleep(2) 2023-02-10 10:29:00 +01:00
50a664638d 12204 fix pre-update 2023-02-10 10:08:33 +01:00
b74a741bb7 Merge branch '12204-dates' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS into 12204-dates 2023-02-10 09:59:07 +01:00
514d49bb15 12204
Add pre-required checkup php  and modules
Add pre-checkup to manage databases outside framework
clean time date var
dateUTF8 WIP remove utf8_encode
2023-02-10 09:58:55 +01:00
27dd70953c 12204
Add pre-required checkup php  and modules
Add pre-checkup to manage databases outside framework
clean time date var
dateUTF8 WIP remove utf8_encode
2023-02-10 09:58:38 +01:00
1fe0740553 12204 checkup module 2023-02-09 10:36:52 +01:00
e486c9344a bloque PHP 8.2 2023-02-08 19:51:00 +01:00
65f5dd7c60 12204 Norme interface graphique (bouton retour) 2023-02-07 14:21:15 +01:00
1661fae398 12204 supprime la fonction getUILanguages 2023-02-07 14:05:03 +01:00
cd3ccb0fc7 12204 Désactive l'édition d'une langue de l'UI 2023-02-07 13:39:10 +01:00
00e4a7ae24 12204 Désactive l'édition d'une langue de l'UI 2023-02-07 13:38:53 +01:00
821d18518d 12204
Update UI languages when open translates setup
2023-02-07 13:31:58 +01:00
a5b79b1689 12204
Delete useless makeUiLanguages
Update UI languagues from template when install
2023-02-07 13:31:11 +01:00
0fcc2b511e 12204 Languafe database version is int 2023-02-07 13:29:20 +01:00
7be2729eb6 séactive le mode test des mises à jour 2023-02-07 11:26:18 +01:00
c5b15578cc 12204
Ajoute une option de fréquence de la recherche auto
Fait correspondre le numéro de version des langues avec la version des données
Mise à jour des langues prenant con compte la nouvelle option
2023-02-07 11:21:21 +01:00
247087b481 12204 sort const 2023-02-07 08:36:19 +01:00
52ea9f66fa 12204 Autoupdate : Optimisation des variables 2023-02-06 21:45:41 +01:00
ebc7b59b20 12204 Supprime Tahoma en double
Réécrit la fonction de contrôle d'une mise à joru en ligne
2023-02-06 21:45:03 +01:00
623d5e775b 12204 autoupdate paramètres manquants 2023-02-06 21:43:40 +01:00
5dc317b131 1204 Wrong class displayNone 2023-02-06 20:11:31 +01:00
4d4512fcc6 dataVersion OKAY
autoupdate actif in config WIP
2023-02-05 19:10:42 +01:00
5a83835b4d typo 2023-02-05 09:51:58 +01:00
4c36ecc088 form 3.6 2023-02-04 22:29:26 +01:00
7e591e99e7 Versions 2023-02-04 17:48:10 +01:00
42506dabfd 12203 bug avec le format de language.json 2023-02-04 17:39:50 +01:00
b491acb4e7 htaccess error 2023-02-04 16:17:09 +01:00
051c787bfe ; riding 2023-02-04 16:12:38 +01:00
0178c694fe Erreur de languages.json 2023-02-04 16:10:46 +01:00
d8f4ec7a69 Mise à jour de '.htaccess' 2023-02-04 16:02:41 +01:00
9332d40c9d changes.md 2023-02-03 22:37:20 +01:00
badfafd8bb Langues version 4 + supprimer le module download de master 2023-02-03 22:30:25 +01:00
b2daeccc2c Bug plugin variable enum dataDirectory empty 2023-02-03 22:17:10 +01:00
50e94976fa plugin delete test constants 2023-02-03 21:59:36 +01:00
7ca90968a0 download 3.2 fix icon's sizes 2023-02-03 21:57:03 +01:00
86b12eca8f plufin okay 2023-02-03 16:14:06 +01:00
af263364f8 liste des pages okay 2023-02-03 15:49:05 +01:00
ca75d9e475 Bug Plugins + download WIP 2023-02-03 11:14:03 +01:00
615c3cc1aa typo 2023-02-02 21:04:38 +01:00
58ba7af79c 12201 bug langues 2023-02-02 21:00:03 +01:00
3f2733c033 Merge branch '12201' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS into 12201 2023-02-02 20:31:46 +01:00
56efada4a6 12201 plugin JSON_UNESCAPED_UNICODE 2023-02-02 16:12:27 +01:00
f233478ead 12201 Adaptation des modules 2023-02-02 15:30:33 +01:00
f67f2deafb 12201 Modules publiés 2023-02-02 15:28:35 +01:00
245375c28e 12201 Allow to select extend input types, not only text (ex : color; week, etc) 2023-02-02 09:39:05 +01:00
fd0a331c88 enum gallery 2023-02-01 21:32:09 +01:00
ee5477414d gallery 3.8 2023-02-01 21:26:02 +01:00
8d6dc7f2e4 12201 Better save json function, 5 tries if save error. 2023-02-01 21:16:55 +01:00
8dded3d437 Fix english modules translations 2023-02-01 10:14:09 +01:00
8761c3500f 12200 2023-02-01 10:07:56 +01:00
e0d47d68c4 120102 bug zip folder + modules enum 2023-01-31 22:52:07 +01:00
87f65862fb change 2023-01-30 09:27:30 +01:00
c266d916ac Form 3.4 bug div en trop 2023-01-27 08:26:34 +01:00
4cc1c59abe Gr_GR mods 2023-01-26 09:00:59 +01:00
FredTempez
1d173dc25a 12102 Modules translations 2023-01-24 16:41:16 +01:00
Prof Langues
c83336b853 Merge branch '12102' of https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS into 12102 2023-01-24 14:30:52 +01:00
d8636b4839 12102 Responsive menus 2023-01-24 14:30:47 +01:00
944474e151 12.1.02 fix banner 2023-01-24 14:30:47 +01:00
Fred Tempez
8c7a2c5990 Ckeck default i18n languages 2023-01-24 11:54:24 +01:00
Fred Tempez
73e728118a redirection translate okay 2023-01-24 11:53:24 +01:00
Fred Tempez
27f5797086 gallery gr okay 2023-01-24 11:51:47 +01:00
Fred Tempez
e90f2cea84 form translations okay 2023-01-24 09:57:45 +01:00
Fred Tempez
76df6d2dcc blog gr Okay 2023-01-24 08:51:13 +01:00
Fred Tempez
c923567aba Blog es translation 2023-01-24 08:48:26 +01:00
Fred Tempez
99bc5c55e5 gr_GR ready 2023-01-24 08:35:40 +01:00
Fred Tempez
fc21681ad2 nettoyage 2023-01-24 08:19:54 +01:00
5fb6346385 blog ready to translate 2023-01-23 18:07:22 +01:00
Fred Tempez
ed0e882ce3 blog translates in progress 2023-01-23 15:44:11 +01:00
Fred Tempez
ad6fac8450 Traudction des boutons 2023-01-23 14:40:03 +01:00
Fred Tempez
aba48be013 Update languages 2023-01-23 14:36:07 +01:00
Fred Tempez
1c92141f71 Move modules dialogues download 2023-01-23 14:22:29 +01:00
e7432f4b7f 12102 Responsive menus 2023-01-21 10:07:12 +01:00
89c1012564 12.1.02 fix banner 2023-01-20 10:39:42 +01:00
946a18a389 Modules translattions es and gr_GR 2023-01-20 09:59:56 +01:00
1ac9f85d85 es WIP 2023-01-19 15:56:23 +01:00
7ef894513d Blog translations es 2023-01-19 15:26:42 +01:00
f81b99badd search es 2023-01-19 15:01:25 +01:00
56626ab671 gallery redirection search translations 2023-01-19 14:58:07 +01:00
b2d185cf1d Gallery h4 translations 2023-01-19 14:53:09 +01:00
667f5a8294 translations h4 form 2023-01-19 14:05:25 +01:00
affb6d476f Blog h4 translations 2023-01-19 13:53:02 +01:00
ce1a0d4b30 redirection and gallery multiliguisme 2023-01-19 13:32:07 +01:00
c5683c0a81 News dialogues js files 2023-01-19 13:28:50 +01:00
7dacf80a73 form ? missing 2023-01-19 11:49:56 +01:00
2112f1f4cf gallery dialogues js files 2023-01-19 11:49:10 +01:00
eafa935c9e Form dialogues js file 2023-01-19 11:47:11 +01:00
cc57609816 Merge branch 'master' into 12100-modules-translations 2023-01-19 11:42:39 +01:00
d690331c7a Blog 6.4 Dialogues JS files 2023-01-19 11:38:23 +01:00
f592ca0844 Core version number 2023-01-18 17:51:20 +01:00
f7256bf27d 12101 Fix random captcha 2023-01-18 15:01:52 +01:00
737af38b70 Core messages translations 2023-01-17 16:32:16 +01:00
84e01a2a35 Code cleaning 2023-01-17 16:01:28 +01:00
bfa1e60e4e All modules translations dialogs 2023-01-17 14:21:36 +01:00
2a4dd3b70a Translation 2023-01-17 13:11:03 +01:00
ab0f98c977 README md block 2023-01-17 13:10:24 +01:00
81b25ae15e bug fix language activation not allowed 2023-01-17 12:45:48 +01:00
39cf9b1d74 12100 Delete pending modules translations 2023-01-17 11:57:20 +01:00
7eb758bcc5 English README 2023-01-17 11:45:34 +01:00
0de17eecfa update README 2023-01-17 11:41:59 +01:00
3c332b06bc Clean dialogues modules blog & form 2023-01-13 17:16:39 +01:00
50e30a2f10 Merge branch '12100---collecte-dialogues-modules' into 12100 2023-01-13 16:04:17 +01:00
46c2455853 Comment translate function 2023-01-13 15:59:59 +01:00
b2cbbf0c2d dialogues redirection 2023-01-13 15:58:11 +01:00
83ffd46644 search dialogues 2023-01-13 15:56:06 +01:00
9ee0e57b9c forme dialogues 2023-01-13 15:22:47 +01:00
f92cee284b 12100 Fix external scripts integrations 2023-01-11 18:01:35 +01:00
ca5a59c673 12100 Auto delete tags <script> and <style> 2023-01-10 18:23:33 +01:00
e5080015a6 gallery dialogues 2023-01-10 15:45:46 +01:00
0256856501 Blog dialogues 2023-01-10 15:35:22 +01:00
b1a2a0ce90 blog translations WIP 2023-01-10 15:22:29 +01:00
18c6f9d5fb Translate module tool 2023-01-10 15:22:13 +01:00
a22e8745fe 121000 fix bad merge 2023-01-10 15:20:57 +01:00
710f2cc2f0 Merge branch '12100---collecte-dialogues-modules' into 12100 2023-01-10 15:19:10 +01:00
fff26fd561 12100 dialogue translation templates 2023-01-10 15:18:07 +01:00
a97a215e0b 12100 capture function 2023-01-10 09:47:21 +01:00
eb1b735a95 12100 cleaning tinymce plugins useless 2023-01-09 20:01:38 +01:00
26dce57cb6 12100 Licence range years 2023-01-09 10:23:32 +01:00
9b1aa98424 12100 fix align colon lost password in login window 2023-01-08 20:30:59 +01:00
bfd8797aa4 12100 include script, add <script> markup 2023-01-08 20:22:31 +01:00
c67a1c0e8e 12100 Fix body.inc.html called twice 2023-01-08 20:09:42 +01:00
552f2d7295 Revert "12100 Corrige un double appel des script dans body"
This reverts commit 3207b5cd8e.
2023-01-08 20:06:24 +01:00
3207b5cd8e 12100 Corrige un double appel des script dans body 2023-01-08 19:55:22 +01:00
2d5722dbe8 Version 2 des langues 2023-01-02 18:16:17 +01:00
1ed41e8fb0 12100 Espace en trop 2023-01-02 18:05:31 +01:00
714c4a4788 12100 label select a file 2023-01-02 18:03:48 +01:00
d60498e313 12100 Pages dans le menu 2023-01-02 17:52:18 +01:00
bf35165558 " Manquants 2023-01-02 17:42:39 +01:00
6a742aea74 12100 Site description 2023-01-02 17:38:40 +01:00
c1d9d8da0c 12100 Simplification Title 2023-01-02 17:36:03 +01:00
911876e4f9 Termes Accueil 2023-01-02 17:31:03 +01:00
1a3ef73c13 12100 Select contents translation 2023-01-02 17:23:11 +01:00
70f1bdd5a7 12100 Comment htaccess files 2023-01-01 14:56:25 +01:00
f27d643b8e 12100 protect site/i18n 2023-01-01 14:49:04 +01:00
cf1e574173 12100 Restore database language 2023-01-01 11:12:30 +01:00
6e97d5c519 Mise à jour des langues par défaut 2023-01-01 10:58:51 +01:00
2739909b6c Enable language selector into admin bar 2022-12-31 16:17:51 +01:00
b7266092fa Disabled language menu selector 2022-12-31 15:43:37 +01:00
b6ba3bbc26 Responsive menu icons sizes 2022-12-31 15:43:19 +01:00
df041b2214 Clean code 2022-12-31 15:42:58 +01:00
c45ef8ccf1 12100 Traduction des label du template absente 2022-12-31 10:37:11 +01:00
ddfef50a73 12100 Nom de l'étiquette multilingue 2022-12-30 15:51:34 +01:00
45c918e2ee 12100 Sélecteur de langue du site dans la barre d'administration 2022-12-30 15:47:55 +01:00
1c16e14bac 12100 Fix traduction du site position des boutons utilitaires 2022-12-30 09:35:09 +01:00
3ec95e1776 12100 Fix bug lors de l"édition d'une locale d'un site non activé 2022-12-30 09:25:09 +01:00
51b8d909c7 12100 fix bug install variable name 2022-12-30 09:15:59 +01:00
fe11a1cc3b 12100 Crédits dans la configuration et lien vers le site et le forum 2022-12-30 08:48:35 +01:00
c427b3ffe2 Affichage de la licence 2022-12-29 17:16:33 +01:00
fca0ec707d License CC Attribution-NonCommercial-NoDerivatives 4.0 International 2022-12-29 17:02:20 +01:00
d2b9ab906c New languages files by order 2022-12-29 11:04:38 +01:00
291860aa2b fix table col 2022-12-29 11:02:40 +01:00
6e46a49287 12100 Remove comment code 2022-12-29 10:42:32 +01:00
5287696476 12100 fix col 2022-12-29 10:30:24 +01:00
69d7f10940 changes.md 2022-12-29 10:10:22 +01:00
3d589a023d 12100 Remove delete languages UI option 2022-12-29 10:08:53 +01:00
be62496d35 12100 temp languages database name is languages.json 2022-12-29 10:06:19 +01:00
f77b40d4b2 12010 devient 12100 2022-12-28 16:39:04 +01:00
4166d77ef9 12010 procédure d'installation avec la base des langues de l'UI 2022-12-28 16:35:20 +01:00
432defa7ca 12010 Gestion des langues de l'UI : base de données dans data/ - gestion du catalogue et traduction manuelle des dialogues 2022-12-28 16:20:55 +01:00
29d505a262 Langue anglaise Un accent en trop dans APRES 2022-12-28 16:17:53 +01:00
5e706a7be8 Par défaut anglais, es et fr 2022-12-28 14:42:20 +01:00
264bbe8b58 12010 Champ date 2022-12-28 14:41:04 +01:00
ac9ab66986 12010 Catalogue et règlementation 2022-12-28 10:35:26 +01:00
ed80401feb 12010 CHANGEs pour les nouvelles langues 2022-12-27 19:05:42 +01:00
71a03f83f0 12010 Activation du Grec et d'autres langues 2022-12-27 18:38:51 +01:00
bcc11ef379 12010 fix mt_srand error 2022-12-27 18:24:19 +01:00
e45c240f3e 12010 Installation d'une langue depuis le store 2022-12-27 17:59:04 +01:00
338ea4210b 12010 Se déconncter sans ? et Actualiser non traduit 2022-12-27 17:33:36 +01:00
1336c8c5db 12010 Langues de l'UI en cours reste le store à actualiser 2022-12-27 09:49:29 +01:00
d208512b45 12010 ? après mettre à jour 2022-12-27 09:48:53 +01:00
3f8c6edc8c Supp les points d'interrogation après mettre à jour 2022-12-27 09:31:34 +01:00
97767dc2cc 12010 changes.md 2022-12-26 12:07:46 +01:00
51dacd7c27 12010 effacement d'une traduction du site 2022-12-26 12:05:01 +01:00
e9ca38b9ab Multilingue 2022-12-26 11:06:28 +01:00
8becae3c11 12010 2022-12-26 11:03:36 +01:00
6c595bdc7b typo 2022-12-20 16:33:49 +01:00
494 changed files with 22189 additions and 91515 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/*.* 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

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

1324
CHANGES.md

File diff suppressed because it is too large Load Diff

676
LICENSE
View File

@ -1,675 +1 @@
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.
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{one line to give the program's name and a brief idea of what it does.}
Copyright (C) {year} {name of author}
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
{project} Copyright (C) {year} {fullname}
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

110
LISEZMOI.md Normal file
View File

@ -0,0 +1,110 @@
# ZwiiCMS 13.4.00 version de test
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.
ZwiiCMS a été créé par un développeur de talent, [Rémi Jean](https://remijean.fr/). Il est désormais maintenu par Frédéric Tempez.
[Site](http://zwiicms.fr/) - [Forum](http://forum.zwiicms.com/) - [Version initiale](https://github.com/remijean/ZwiiCMS/) - [GitHub](https://github.com/fredtempez/ZwiiCMS)
## Configuration recommandée
* PHP 7.2 ou plus
* Support de .htaccess
## Licence
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.
## Téléchargement de ZwiiCMS
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)
* ou sur [la page de téléchargement du site](https://zwiicms.fr/telechargement)
## Installation
Décompressez l'archive de Zwii et téléversez son contenu à la racine de votre serveur ou dans un sous-répertoire. C'est tout !
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
A l'occasion de l'installation d'une verion majeure, il est recommandé de réaliser une copie de sauvegarde.
### Automatique
* Connectez-vous à votre site.
* Si une mise à jour est disponible, elle vous est proposée dans la barre d'administration.
* Cliquez sur le bouton "Mettre à jour".
### Manuelle
* Sauvegardez l'intégralité de votre site, spécialement le répertoire "site".
* Décompressez la nouvelle version sur votre ordinateur.
* Transférez son contenu sur votre serveur en activant le remplacement des fichiers.
## Arborescence générale
*Légende : [R] Répertoire - [F] Fichier*
```text
[R] core Cœur du système
[R] class Classes
[R] layout Mise en page
[R] module Modules du cœur
[R] vendor Librairies extérieures
[F] core.js.php Cœur javascript
[F] core.php Cœur PHP
[R] module Modules de page
[R] blog Blog
[R] form Gestionnaire de formulaires
[R] gallery Galerie
[R] news Nouvelles
[R] redirection Redirection
[R] site Contenu du site
[R] backup Sauvegardes automatiques
[R] i18N Langues de l'interface de Zwii
[R] data Répertoire des données
[R] fr Dossier localisé
[F] page.json Données des pages
[F] module.json Données des modules de pages
[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
[F] accueil.html Exemple contenu de la page d'accueil
[R] font Dossier contenant les fontes installées
[F] font.html Fichier contenant les appels des fontes à charger sur cdnFonts
[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..)
[R] modules Personnalisation des modules ou données propres
[F] admin.css Thème des pages d'administration
[F] admin.json Données de thème des pages d'administration
[F] blacklist.json Journalisation des tentatives de connexion avec des comptes inconnus
[F] config.json Configuration du site
[F] core.json Configuration du noyau
[F] custom.css Feuille de style de la personnalisation avancée
[F] font.json Descripteur des fontes personnalisées
[F] journal.log Journalisation des activités
[F] language.json Langues de l'interface
[F] profil.json Profils des utilisateurs
[F] theme.css Thème du site
[F] theme.json Données du site
[F] user.json Données des utilisateurs
[F] .backup Marqueur de la sauvegarde des fichiers si présent
[R] file Répertoire d'upload du gestionnaire de fichiers
[R] source Ressources diverses
[R] thumb Miniatures des images
[R] tmp Répertoire temporaire
[F] index.php Fichier d'initialisation de ZwiiCMS
[F] robots.txt Filtrage des répertoires accessibles aux robots des moteurs de recherche
[F] sitemap.xml Plan du site
[F] sitemap.xml.gz Version compressée
Le fichiers .htaccess contribuent à la sécurité en filtrant l'accès aux répertoires sensibles.
```

167
README.md
View File

@ -1,108 +1,109 @@
# ZwiiCMS 12.0.09 # ZwiiCMS 13.4.00 test version
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 is a database-less (flat-file) CMS that allows you to easily create and manage a web site without any programming knowledge.
ZwiiCMS a été créé par un développeur de talent, [Rémi Jean](https://remijean.fr/). Il est désormais maintenu par Frédéric Tempez. ZwiiCMS was created by a talented developer, [Rémi Jean](https://remijean.fr/). It is now maintained by Frédéric Tempez.
[Site](http://zwiicms.fr/) - [Forum](http://forum.zwiicms.com/) - [Version initiale](https://github.com/remijean/ZwiiCMS/) - [GitHub](https://github.com/fredtempez/ZwiiCMS) [Site](http://zwiicms.fr/) - [Forum](http://forum.zwiicms.com/) - [Initial version](https://github.com/remijean/ZwiiCMS/) - [GitHub](https://github.com/fredtempez/ZwiiCMS)
## Configuration recommandée ## Recommended configuration
* PHP 7.2 ou plus * PHP 7.2 or higher
* Support de .htaccess * .htaccess support
## Téléchargement de ZwiiCMS ## License
Pour télécharger la dernière version publiée, il faut vous rendre sur la page de téléchargement du [site](https://zwiicms.fr/telechargement) This work is licensed under the Attribution-Noncommercial-No Derivative Works 4.0 International License.
La version github est une **version de développement** qui peut encore contenir des bugs mais elle vous permet de tester les dernières nouveautés. Cette version n'est pas recommandée en production. 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
To download the latest released version, go to :
* [the Updates page](https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS/releases)
* or at [the site download page](https://zwiicms.fr/download)
## Installation ## Installation
Décompressez l'archive de Zwii et téléversez son contenu à la racine de votre serveur ou dans un sous-répertoire. C'est tout ! Unzip the Zwii archive and upload its contents to the root of your server or to a subdirectory. That's all!
Vous trouverez de plus amples explications, en particulier pour une installation chez Free, dans la rubrique "Téléchargements" du forum. You will find more explanations, in particular for an installation at Free, in the "Downloads" section of the forum.
## Update procedures
## Procédures de mise à jour When installing a major version, it is recommended to make a backup copy.
### Automatique ### Automatic
* Connectez-vous à votre site. * Connect to your site.
* Si une mise à jour est disponible, elle vous est proposée dans la barre d'administration. * If an update is available, it is proposed in the administration bar.
* Cliquez sur le bouton "Mettre à jour". * Click on the "Update" button.
### Manuelle ### Manual
* Sauvegardez l'intégralité de votre site, spécialement le répertoire "site". * Save your entire site, especially the "site" directory.
* Décompressez la nouvelle version sur votre ordinateur. * Unzip the new version on your computer.
* Transférez son contenu sur votre serveur en activant le remplacement des fichiers. * Transfer its content to your server by activating the file replacement.
En cas de difficulté avec la nouvelle version, il suffira de téléverser la sauvegarde pour remettre votre site dans son état initial. ## General tree structure
**Remarques :** *Legend: [D] Directory - [FILE] File
* La mise à jour manuelle désactive la réécriture d'URL. À vous de la réactiver depuis la page de configuration du site. ````
* La mise à niveau de la version 8 vers la version 9 crée deux fichiers de données distincts ("core.json" et "theme.json") à partir du fichier "data.json" de la version 8, puis le renomme "data_imported.json". text
[DIR] core Core of the system
[DIR] class Classes
[DIR] layout Layout
[DIR] module Core modules
[DIR] vendor External libraries
[FILE] core.js.php Javascript core
[FILE] core.php PHP core
Pour revenir à la version 8, renommez ce fichier "data.json". [DIR] module Page modules
[DIR] blog Blog
[DIR] form Form manager
[DIR] gallery Gallery
[DIR] news News
[DIR] redirection Redirection
## Arborescence générale [DIR] site Site content
[DIR] backup Automatic backups
[DIR] i18N Zwii Interface languages
[DIR] data Data directory
[DIR] en Localized folder
[FILE] page.json Page data
[FILE] module.json Page module data
[FILE] local.json Language-specific site data
[FILE] .default Unique file of default site language
[DIR] content Folder of page contents
[FILE] home.html Sample home page content
[DIR] fonts Folder containing the installed fonts
[FILE] fonts.html File containing the fonts calls to load on cdnFonts
[FILE] fonts.css File containing the style sheet linked to the local fonts
[FILE] fonts.woff Local font files (woff, etc..)
[DIR] modules Customization of modules or own data
[FILE] admin.css Theme of administration pages
[FILE] admin.json Theme data for administration pages
[FILE] blacklist.json Logging of login attempts with unknown accounts
[FILE] config.json Site configuration
[FILE] core.json Core configuration
[FILE] custom.css Advanced customization stylesheet
[FILE] font.json Custom font descriptor
[FILE] journal.log Activities logging
[FILE] language.json Interface languages database
[FILE] profil.json Users profiles database
[FILE] theme.css Site theme
[FILE] theme.json Site database
[FILE] user.json User database
[FILE] .backup Marker for file backup if present
[DIR] file File manager upload directory
[DIR] source Various resources
[DIR] thumb Image thumbnails
[DIR] tmp Temporary directory
*Légende : [R] Répertoire - [F] Fichier* [FILE] index.php ZwiiCMS initialization file
[FILE] robots.txt Filtering of directories accessible to search engine robots
[FILE] sitemap.xml Sitemap
[FILE] sitemap.xml.gz Compressed version
```text The .htaccess files contribute to security by filtering access to sensitive directories.
[R] core Cœur du système
[R] class Classes
[R] layout Mise en page
[R] module Modules du cœur
[R] vendor Librairies extérieures
[F] core.js.php Cœur javascript
[F] core.php Cœur PHP
[R] module Modules de page
[R] blog Blog
[R] form Gestionnaire de formulaires
[R] gallery Galerie
[R] news Nouvelles
[R] redirection Redirection
[R] site Contenu du site
[R] backup Sauvegardes automatiques
[R] data Répertoire des données
[R] fr Dossier localisé
[F] page.json Données des pages
[F] module.json Données des modules de pages
[F] local.json Données du site propres à la langue
[R] content Dossier des contenus de page
[F] accueil.html Exemple contenu de la page d'accueil
[R] fonts Dossier contenant les fontes installées
[F] fonts.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] fontes.woff Fichiers locaux des fontes (woff, etc..)
[R] modules Personnalisation des modules ou données propres
[F] admin.css Thème des pages d'administration
[F] admin.json Données de thème des pages d'administration
[F] blacklist.json Journalisation des tentatives de connexion avec des comptes inconnus
[F] config.json Configuration du site
[F] core.json Configuration du noyau
[F] custom.css Feuille de style de la personnalisation avancée
[F] fonts.json Descripteur des fontes personnalisées
[F] journal.log Journalisation des actions
[F] theme.css Thème du site
[F] theme.json Données du site
[F] user.json Données des utilisateurs
[F] .backup Marqueur de la sauvegarde des fichiers si présent
[R] file Répertoire d'upload du gestionnaire de fichiers
[R] source Ressources diverses
[R] thumb Miniatures des images
[R] tmp Répertoire temporaire
[F] index.php Fichier d'initialisation de ZwiiCMS
[F] robots.txt Filtrage des répertoires accessibles aux robots des moteurs de recherche
[F] sitemap.xml Plan du site
[F] sitemap.xml.gz Version compressée
Le fichiers .htaccess contribuent à la sécurité en filtrant l'accès aux répertoires sensibles.
```

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,6 +32,15 @@ class helper
public static function translate($text) public static function translate($text)
{ {
// La traduction existe déjà dans le core
/*
if (array_key_exists($text, core::$dialog) === false && !empty($text)) {
$dialogues = json_decode(file_get_contents('core/module/install/ressource/i18n/fr_FR.json' ), true);
$data = array_merge($dialogues,[$text => '']);
file_put_contents ('core/module/install/ressource/i18n/fr_FR.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX);
}
*/
return (array_key_exists($text, core::$dialog) && !empty(core::$dialog[$text]) ? core::$dialog[$text] : $text); return (array_key_exists($text, core::$dialog) && !empty(core::$dialog[$text]) ? core::$dialog[$text] : $text);
} }
@ -34,42 +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_detect_encoding(\PHP81_BC\strftime($format, $date), 'UTF-8', true) return mb_convert_encoding(\PHP81_BC\strftime($format, $date, $locale), 'UTF-8', mb_list_encodings());
? \PHP81_BC\strftime($format, $date)
: utf8_encode(\PHP81_BC\strftime($format, $date));
} }
/** /**
* 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));
} }
} }
@ -186,12 +200,12 @@ class helper
// Creation du ZIP // Creation du 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', time()) . '.zip';
$zip = new ZipArchive(); $zip = new ZipArchive();
$zip->open($folder . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE); $zip->open($folder . $fileName, ZipArchive::CREATE | ZipArchive::OVERWRITE);
$directory = 'site/'; $directory = 'site/';
//$filter = array('backup','tmp','file'); //$filter = array('backup','tmp','file');
$files = new RecursiveIteratorIterator( $files = new RecursiveIteratorIterator(
new RecursiveCallbackFilterIterator( new RecursiveCallbackFilterIterator(
new RecursiveDirectoryIterator( new RecursiveDirectoryIterator(
$directory, $directory,
@ -220,7 +234,7 @@ class helper
* du nom réel * du nom réel
* du numéro de version * du numéro de version
*/ */
public static function getModules() public static function getModules()
{ {
$modules = array(); $modules = array();
$dirs = array_diff(scandir('module'), array('..', '.')); $dirs = array_diff(scandir('module'), array('..', '.'));
@ -262,7 +276,7 @@ class helper
$dataDirectory = ''; $dataDirectory = '';
} }
// Affection // Affection
$modules[$value] = [ $modules[$value] = [
'name' => $value, 'name' => $value,
'realName' => $realName, 'realName' => $realName,
'version' => $version, 'version' => $version,
@ -330,13 +344,12 @@ class helper
{ {
// N'interroge que le serveur Apache // N'interroge que le serveur Apache
if (strpos($_SERVER["SERVER_SOFTWARE"], 'Apache') > 0) { if (strpos($_SERVER["SERVER_SOFTWARE"], 'Apache') > 0) {
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;
} }
@ -345,9 +358,9 @@ class helper
* 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
*/ */
public static function getOnlineVersion() public static function getOnlineVersion($channel)
{ {
return (helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/version')); return (helper::getUrlContents(common::ZWII_UPDATE_URL . $channel . '/version'));
} }
@ -355,14 +368,14 @@ class helper
* Check si une nouvelle version de Zwii est disponible * Check si une nouvelle version de Zwii est disponible
* @return bool * @return bool
*/ */
public static function checkNewVersion() public static function checkNewVersion($channel)
{ {
$version = helper::getOnlineVersion(); $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;
} }
@ -380,12 +393,12 @@ class helper
'darken' => 'rgba(' . max(0, $rgba[0] - 15) . ',' . max(0, $rgba[1] - 15) . ',' . max(0, $rgba[2] - 15) . ',' . $rgba[3] . ')', 'darken' => 'rgba(' . max(0, $rgba[0] - 15) . ',' . max(0, $rgba[1] - 15) . ',' . max(0, $rgba[2] - 15) . ',' . $rgba[3] . ')',
'veryDarken' => 'rgba(' . max(0, $rgba[0] - 20) . ',' . max(0, $rgba[1] - 20) . ',' . max(0, $rgba[2] - 20) . ',' . $rgba[3] . ')', 'veryDarken' => 'rgba(' . max(0, $rgba[0] - 20) . ',' . max(0, $rgba[1] - 20) . ',' . max(0, $rgba[2] - 20) . ',' . $rgba[3] . ')',
'text' => self::relativeLuminanceW3C($rgba) > .22 ? "#222" : "#DDD", 'text' => self::relativeLuminanceW3C($rgba) > .22 ? "#222" : "#DDD",
'rgb' => 'rgb(' . $rgba[0] . ',' . $rgba[1] . ',' . $rgba[2] . ')', 'rgb' => 'rgb(' . $rgba[0] . ',' . $rgba[1] . ',' . $rgba[2] . ')',
'invert' => 'rgba (' . 'invert' => 'rgba (' .
($rgba[0] < 128 ? 255 : 0) . ',' . ($rgba[0] < 128 ? 255 : 0) . ',' .
($rgba[1] < 128 ? 255 : 0) . ',' . ($rgba[1] < 128 ? 255 : 0) . ',' .
($rgba[1] < 128 ? 255 : 0) . ',' . ($rgba[1] < 128 ? 255 : 0) . ',' .
($rgba[0] < 128 ? 255 : 0) . ')' ($rgba[0] < 128 ? 255 : 0) . ')'
]; ];
} }
@ -395,8 +408,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]);
} }
/** /**
@ -419,16 +432,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(
explode(',', 'á,à,â,ä,ã,å,ç,é,è,ê,ë,í,ì,î,ï,ñ,ó,ò,ô,ö,õ,ú,ù,û,ü,ý,ÿ,\',", '), str_replace(
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(',', 'á,à,â,ä,ã,å,ç,é,è,ê,ë,í,ì,î,ï,ñ,ó,ò,ô,ö,õ,ú,ù,û,ü,ý,ÿ,\',", '),
$text 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 = 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);
@ -464,6 +480,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;
} }
@ -516,6 +537,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;
} }
@ -544,7 +569,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);
@ -568,7 +593,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>';
} }
@ -658,25 +683,25 @@ class helper
/** /**
* 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 = [])
{ {
@ -52,7 +58,8 @@ class JsonDb extends \Prowebcraft\Dot
public function set($key, $value = null, $save = true) public function set($key, $value = null, $save = true)
{ {
parent::set($key, $value); parent::set($key, $value);
if ($save) $this->save(); if ($save)
$this->save();
return $this; return $this;
} }
@ -68,7 +75,8 @@ class JsonDb extends \Prowebcraft\Dot
public function add($key, $value = null, $pop = false, $save = true) public function add($key, $value = null, $pop = false, $save = true)
{ {
parent::add($key, $value, $pop); parent::add($key, $value, $pop);
if ($save) $this->save(); if ($save)
$this->save();
return $this; return $this;
} }
@ -82,7 +90,8 @@ class JsonDb extends \Prowebcraft\Dot
public function delete($key, $save = true) public function delete($key, $save = true)
{ {
parent::delete($key); parent::delete($key);
if ($save) $this->save(); if ($save)
$this->save();
return $this; return $this;
} }
@ -98,7 +107,8 @@ class JsonDb extends \Prowebcraft\Dot
public function clear($key = null, $format = false, $save = true) public function clear($key = null, $format = false, $save = true)
{ {
parent::clear($key, $format); parent::clear($key, $format);
if ($save) $this->save(); if ($save)
$this->save();
return $this; return $this;
} }
@ -108,19 +118,20 @@ class JsonDb extends \Prowebcraft\Dot
* @param bool $reload Reboot data? * @param bool $reload Reboot data?
* @return array|mixed|null * @return array|mixed|null
*/ */
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);
} }
} }
} }
$this->data = json_decode(file_get_contents($this->db), true); $this->data = json_decode(file_get_contents($this->db), true);
@ -135,9 +146,43 @@ class JsonDb extends \Prowebcraft\Dot
/** /**
* Save database * Save database
*/ */
public function save() { public function save()
file_put_contents($this->db, json_encode($this->data, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT|LOCK_EX)); // Multi user get a locker {
// Encode les données au format JSON avec les options spécifiées
//$encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT | JSON_PRETTY_PRINT);
$encoded_data = json_encode($this->data, JSON_UNESCAPED_UNICODE | JSON_FORCE_OBJECT);
// Vérifie la longueur de la chaîne JSON encodée
$encoded_length = strlen($encoded_data);
// Initialise le compteur de tentatives
$attempt = 0;
// Tente d'encoder les données en JSON et de les sauvegarder jusqu'à 5 fois en cas d'échec
while ($attempt < 5) {
// Essaye d'écrire les données encodées dans le fichier de base de données
$write_result = file_put_contents($this->db, $encoded_data, LOCK_EX); // Les utilisateurs multiples obtiennent un verrou
// Vérifie si l'écriture a réussi
if ($write_result === $encoded_length) {
// Sort de la boucle si l'écriture a réussi
break;
}
// Incrémente le compteur de tentatives
$attempt++;
// Attente
sleep(1);
}
// 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.');
}
} }
} }

1355
core/class/layout.class.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -350,8 +350,8 @@ class PHPMailer
public $Password = ''; public $Password = '';
/** /**
* SMTP auth type. * SMTP authentication type. Options are CRAM-MD5, LOGIN, PLAIN, XOAUTH2.
* Options are CRAM-MD5, LOGIN, PLAIN, XOAUTH2, attempted in that order if not specified. * If not specified, the first one from that list that the server supports will be selected.
* *
* @var string * @var string
*/ */
@ -750,7 +750,7 @@ class PHPMailer
* *
* @var string * @var string
*/ */
const VERSION = '6.6.0'; const VERSION = '6.7.1';
/** /**
* Error severity: message only, continue processing. * Error severity: message only, continue processing.
@ -858,7 +858,7 @@ class PHPMailer
private function mailPassthru($to, $subject, $body, $header, $params) private function mailPassthru($to, $subject, $body, $header, $params)
{ {
//Check overloading of mail function to avoid double-encoding //Check overloading of mail function to avoid double-encoding
if (ini_get('mbstring.func_overload') & 1) { if ((int)ini_get('mbstring.func_overload') & 1) {
$subject = $this->secureHeader($subject); $subject = $this->secureHeader($subject);
} else { } else {
$subject = $this->encodeHeader($this->secureHeader($subject)); $subject = $this->encodeHeader($this->secureHeader($subject));
@ -1066,8 +1066,8 @@ class PHPMailer
* Addresses that have been added already return false, but do not throw exceptions. * Addresses that have been added already return false, but do not throw exceptions.
* *
* @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo'
* @param string $address The email address to send, resp. to reply to * @param string $address The email address
* @param string $name * @param string $name An optional username associated with the address
* *
* @throws Exception * @throws Exception
* *
@ -1075,9 +1075,11 @@ class PHPMailer
*/ */
protected function addOrEnqueueAnAddress($kind, $address, $name) protected function addOrEnqueueAnAddress($kind, $address, $name)
{ {
$address = trim($address); $pos = false;
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim if ($address !== null) {
$pos = strrpos($address, '@'); $address = trim($address);
$pos = strrpos($address, '@');
}
if (false === $pos) { if (false === $pos) {
//At-sign is missing. //At-sign is missing.
$error_message = sprintf( $error_message = sprintf(
@ -1094,8 +1096,14 @@ class PHPMailer
return false; return false;
} }
if ($name !== null && is_string($name)) {
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
} else {
$name = '';
}
$params = [$kind, $address, $name]; $params = [$kind, $address, $name];
//Enqueue addresses with IDN until we know the PHPMailer::$CharSet. //Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
//Domain is assumed to be whatever is after the last @ symbol in the address
if (static::idnSupported() && $this->has8bitChars(substr($address, ++$pos))) { if (static::idnSupported() && $this->has8bitChars(substr($address, ++$pos))) {
if ('Reply-To' !== $kind) { if ('Reply-To' !== $kind) {
if (!array_key_exists($address, $this->RecipientsQueue)) { if (!array_key_exists($address, $this->RecipientsQueue)) {
@ -1116,6 +1124,22 @@ class PHPMailer
return call_user_func_array([$this, 'addAnAddress'], $params); return call_user_func_array([$this, 'addAnAddress'], $params);
} }
/**
* Set the boundaries to use for delimiting MIME parts.
* If you override this, ensure you set all 3 boundaries to unique values.
* The default boundaries include a "=_" sequence which cannot occur in quoted-printable bodies,
* as suggested by https://www.rfc-editor.org/rfc/rfc2045#section-6.7
*
* @return void
*/
public function setBoundaries()
{
$this->uniqueid = $this->generateId();
$this->boundary[1] = 'b1=_' . $this->uniqueid;
$this->boundary[2] = 'b2=_' . $this->uniqueid;
$this->boundary[3] = 'b3=_' . $this->uniqueid;
}
/** /**
* Add an address to one of the recipient arrays or to the ReplyTo array. * Add an address to one of the recipient arrays or to the ReplyTo array.
* Addresses that have been added already return false, but do not throw exceptions. * Addresses that have been added already return false, but do not throw exceptions.
@ -1280,7 +1304,7 @@ class PHPMailer
*/ */
public function setFrom($address, $name = '', $auto = true) public function setFrom($address, $name = '', $auto = true)
{ {
$address = trim($address); $address = trim((string)$address);
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
//Don't validate now addresses with IDN. Will be done in send(). //Don't validate now addresses with IDN. Will be done in send().
$pos = strrpos($address, '@'); $pos = strrpos($address, '@');
@ -1547,17 +1571,17 @@ class PHPMailer
//Validate From, Sender, and ConfirmReadingTo addresses //Validate From, Sender, and ConfirmReadingTo addresses
foreach (['From', 'Sender', 'ConfirmReadingTo'] as $address_kind) { foreach (['From', 'Sender', 'ConfirmReadingTo'] as $address_kind) {
$this->$address_kind = trim($this->$address_kind); $this->{$address_kind} = trim($this->{$address_kind});
if (empty($this->$address_kind)) { if (empty($this->{$address_kind})) {
continue; continue;
} }
$this->$address_kind = $this->punyencodeAddress($this->$address_kind); $this->{$address_kind} = $this->punyencodeAddress($this->{$address_kind});
if (!static::validateAddress($this->$address_kind)) { if (!static::validateAddress($this->{$address_kind})) {
$error_message = sprintf( $error_message = sprintf(
'%s (%s): %s', '%s (%s): %s',
$this->lang('invalid_address'), $this->lang('invalid_address'),
$address_kind, $address_kind,
$this->$address_kind $this->{$address_kind}
); );
$this->setError($error_message); $this->setError($error_message);
$this->edebug($error_message); $this->edebug($error_message);
@ -1657,17 +1681,17 @@ class PHPMailer
default: default:
$sendMethod = $this->Mailer . 'Send'; $sendMethod = $this->Mailer . 'Send';
if (method_exists($this, $sendMethod)) { if (method_exists($this, $sendMethod)) {
return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody); return $this->{$sendMethod}($this->MIMEHeader, $this->MIMEBody);
} }
return $this->mailSend($this->MIMEHeader, $this->MIMEBody); return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
} }
} catch (Exception $exc) { } catch (Exception $exc) {
if ($this->Mailer === 'smtp' && $this->SMTPKeepAlive == true) {
$this->smtp->reset();
}
$this->setError($exc->getMessage()); $this->setError($exc->getMessage());
$this->edebug($exc->getMessage()); $this->edebug($exc->getMessage());
if ($this->Mailer === 'smtp' && $this->SMTPKeepAlive == true && $this->smtp->connected()) {
$this->smtp->reset();
}
if ($this->exceptions) { if ($this->exceptions) {
throw $exc; throw $exc;
} }
@ -1855,7 +1879,7 @@ class PHPMailer
if (!static::isPermittedPath($path)) { if (!static::isPermittedPath($path)) {
return false; return false;
} }
$readable = file_exists($path); $readable = is_file($path);
//If not a UNC path (expected to start with \\), check read permission, see #2069 //If not a UNC path (expected to start with \\), check read permission, see #2069
if (strpos($path, '\\\\') !== 0) { if (strpos($path, '\\\\') !== 0) {
$readable = $readable && is_readable($path); $readable = $readable && is_readable($path);
@ -1883,7 +1907,14 @@ class PHPMailer
foreach ($this->to as $toaddr) { foreach ($this->to as $toaddr) {
$toArr[] = $this->addrFormat($toaddr); $toArr[] = $this->addrFormat($toaddr);
} }
$to = implode(', ', $toArr); $to = trim(implode(', ', $toArr));
//If there are no To-addresses (e.g. when sending only to BCC-addresses)
//the following should be added to get a correct DKIM-signature.
//Compare with $this->preSend()
if ($to === '') {
$to = 'undisclosed-recipients:;';
}
$params = null; $params = null;
//This sets the SMTP envelope sender which gets turned into a return-path header by the receiver //This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
@ -2086,6 +2117,9 @@ class PHPMailer
$this->smtp->setDebugLevel($this->SMTPDebug); $this->smtp->setDebugLevel($this->SMTPDebug);
$this->smtp->setDebugOutput($this->Debugoutput); $this->smtp->setDebugOutput($this->Debugoutput);
$this->smtp->setVerp($this->do_verp); $this->smtp->setVerp($this->do_verp);
if ($this->Host === null) {
$this->Host = 'localhost';
}
$hosts = explode(';', $this->Host); $hosts = explode(';', $this->Host);
$lastexception = null; $lastexception = null;
@ -2192,7 +2226,8 @@ class PHPMailer
//As we've caught all exceptions, just report whatever the last one was //As we've caught all exceptions, just report whatever the last one was
if ($this->exceptions && null !== $lastexception) { if ($this->exceptions && null !== $lastexception) {
throw $lastexception; throw $lastexception;
} elseif ($this->exceptions) { }
if ($this->exceptions) {
// no exception was thrown, likely $this->smtp->connect() failed // no exception was thrown, likely $this->smtp->connect() failed
$message = $this->getSmtpErrorMessage('connect_host'); $message = $this->getSmtpErrorMessage('connect_host');
throw new Exception($message); throw new Exception($message);
@ -2775,10 +2810,7 @@ class PHPMailer
{ {
$body = ''; $body = '';
//Create unique IDs and preset boundaries //Create unique IDs and preset boundaries
$this->uniqueid = $this->generateId(); $this->setBoundaries();
$this->boundary[1] = 'b1_' . $this->uniqueid;
$this->boundary[2] = 'b2_' . $this->uniqueid;
$this->boundary[3] = 'b3_' . $this->uniqueid;
if ($this->sign_key_file) { if ($this->sign_key_file) {
$body .= $this->getMailMIME() . static::$LE; $body .= $this->getMailMIME() . static::$LE;
@ -2814,7 +2846,7 @@ class PHPMailer
$altBodyEncoding = static::ENCODING_QUOTED_PRINTABLE; $altBodyEncoding = static::ENCODING_QUOTED_PRINTABLE;
} }
//Use this as a preamble in all multipart message types //Use this as a preamble in all multipart message types
$mimepre = 'This is a multi-part message in MIME format.' . static::$LE . static::$LE; $mimepre = '';
switch ($this->message_type) { switch ($this->message_type) {
case 'inline': case 'inline':
$body .= $mimepre; $body .= $mimepre;
@ -3050,6 +3082,18 @@ class PHPMailer
return $body; return $body;
} }
/**
* Get the boundaries that this message will use
* @return array
*/
public function getBoundaries()
{
if (empty($this->boundary)) {
$this->setBoundaries();
}
return $this->boundary;
}
/** /**
* Return the start of a message boundary. * Return the start of a message boundary.
* *
@ -3705,20 +3749,21 @@ class PHPMailer
* These differ from 'regular' attachments in that they are intended to be * These differ from 'regular' attachments in that they are intended to be
* displayed inline with the message, not just attached for download. * displayed inline with the message, not just attached for download.
* This is used in HTML messages that embed the images * This is used in HTML messages that embed the images
* the HTML refers to using the $cid value. * the HTML refers to using the `$cid` value in `img` tags, for example `<img src="cid:mylogo">`.
* Never use a user-supplied path to a file! * Never use a user-supplied path to a file!
* *
* @param string $path Path to the attachment * @param string $path Path to the attachment
* @param string $cid Content ID of the attachment; Use this to reference * @param string $cid Content ID of the attachment; Use this to reference
* the content when using an embedded image in HTML * the content when using an embedded image in HTML
* @param string $name Overrides the attachment name * @param string $name Overrides the attachment filename
* @param string $encoding File encoding (see $Encoding) * @param string $encoding File encoding (see $Encoding) defaults to `base64`
* @param string $type File MIME type * @param string $type File MIME type (by default mapped from the `$path` filename's extension)
* @param string $disposition Disposition to use * @param string $disposition Disposition to use: `inline` (default) or `attachment`
* * (unlikely you want this {@see `addAttachment()`} instead)
* @throws Exception
* *
* @return bool True on successfully adding an attachment * @return bool True on successfully adding an attachment
* @throws Exception
*
*/ */
public function addEmbeddedImage( public function addEmbeddedImage(
$path, $path,
@ -4096,12 +4141,8 @@ class PHPMailer
//Is it a valid IPv4 address? //Is it a valid IPv4 address?
return filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false; return filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false;
} }
if (filter_var('http://' . $host, FILTER_VALIDATE_URL) !== false) { //Is it a syntactically valid hostname (when embeded in a URL)?
//Is it a syntactically valid hostname? return filter_var('http://' . $host, FILTER_VALIDATE_URL) !== false;
return true;
}
return false;
} }
/** /**
@ -4170,6 +4211,7 @@ class PHPMailer
* @param string $name Custom header name * @param string $name Custom header name
* @param string|null $value Header value * @param string|null $value Header value
* *
* @return bool True if a header was set successfully
* @throws Exception * @throws Exception
*/ */
public function addCustomHeader($name, $value = null) public function addCustomHeader($name, $value = null)
@ -4464,6 +4506,7 @@ class PHPMailer
'ics' => 'text/calendar', 'ics' => 'text/calendar',
'xml' => 'text/xml', 'xml' => 'text/xml',
'xsl' => 'text/xml', 'xsl' => 'text/xml',
'csv' => 'text/csv',
'wmv' => 'video/x-ms-wmv', 'wmv' => 'video/x-ms-wmv',
'mpeg' => 'video/mpeg', 'mpeg' => 'video/mpeg',
'mpe' => 'video/mpeg', 'mpe' => 'video/mpeg',
@ -4571,7 +4614,7 @@ class PHPMailer
public function set($name, $value = '') public function set($name, $value = '')
{ {
if (property_exists($this, $name)) { if (property_exists($this, $name)) {
$this->$name = $value; $this->{$name} = $value;
return true; return true;
} }
@ -4618,15 +4661,27 @@ class PHPMailer
} }
/** /**
* Remove trailing breaks from a string. * Remove trailing whitespace from a string.
*
* @param string $text
*
* @return string The text to remove whitespace from
*/
public static function stripTrailingWSP($text)
{
return rtrim($text, " \r\n\t");
}
/**
* Strip trailing line breaks from a string.
* *
* @param string $text * @param string $text
* *
* @return string The text to remove breaks from * @return string The text to remove breaks from
*/ */
public static function stripTrailingWSP($text) public static function stripTrailingBreaks($text)
{ {
return rtrim($text, " \r\n\t"); return rtrim($text, "\r\n");
} }
/** /**
@ -4792,7 +4847,7 @@ class PHPMailer
$body = static::normalizeBreaks($body, self::CRLF); $body = static::normalizeBreaks($body, self::CRLF);
//Reduce multiple trailing line breaks to a single one //Reduce multiple trailing line breaks to a single one
return static::stripTrailingWSP($body) . self::CRLF; return static::stripTrailingBreaks($body) . self::CRLF;
} }
/** /**

View File

@ -35,7 +35,7 @@ class SMTP
* *
* @var string * @var string
*/ */
const VERSION = '6.6.0'; const VERSION = '6.7.1';
/** /**
* SMTP line break constant. * SMTP line break constant.
@ -682,7 +682,6 @@ class SMTP
*/ */
public function close() public function close()
{ {
$this->setError('');
$this->server_caps = null; $this->server_caps = null;
$this->helo_rply = null; $this->helo_rply = null;
if (is_resource($this->smtp_conn)) { if (is_resource($this->smtp_conn)) {
@ -1037,7 +1036,10 @@ class SMTP
return false; return false;
} }
$this->setError(''); //Don't clear the error store when using keepalive
if ($command !== 'RSET') {
$this->setError('');
}
return true; return true;
} }

View File

@ -0,0 +1,28 @@
<?php
/**
* German PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer
*/
$PHPMAILER_LANG['authenticate'] = 'SMTP-Fehler: Authentifizierung fehlgeschlagen.';
$PHPMAILER_LANG['connect_host'] = 'SMTP-Fehler: Konnte keine Verbindung zum SMTP-Host herstellen.';
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP-Fehler: Daten werden nicht akzeptiert.';
$PHPMAILER_LANG['empty_message'] = 'E-Mail-Inhalt ist leer.';
$PHPMAILER_LANG['encoding'] = 'Unbekannte Kodierung: ';
$PHPMAILER_LANG['execute'] = 'Konnte folgenden Befehl nicht ausführen: ';
$PHPMAILER_LANG['file_access'] = 'Zugriff auf folgende Datei fehlgeschlagen: ';
$PHPMAILER_LANG['file_open'] = 'Dateifehler: Konnte folgende Datei nicht öffnen: ';
$PHPMAILER_LANG['from_failed'] = 'Die folgende Absenderadresse ist nicht korrekt: ';
$PHPMAILER_LANG['instantiate'] = 'Mail-Funktion konnte nicht initialisiert werden.';
$PHPMAILER_LANG['invalid_address'] = 'Die Adresse ist ungültig: ';
$PHPMAILER_LANG['invalid_hostentry'] = 'Ungültiger Hosteintrag: ';
$PHPMAILER_LANG['invalid_host'] = 'Ungültiger Host: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer wird nicht unterstützt.';
$PHPMAILER_LANG['provide_address'] = 'Bitte geben Sie mindestens eine Empfängeradresse an.';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP-Fehler: Die folgenden Empfänger sind nicht korrekt: ';
$PHPMAILER_LANG['signing'] = 'Fehler beim Signieren: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'Verbindung zum SMTP-Server fehlgeschlagen.';
$PHPMAILER_LANG['smtp_error'] = 'Fehler vom SMTP-Server: ';
$PHPMAILER_LANG['variable_set'] = 'Kann Variable nicht setzen oder zurücksetzen: ';
$PHPMAILER_LANG['extension_missing'] = 'Fehlende Erweiterung: ';

View File

@ -0,0 +1,33 @@
<?php
/**
* Greek PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer
*/
$PHPMAILER_LANG['authenticate'] = 'Σφάλμα SMTP: Αδυναμία πιστοποίησης.';
$PHPMAILER_LANG['buggy_php'] = 'Η έκδοση PHP που χρησιμοποιείτε παρουσιάζει σφάλμα που μπορεί να έχει ως αποτέλεσμα κατεστραμένα μηνύματα. Για να το διορθώσετε, αλλάξτε τον τρόπο αποστολής σε SMTP, απενεργοποιήστε την επιλογή mail.add_x_header στο αρχείο php.ini, αλλάξτε λειτουργικό σε MacOS ή Linux ή αναβαθμίστε την PHP σε έκδοση 7.0.17+ ή 7.1.3+.';
$PHPMAILER_LANG['connect_host'] = 'Σφάλμα SMTP: Αδυναμία σύνδεσης με τον φιλοξενητή SMTP.';
$PHPMAILER_LANG['data_not_accepted'] = 'Σφάλμα SMTP: Μη αποδεκτά δεδομένα.';
$PHPMAILER_LANG['empty_message'] = 'Η ηλεκτρονική επιστολή δεν έχει περιεχόμενο.';
$PHPMAILER_LANG['encoding'] = 'Άγνωστη μορφή κωδικοποίησης: ';
$PHPMAILER_LANG['execute'] = 'Αδυναμία εκτέλεσης: ';
$PHPMAILER_LANG['extension_missing'] = 'Απουσία επέκτασης: ';
$PHPMAILER_LANG['file_access'] = 'Αδυναμία πρόσβασης στο αρχείο: ';
$PHPMAILER_LANG['file_open'] = 'Σφάλμα Αρχείου: Αδυναμία ανοίγματος αρχείου: ';
$PHPMAILER_LANG['from_failed'] = 'Η ακόλουθη διεύθυνση αποστολέα δεν είναι σωστή: ';
$PHPMAILER_LANG['instantiate'] = 'Αδυναμία εκκίνησης συνάρτησης Mail.';
$PHPMAILER_LANG['invalid_address'] = 'Μη έγκυρη διεύθυνση: ';
$PHPMAILER_LANG['invalid_header'] = 'Μη έγκυρο όνομα κεφαλίδας ή τιμή';
$PHPMAILER_LANG['invalid_hostentry'] = 'Μη έγκυρη εισαγωγή φιλοξενητή: ';
$PHPMAILER_LANG['invalid_host'] = 'Μη έγκυρος φιλοξενητής: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer δεν υποστηρίζεται.';
$PHPMAILER_LANG['provide_address'] = 'Δώστε τουλάχιστον μια ηλεκτρονική διεύθυνση παραλήπτη.';
$PHPMAILER_LANG['recipients_failed'] = 'Σφάλμα SMTP: Οι παρακάτω διευθύνσεις παραλήπτη δεν είναι έγκυρες: ';
$PHPMAILER_LANG['signing'] = 'Σφάλμα υπογραφής: ';
$PHPMAILER_LANG['smtp_code'] = 'Κώδικάς SMTP: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Πρόσθετες πληροφορίες SMTP: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'Αποτυχία σύνδεσης SMTP.';
$PHPMAILER_LANG['smtp_detail'] = 'Λεπτομέρεια: ';
$PHPMAILER_LANG['smtp_error'] = 'Σφάλμα με τον διακομιστή SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'Αδυναμία ορισμού ή επαναφοράς μεταβλητής: ';

View File

@ -0,0 +1,31 @@
<?php
/**
* Spanish PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer
* @author Matt Sturdy <matt.sturdy@gmail.com>
* @author Crystopher Glodzienski Cardoso <crystopher.glodzienski@gmail.com>
*/
$PHPMAILER_LANG['authenticate'] = 'Error SMTP: Imposible autentificar.';
$PHPMAILER_LANG['connect_host'] = 'Error SMTP: Imposible conectar al servidor SMTP.';
$PHPMAILER_LANG['data_not_accepted'] = 'Error SMTP: Datos no aceptados.';
$PHPMAILER_LANG['empty_message'] = 'El cuerpo del mensaje está vacío.';
$PHPMAILER_LANG['encoding'] = 'Codificación desconocida: ';
$PHPMAILER_LANG['execute'] = 'Imposible ejecutar: ';
$PHPMAILER_LANG['file_access'] = 'Imposible acceder al archivo: ';
$PHPMAILER_LANG['file_open'] = 'Error de Archivo: Imposible abrir el archivo: ';
$PHPMAILER_LANG['from_failed'] = 'La(s) siguiente(s) direcciones de remitente fallaron: ';
$PHPMAILER_LANG['instantiate'] = 'Imposible crear una instancia de la función Mail.';
$PHPMAILER_LANG['invalid_address'] = 'Imposible enviar: dirección de email inválido: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer no está soportado.';
$PHPMAILER_LANG['provide_address'] = 'Debe proporcionar al menos una dirección de email de destino.';
$PHPMAILER_LANG['recipients_failed'] = 'Error SMTP: Los siguientes destinos fallaron: ';
$PHPMAILER_LANG['signing'] = 'Error al firmar: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falló.';
$PHPMAILER_LANG['smtp_error'] = 'Error del servidor SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'No se pudo configurar la variable: ';
$PHPMAILER_LANG['extension_missing'] = 'Extensión faltante: ';
$PHPMAILER_LANG['smtp_code'] = 'Código del servidor SMTP: ';
$PHPMAILER_LANG['smtp_code_ex'] = 'Información adicional del servidor SMTP: ';
$PHPMAILER_LANG['invalid_header'] = 'Nombre o valor de encabezado no válido';

View File

@ -0,0 +1,28 @@
<?php
/**
* Italian PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer
* @author Ilias Bartolini <brain79@inwind.it>
* @author Stefano Sabatini <sabas88@gmail.com>
*/
$PHPMAILER_LANG['authenticate'] = 'SMTP Error: Impossibile autenticarsi.';
$PHPMAILER_LANG['connect_host'] = 'SMTP Error: Impossibile connettersi all\'host SMTP.';
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Error: Dati non accettati dal server.';
$PHPMAILER_LANG['empty_message'] = 'Il corpo del messaggio è vuoto';
$PHPMAILER_LANG['encoding'] = 'Codifica dei caratteri sconosciuta: ';
$PHPMAILER_LANG['execute'] = 'Impossibile eseguire l\'operazione: ';
$PHPMAILER_LANG['file_access'] = 'Impossibile accedere al file: ';
$PHPMAILER_LANG['file_open'] = 'File Error: Impossibile aprire il file: ';
$PHPMAILER_LANG['from_failed'] = 'I seguenti indirizzi mittenti hanno generato errore: ';
$PHPMAILER_LANG['instantiate'] = 'Impossibile istanziare la funzione mail';
$PHPMAILER_LANG['invalid_address'] = 'Impossibile inviare, l\'indirizzo email non è valido: ';
$PHPMAILER_LANG['provide_address'] = 'Deve essere fornito almeno un indirizzo ricevente';
$PHPMAILER_LANG['mailer_not_supported'] = 'Mailer non supportato';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP Error: I seguenti indirizzi destinatari hanno generato un errore: ';
$PHPMAILER_LANG['signing'] = 'Errore nella firma: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() fallita.';
$PHPMAILER_LANG['smtp_error'] = 'Errore del server SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'Impossibile impostare o resettare la variabile: ';
$PHPMAILER_LANG['extension_missing'] = 'Estensione mancante: ';

View File

@ -0,0 +1,27 @@
<?php
/**
* Portuguese (European) PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer
* @author Jonadabe <jonadabe@hotmail.com>
*/
$PHPMAILER_LANG['authenticate'] = 'Erro do SMTP: Não foi possível realizar a autenticação.';
$PHPMAILER_LANG['connect_host'] = 'Erro do SMTP: Não foi possível realizar ligação com o servidor SMTP.';
$PHPMAILER_LANG['data_not_accepted'] = 'Erro do SMTP: Os dados foram rejeitados.';
$PHPMAILER_LANG['empty_message'] = 'A mensagem no e-mail está vazia.';
$PHPMAILER_LANG['encoding'] = 'Codificação desconhecida: ';
$PHPMAILER_LANG['execute'] = 'Não foi possível executar: ';
$PHPMAILER_LANG['file_access'] = 'Não foi possível aceder o ficheiro: ';
$PHPMAILER_LANG['file_open'] = 'Abertura do ficheiro: Não foi possível abrir o ficheiro: ';
$PHPMAILER_LANG['from_failed'] = 'Ocorreram falhas nos endereços dos seguintes remententes: ';
$PHPMAILER_LANG['instantiate'] = 'Não foi possível iniciar uma instância da função mail.';
$PHPMAILER_LANG['invalid_address'] = 'Não foi enviado nenhum e-mail para o endereço de e-mail inválido: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer não é suportado.';
$PHPMAILER_LANG['provide_address'] = 'Tem de fornecer pelo menos um endereço como destinatário do e-mail.';
$PHPMAILER_LANG['recipients_failed'] = 'Erro do SMTP: O endereço do seguinte destinatário falhou: ';
$PHPMAILER_LANG['signing'] = 'Erro ao assinar: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP Connect() falhou.';
$PHPMAILER_LANG['smtp_error'] = 'Erro de servidor SMTP: ';
$PHPMAILER_LANG['variable_set'] = 'Não foi possível definir ou redefinir a variável: ';
$PHPMAILER_LANG['extension_missing'] = 'Extensão em falta: ';

View File

@ -0,0 +1,31 @@
<?php
/**
* Turkish PHPMailer language file: refer to English translation for definitive list
* @package PHPMailer
* @author Elçin Özel
* @author Can Yılmaz
* @author Mehmet Benlioğlu
* @author @yasinaydin
* @author Ogün Karakuş
*/
$PHPMAILER_LANG['authenticate'] = 'SMTP Hatası: Oturum açılamadı.';
$PHPMAILER_LANG['connect_host'] = 'SMTP Hatası: SMTP sunucusuna bağlanılamadı.';
$PHPMAILER_LANG['data_not_accepted'] = 'SMTP Hatası: Veri kabul edilmedi.';
$PHPMAILER_LANG['empty_message'] = 'Mesajın içeriği boş';
$PHPMAILER_LANG['encoding'] = 'Bilinmeyen karakter kodlama: ';
$PHPMAILER_LANG['execute'] = 'Çalıştırılamadı: ';
$PHPMAILER_LANG['file_access'] = 'Dosyaya erişilemedi: ';
$PHPMAILER_LANG['file_open'] = 'Dosya Hatası: Dosya açılamadı: ';
$PHPMAILER_LANG['from_failed'] = 'Belirtilen adreslere gönderme başarısız: ';
$PHPMAILER_LANG['instantiate'] = 'Örnek e-posta fonksiyonu oluşturulamadı.';
$PHPMAILER_LANG['invalid_address'] = 'Geçersiz e-posta adresi: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' e-posta kütüphanesi desteklenmiyor.';
$PHPMAILER_LANG['provide_address'] = 'En az bir alıcı e-posta adresi belirtmelisiniz.';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP Hatası: Belirtilen alıcılara ulaşılamadı: ';
$PHPMAILER_LANG['signing'] = 'İmzalama hatası: ';
$PHPMAILER_LANG['smtp_connect_failed'] = 'SMTP connect() fonksiyonu başarısız.';
$PHPMAILER_LANG['smtp_error'] = 'SMTP sunucu hatası: ';
$PHPMAILER_LANG['variable_set'] = 'Değişken ayarlanamadı ya da sıfırlanamadı: ';
$PHPMAILER_LANG['extension_missing'] = 'Eklenti bulunamadı: ';

899
core/class/router.class.php Normal file
View File

@ -0,0 +1,899 @@
<?php
class core extends common
{
/**
* Constructeur du coeur
*/
public function __construct()
{
parent::__construct();
// Token CSRF
if (empty($_SESSION['csrf'])) {
$_SESSION['csrf'] = bin2hex(openssl_random_pseudo_bytes(64));
}
// Fuseau horaire
common::$timezone = $this->getData(['config', 'timezone']); // Utile pour transmettre le timezone à la classe helper
date_default_timezone_set(common::$timezone);
// Supprime les fichiers temporaires
$lastClearTmp = mktime(0, 0, 0);
if ($lastClearTmp > $this->getData(['core', 'lastClearTmp']) + 86400) {
$iterator = new DirectoryIterator(common::TEMP_DIR);
foreach ($iterator as $fileInfos) {
if (
$fileInfos->isFile() &&
$fileInfos->getBasename() !== '.htaccess' &&
$fileInfos->getBasename() !== '.gitkeep'
) {
@unlink($fileInfos->getPathname());
}
}
// Date de la dernière suppression
$this->setData(['core', 'lastClearTmp', $lastClearTmp]);
// Enregistre les données
//$this->SaveData();
}
// Backup automatique des données
$lastBackup = mktime(0, 0, 0);
if (
$this->getData(['config', 'autoBackup'])
and $lastBackup > $this->getData(['core', 'lastBackup']) + 86400
and $this->getData(['user']) // Pas de backup pendant l'installation
) {
// Copie des fichier de données
helper::autoBackup(common::BACKUP_DIR, ['backup', 'tmp', 'file']);
// Date du dernier backup
$this->setData(['core', 'lastBackup', $lastBackup]);
// Supprime les backups de plus de 30 jours
$iterator = new DirectoryIterator(common::BACKUP_DIR);
foreach ($iterator as $fileInfos) {
if (
$fileInfos->isFile()
and $fileInfos->getBasename() !== '.htaccess'
and $fileInfos->getMTime() + (86400 * 30) < time()
) {
@unlink($fileInfos->getPathname());
}
}
}
// Crée le fichier de personnalisation avancée
if (file_exists(common::DATA_DIR . 'custom.css') === false) {
$this->secure_file_put_contents(common::DATA_DIR . 'custom.css', file_get_contents('core/module/theme/resource/custom.css'));
chmod(common::DATA_DIR . 'custom.css', 0755);
}
// Crée le fichier de personnalisation
if (file_exists(common::DATA_DIR . 'theme.css') === false) {
$this->secure_file_put_contents(common::DATA_DIR . 'theme.css', '');
chmod(common::DATA_DIR . 'theme.css', 0755);
}
// Crée le fichier de personnalisation de l'administration
if (file_exists(common::DATA_DIR . 'admin.css') === false) {
$this->secure_file_put_contents(common::DATA_DIR . 'admin.css', '');
chmod(common::DATA_DIR . 'admin.css', 0755);
}
// Check la version rafraichissement du theme
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . 'theme.css'));
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['theme'])))) {
// Version
$css = '/*' . md5(json_encode($this->getData(['theme']))) . '*/';
/**
* Import des polices de caractères
* A partir du CDN
* ou dans le dossier site/file/source/fonts
* ou pas du tout si fonte webSafe
*/
// Fonts disponibles
$fontsAvailable['files'] = $this->getData(['font', 'files']);
$fontsAvailable['imported'] = $this->getData(['font', 'imported']);
$fontsAvailable['websafe'] = common::$fontsWebSafe;
// Fontes installées
$fonts = [
$this->getData(['theme', 'text', 'font']),
$this->getData(['theme', 'title', 'font']),
$this->getData(['theme', 'header', 'font']),
$this->getData(['theme', 'menu', 'font']),
$this->getData(['theme', 'footer', 'font'])
];
// Suppression des polices identiques
$fonts = array_unique($fonts);
/**
* Charge les fontes
*/
foreach ($fonts as $fontId) {
foreach (['websafe', 'imported', 'files'] as $typeFont) {
if (isset($fontsAvailable[$typeFont][$fontId])) {
$fonts[$fontId] = $fontsAvailable[$typeFont][$fontId]['font-family'];
}
}
}
// Fond du body
$colors = helper::colorVariants($this->getData(['theme', 'body', 'backgroundColor']));
// Body
$css .= 'body{font-family:' . $fonts[$this->getData(['theme', 'text', 'font'])] . ';}';
if ($themeBodyImage = $this->getData(['theme', 'body', 'image'])) {
// Image dans html pour éviter les déformations.
$css .= 'html {background-image:url("../file/source/' . $themeBodyImage . '");background-position:' . $this->getData(['theme', 'body', 'imagePosition']) . ';background-attachment:' . $this->getData(['theme', 'body', 'imageAttachment']) . ';background-size:' . $this->getData(['theme', 'body', 'imageSize']) . ';background-repeat:' . $this->getData(['theme', 'body', 'imageRepeat']) . '}';
// Couleur du body transparente
$css .= 'body {background-color: rgba(0,0,0,0)}';
} else {
// Pas d'image couleur du body
$css .= 'html {background-color:' . $colors['normal'] . ';}';
}
// Icône BacktoTop
$css .= '#backToTop {background-color:' . $this->getData(['theme', 'body', 'toTopbackgroundColor']) . ';color:' . $this->getData(['theme', 'body', 'toTopColor']) . ';}';
// Site
$colors = helper::colorVariants($this->getData(['theme', 'text', 'linkColor']));
$css .= 'a{color:' . $colors['normal'] . '}';
// Couleurs de site dans TinyMCe
$css .= 'div.mce-edit-area {font-family:' . $fonts[$this->getData(['theme', 'text', 'font'])] . ';}';
// Site dans TinyMCE
$css .= '.editorWysiwyg, .editorWysiwygComment {background-color:' . $this->getData(['theme', 'site', 'backgroundColor']) . ';}';
$css .= 'span.mce-text{background-color: unset !important;}';
$css .= 'body,.row > div{font-size:' . $this->getData(['theme', 'text', 'fontSize']) . '}';
$css .= 'body{color:' . $this->getData(['theme', 'text', 'textColor']) . '}';
$css .= 'select,input[type=password],input[type=email],input[type=text],input[type=date],input[type=time],input[type=week],input[type=month],input[type=datetime-local],.inputFile,select,textarea{color:' . $this->getData(['theme', 'text', 'textColor']) . ';background-color:' . $this->getData(['theme', 'site', 'backgroundColor']) . ';}';
// spécifiques au module de blog
$css .= '.blogDate {color:' . $this->getData(['theme', 'text', 'textColor']) . ';}.blogPicture img{border:1px solid ' . $this->getData(['theme', 'text', 'textColor']) . '; box-shadow: 1px 1px 5px ' . $this->getData(['theme', 'text', 'textColor']) . ';}';
// Couleur fixée dans admin.css
$css .= '.container {max-width:' . $this->getData(['theme', 'site', '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(['theme', 'site', '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(['theme', 'site', 'width']) === '750px'
? '.button, button{font-size:0.8em;}'
: '';
$css .= '#site{background-color:' . $this->getData(['theme', 'site', 'backgroundColor']) . ';border-radius:' . $this->getData(['theme', 'site', 'radius']) . ';box-shadow:' . $this->getData(['theme', 'site', 'shadow']) . ' #212223;}';
$colors = helper::colorVariants($this->getData(['theme', 'button', 'backgroundColor']));
$css .= '.speechBubble,.button,.button:hover,button[type=submit],.pagination a,.pagination a:hover,input[type=checkbox]:checked + label:before,input[type=radio]:checked + label:before,.helpContent{background-color:' . $colors['normal'] . ';color:' . $colors['text'] . '}';
$css .= '.helpButton span{color:' . $colors['normal'] . '}';
$css .= 'input[type=text]:hover,input[type=date]:hover,input[type=time]:hover,input[type=week]:hover,input[type=month]:hover,input[type=datetime-local]:hover,input[type=password]:hover,.inputFile:hover,select:hover,textarea:hover{border-color:' . $colors['normal'] . '}';
$css .= '.speechBubble:before{border-color:' . $colors['normal'] . ' transparent transparent transparent}';
$css .= '.button:hover,button[type=submit]:hover,.pagination a:hover,input[type=checkbox]:not(:active):checked:hover + label:before,input[type=checkbox]:active + label:before,input[type=radio]:checked:hover + label:before,input[type=radio]:not(:checked):active + label:before{background-color:' . $colors['darken'] . '}';
$css .= '.helpButton span:hover{color:' . $colors['darken'] . '}';
$css .= '.button:active,button[type=submit]:active,.pagination a:active{background-color:' . $colors['veryDarken'] . '}';
$colors = helper::colorVariants($this->getData(['theme', 'title', 'textColor']));
$css .= 'h1,h2,h3,h4,h5,h6,h1 a,h2 a,h3 a,h4 a,h5 a,h6 a{color:' . $colors['normal'] . ';font-family:' . $fonts[$this->getData(['theme', 'title', 'font'])] . ';font-weight:' . $this->getData(['theme', 'title', 'fontWeight']) . ';text-transform:' . $this->getData(['theme', 'title', 'textTransform']) . '}';
$css .= 'h1 a:hover,h2 a:hover,h3 a:hover,h4 a:hover,h5 a:hover,h6 a:hover{color:' . $colors['darken'] . '}';
// Les blocs
$colors = helper::colorVariants($this->getData(['theme', 'block', 'backgroundColor']));
$css .= '.block {border: 1px solid ' . $this->getdata(['theme', 'block', 'borderColor']) . ';}.block h4 {background-color:' . $colors['normal'] . ';color:' . $colors['text'] . ';}';
// Bannière
// Eléments communs
if ($this->getData(['theme', 'header', 'margin'])) {
if ($this->getData(['theme', 'menu', 'position']) === 'site-first') {
$css .= 'header{margin:0 20px}';
} else {
$css .= 'header{margin:20px 20px 0 20px}';
}
}
$colors = helper::colorVariants($this->getData(['theme', 'header', 'backgroundColor']));
$css .= 'header{background-color:' . $colors['normal'] . ';}';
// Bannière de type papier peint
if ($this->getData(['theme', 'header', 'feature']) === 'wallpaper') {
$css .= 'header{background-size:' . $this->getData(['theme', 'header', 'imageContainer']) . '}';
$css .= 'header{background-color:' . $colors['normal'];
// Valeur de hauteur traditionnelle
$css .= ';height:' . $this->getData(['theme', 'header', 'height']) . ';line-height:' . $this->getData(['theme', 'header', 'height']);
$css .= ';text-align:' . $this->getData(['theme', 'header', 'textAlign']) . '}';
if ($themeHeaderImage = $this->getData(['theme', 'header', 'image'])) {
$css .= 'header{background-image:url("../file/source/' . $themeHeaderImage . '");background-position:' . $this->getData(['theme', 'header', 'imagePosition']) . ';background-repeat:' . $this->getData(['theme', 'header', 'imageRepeat']) . '}';
}
$colors = helper::colorVariants($this->getData(['theme', 'header', 'textColor']));
$css .= 'header span{color:' . $colors['normal'] . ';font-family:' . $fonts[$this->getData(['theme', 'header', 'font'])] . ';font-weight:' . $this->getData(['theme', 'header', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'header', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'header', 'textTransform']) . '}';
}
// Bannière au Contenu HTML
if ($this->getData(['theme', 'header', 'feature']) === 'feature') {
// Hauteur de la taille du contenu perso
$css .= 'header {height:' . $this->getData(['theme', 'header', 'height']) . '; min-height:' . $this->getData(['theme', 'header', 'height']) . ';overflow: hidden;}';
}
// Menu
$colors = helper::colorVariants($this->getData(['theme', 'menu', 'backgroundColor']));
$css .= 'nav,nav.navMain a{background-color:' . $colors['normal'] . '}';
$css .= 'nav a,#toggle span,nav a:hover{color:' . $this->getData(['theme', 'menu', 'textColor']) . '}';
$css .= 'nav a:hover{background-color:' . $colors['darken'] . '}';
$css .= 'nav a.active{color:' . $this->getData(['theme', 'menu', 'activeTextColor']) . ';}';
if ($this->getData(['theme', 'menu', 'activeColorAuto']) === true) {
$css .= 'nav a.active{background-color:' . $colors['veryDarken'] . '}';
} else {
$css .= 'nav a.active{background-color:' . $this->getData(['theme', 'menu', 'activeColor']) . '}';
}
$css .= 'nav #burgerText{color:' . $colors['text'] . '}';
// Sous menu
$colors = helper::colorVariants($this->getData(['theme', 'menu', 'backgroundColorSub']));
$css .= 'nav .navSub a{background-color:' . $colors['normal'] . '}';
$css .= 'nav .navMain a.active {border-radius:' . $this->getData(['theme', 'menu', 'radius']) . '}';
$css .= '#menu{text-align:' . $this->getData(['theme', 'menu', 'textAlign']) . '}';
if ($this->getData(['theme', 'menu', 'margin'])) {
if (
$this->getData(['theme', 'menu', 'position']) === 'site-first'
or $this->getData(['theme', 'menu', 'position']) === 'site-second'
) {
$css .= 'nav{padding:10px 10px 0 10px;}';
} else {
$css .= 'nav{padding:0 10px}';
}
} else {
$css .= 'nav{margin:0}';
}
if (
$this->getData(['theme', 'menu', 'position']) === 'top'
) {
$css .= 'nav{padding:0 10px;}';
}
$css .= '#toggle span,#menu a{padding:' . $this->getData(['theme', 'menu', 'height']) . ';font-family:' . $fonts[$this->getData(['theme', 'menu', 'font'])] . ';font-weight:' . $this->getData(['theme', 'menu', 'fontWeight']) . ';font-size:' . $this->getData(['theme', 'menu', 'fontSize']) . ';text-transform:' . $this->getData(['theme', 'menu', 'textTransform']) . '}';
// Pied de page
$colors = helper::colorVariants($this->getData(['theme', 'footer', 'backgroundColor']));
if ($this->getData(['theme', 'footer', 'margin'])) {
$css .= 'footer{padding:0 20px;}';
} else {
$css .= 'footer{padding:0}';
}
$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 a{color:' . $this->getData(['theme', 'footer', 'textColor']) . '}';
$css .= 'footer #footersite > div {margin:' . $this->getData(['theme', 'footer', 'height']) . ' 0}';
$css .= 'footer #footerbody > div {margin:' . $this->getData(['theme', 'footer', 'height']) . ' 0}';
$css .= '@media (max-width: 768px) {footer #footerbody > div { padding: 2px }}';
$css .= '#footerSocials{text-align:' . $this->getData(['theme', 'footer', 'socialsAlign']) . '}';
$css .= '#footerText > p {text-align:' . $this->getData(['theme', 'footer', 'textAlign']) . '}';
$css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}';
// Enregistre la personnalisation
$this->secure_file_put_contents(common::DATA_DIR . 'theme.css', $css);
// Effacer le cache pour tenir compte de la couleur de fond TinyMCE
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
}
// Check la version rafraichissement du theme admin
$cssVersion = preg_split('/\*+/', file_get_contents(common::DATA_DIR . 'admin.css'));
if (empty($cssVersion[1]) or $cssVersion[1] !== md5(json_encode($this->getData(['admin'])))) {
// Version
$css = '/*' . md5(json_encode($this->getData(['admin']))) . '*/';
// Fonts disponibles
$fontsAvailable['files'] = $this->getData(['font', 'files']);
$fontsAvailable['imported'] = $this->getData(['font', 'imported']);
$fontsAvailable['websafe'] = common::$fontsWebSafe;
/**
* Import des polices de caractères
* A partir du CDN ou dans le dossier site/file/source/fonts
*/
$fonts = [
$this->getData(['admin', 'fontText']),
$this->getData(['admin', 'fontTitle']),
];
// Suppression des polices identiques
$fonts = array_unique($fonts);
/**
* Charge les fontes
*/
foreach ($fonts as $fontId) {
foreach (['websafe', 'imported', 'files'] as $typeFont) {
if (isset($fontsAvailable[$typeFont][$fontId])) {
$fonts[$fontId] = $fontsAvailable[$typeFont][$fontId]['font-family'];
}
}
}
// Thème Administration
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColor']));
$css .= '#site{background-color:' . $colors['normal'] . ';}';
$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 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
$colors = helper::colorVariants($this->getData(['admin', 'colorText']));
$css .= 'body:not(.editorWysiwyg), body:not(editorWysiwygComment),span .zwiico-help {color:' . $colors['normal'] . ';}';
$css .= 'table thead tr, table thead tr .zwiico-help{ background-color:' . $colors['normal'] . '; color:' . $colors['text'] . ';}';
$css .= 'table thead th { color:' . $colors['text'] . ';}';
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColorButton']));
$css .= 'input[type=checkbox]:checked + label::before,.speechBubble{background-color:' . $colors['normal'] . ';color:' . $colors['text'] . ';}';
$css .= '.speechBubble::before {border-color:' . $colors['normal'] . ' transparent transparent transparent;}';
$css .= '.button {background-color:' . $colors['normal'] . ';color:' . $colors['text'] . ';}.button:hover {background-color:' . $colors['darken'] . ';color:' . $colors['text'] . ';}.button:active {background-color:' . $colors['veryDarken'] . ';color:' . $colors['text'] . ';}';
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColorButtonGrey']));
$css .= '.button.buttonGrey {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonGrey:hover {background-color:' . $colors['darken'] . ';color:' . $colors['text'] . ';}.button.buttonGrey:active {background-color:' . $colors['veryDarken'] . ';color:' . $colors['text'] . ';}';
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColorButtonRed']));
$css .= '.button.buttonRed {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonRed:hover {background-color:' . $colors['darken'] . ';color:' . $colors['text'] . ';}.button.buttonRed:active {background-color:' . $colors['veryDarken'] . ';color:' . $colors['text'] . ';}';
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColorButtonHelp']));
$css .= '.button.buttonHelp {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonHelp:hover {background-color:' . $colors['darken'] . ';color:' . $colors['text'] . ';}.button.buttonHelp:active {background-color:' . $colors['veryDarken'] . ';color:' . $colors['text'] . ';}';
$colors = helper::colorVariants($this->getData(['admin', 'backgroundColorButtonGreen']));
$css .= '.button.buttonGreen, button[type=submit] {background-color: ' . $colors['normal'] . ';color: ' . $colors['text'] . ';}.button.buttonGreen:hover, button[type=submit]:hover {background-color: ' . $colors['darken'] . ';color: ' . $colors['text'] . ';}.button.buttonGreen:active, button[type=submit]:active {background-color: ' . $colors['darken'] . ';color: ' . $colors['text'] . ';}';
$colors = helper::colorVariants($this->getData(['admin', 'backgroundBlockColor']));
$css .= '.buttonTab, .block {border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . ';}.buttonTab, .block h4 {background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';}';
$css .= 'table tr,input[type=email],input[type=date],input[type=time],input[type=month],input[type=week],input[type=datetime-local],input[type=text],input[type=password],select:not(#barSelectLanguage),select:not(#barSelectPage),textarea:not(.editorWysiwyg), textarea:not(.editorWysiwygComment),.inputFile{background-color: ' . $colors['normal'] . ';color:' . $colors['text'] . ';border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . ';}';
// Bordure du contour TinyMCE
$css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}';
// Enregistre la personnalisation
$this->secure_file_put_contents(common::DATA_DIR . 'admin.css', $css);
}
}
/**
* Auto-chargement des classes
* @param string $className Nom de la classe à charger
*/
public static function autoload($className)
{
$classPath = strtolower($className) . '/' . strtolower($className) . '.php';
// Module du coeur
if (is_readable('core/module/' . $classPath)) {
require 'core/module/' . $classPath;
}
// Module
elseif (is_readable(common::MODULE_DIR . $classPath)) {
require common::MODULE_DIR . $classPath;
}
// Librairie
elseif (is_readable('core/vendor/' . $classPath)) {
require 'core/vendor/' . $classPath;
}
}
/**
* Routage des modules
*/
public function router()
{
$layout = new layout($this);
// Installation
if (
$this->getData(['user']) === []
and $this->getUrl(0) !== 'install'
) {
http_response_code(302);
header('Location:' . helper::baseUrl() . 'install');
exit();
}
// Journalisation
$this->saveLog();
// Force la déconnexion des membres bannis ou d'une seconde session
if (
$this->isConnected() === true
and ($this->getUser('group') === common::GROUP_BANNED
or ($_SESSION['csrf'] !== $this->getData(['user', $this->getUser('id'), 'accessCsrf'])
and $this->getData(['config', 'connect', 'autoDisconnect']) === true)
)
) {
$user = new user;
$user->logout();
}
// Mode maintenance
if (
$this->getData(['config', 'maintenance'])
and in_array($this->getUrl(0), ['maintenance', 'user']) === false
and $this->getUrl(1) !== 'login'
and ($this->isConnected() === false
or ($this->isConnected() === true
and $this->getUser('group') < common::GROUP_ADMIN
)
)
) {
// Déconnexion
$user = new user;
$user->logout();
// Redirection
http_response_code(302);
header('Location:' . helper::baseUrl() . 'maintenance');
exit();
}
// Check l'accès à la page
$access = null;
if ($this->getData(['page', $this->getUrl(0)]) !== null) {
if (
$this->getData(['page', $this->getUrl(0), 'group']) === common::GROUP_VISITOR
or ($this->isConnected() === true
// and $this->getUser('group') >= $this->getData(['page', $this->getUrl(0), 'group'])
// Modification qui tient compte du profil de la page
and ($this->getUser('group') * 10 + $this->getUser('profil')) >= ($this->getData(['page', $this->getUrl(0), 'group']) * 10 + $this->getData(['page', $this->getUrl(0), 'profil']))
)
) {
$access = true;
} else {
if ($this->getUrl(0) === $this->getData(['locale', 'homePageId'])) {
$access = 'login';
} else {
$access = false;
}
}
// Empêcher l'accès aux pages désactivées par URL directe
if (
($this->getData(['page', $this->getUrl(0), 'disable']) === true
and $this->isConnected() === false
) or ($this->getData(['page', $this->getUrl(0), 'disable']) === true
and $this->isConnected() === true
and $this->getUser('group') < common::GROUP_EDITOR
)
) {
$access = false;
}
// Lève une erreur si l'url est celle d'une page avec des éléments surnuméraires https://www.site.fr/page/truc
if (
array_key_exists($this->getUrl(0), $this->getData(['page']))
and $this->getUrl(1)
and $this->getData(['page', $this->getUrl(0), 'moduleId']) === ''
) {
$access = false;
}
}
/**
* Contrôle si la page demandée est en édition ou accès à la gestion du site
* conditions de blocage :
* - Les deux utilisateurs qui accèdent à la même page sont différents
* - les URLS sont identiques
* - Une partie de l'URL fait partie de la liste de filtrage (édition d'un module etc..)
* - L'édition est ouverte depuis un temps dépassé, on considère que la page est restée ouverte et qu'elle ne sera pas validée
*/
$accessInfo['userName'] = '';
$accessInfo['pageId'] = '';
if ($this->getData(['user'])) {
foreach ($this->getData(['user']) as $userId => $userIds) {
if (!is_null($this->getData(['user', $userId, 'accessUrl']))) {
$t = explode('/', $this->getData(['user', $userId, 'accessUrl']));
}
if (
$this->getUser('id') &&
$userId !== $this->getUser('id') &&
$this->getData(['user', $userId, 'accessUrl']) === $this->getUrl() &&
array_intersect($t, common::$concurrentAccess) &&
//array_intersect($t, common::$accessExclude) !== false &&
time() < $this->getData(['user', $userId, 'accessTimer']) + common::ACCESS_TIMER
) {
$access = false;
$accessInfo['userName'] = $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']);
$accessInfo['pageId'] = end($t);
}
}
}
// Accès concurrent stocke la page visitée
if (
$this->isConnected() === true
&& $this->getUser('id')
) {
$this->setData(['user', $this->getUser('id'), 'accessUrl', $this->getUrl()]);
$this->setData(['user', $this->getUser('id'), 'accessTimer', time()]);
}
// Breadcrumb
$title = $this->getData(['page', $this->getUrl(0), 'title']);
if (
!empty($this->getData(['page', $this->getUrl(0), 'parentPageId'])) &&
$this->getData(['page', $this->getUrl(0), 'breadCrumb'])
) {
$title = '<a href="' . helper::baseUrl() .
$this->getData(['page', $this->getUrl(0), 'parentPageId']) .
'">' .
ucfirst($this->getData(['page', $this->getData(['page', $this->getUrl(0), 'parentPageId']), 'title'])) .
'</a> &#8250; ' .
$this->getData(['page', $this->getUrl(0), 'title']);
}
// Importe le style de la page principale
$inlineStyle[] = $this->getData(['page', $this->getUrl(0), 'css']) === null ? '' : $this->getData(['page', $this->getUrl(0), 'css']);
// Importe le script de la page principale
$inlineScript[] = $this->getData(['page', $this->getUrl(0), 'js']) === null ? '' : $this->getData(['page', $this->getUrl(0), 'js']);
// Importe le contenu, le CSS et le script des barres
$contentRight = $this->getData(['page', $this->getUrl(0), 'barRight']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barRight']), common::$siteContent) : '';
$inlineStyle[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'css']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'css']);
$inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barRight']), 'js']);
$contentLeft = $this->getData(['page', $this->getUrl(0), 'barLeft']) ? $this->getPage($this->getData(['page', $this->getUrl(0), 'barLeft']), common::$siteContent) : '';
$inlineStyle[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'css']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'css']);
$inlineScript[] = $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']) === null ? '' : $this->getData(['page', $this->getData(['page', $this->getUrl(0), 'barLeft']), 'js']);
// Importe la page simple sans module ou avec un module inexistant
if (
$this->getData(['page', $this->getUrl(0)]) !== null
and ($this->getData(['page', $this->getUrl(0), 'moduleId']) === ''
or !class_exists($this->getData(['page', $this->getUrl(0), 'moduleId']))
)
and $access
) {
// Importe le CSS de la page principale
$this->addOutput([
'title' => $title,
'content' => $this->getPage($this->getUrl(0), common::$siteContent),
'metaDescription' => $this->getData(['page', $this->getUrl(0), 'metaDescription']),
'metaTitle' => $this->getData(['page', $this->getUrl(0), 'metaTitle']),
'typeMenu' => $this->getData(['page', $this->getUrl(0), 'typeMenu']),
'iconUrl' => $this->getData(['page', $this->getUrl(0), 'iconUrl']),
'disable' => $this->getData(['page', $this->getUrl(0), 'disable']),
'contentRight' => $contentRight,
'contentLeft' => $contentLeft,
'inlineStyle' => $inlineStyle,
'inlineScript' => $inlineScript,
]);
}
// Importe le module
else {
// Id du module, et valeurs en sortie de la page s'il s'agit d'un module de page
if ($access and $this->getData(['page', $this->getUrl(0), 'moduleId'])) {
$moduleId = $this->getData(['page', $this->getUrl(0), 'moduleId']);
// Construit un meta absent
$metaDescription = $this->getData(['page', $this->getUrl(0), 'moduleId']) === 'blog' && !empty($this->getUrl(1)) && in_array($this->getUrl(1), $this->getData(['module']))
? strip_tags(substr($this->getData(['module', $this->getUrl(0), 'posts', $this->getUrl(1), 'content']), 0, 159))
: $this->getData(['page', $this->getUrl(0), 'metaDescription']);
// Importe le CSS de la page principale
$pageContent = $this->getPage($this->getUrl(0), common::$siteContent);
$this->addOutput([
'title' => $title,
// Meta description = 160 premiers caractères de l'article
'content' => $pageContent,
'metaDescription' => $metaDescription,
'metaTitle' => $this->getData(['page', $this->getUrl(0), 'metaTitle']),
'typeMenu' => $this->getData(['page', $this->getUrl(0), 'typeMenu']),
'iconUrl' => $this->getData(['page', $this->getUrl(0), 'iconUrl']),
'disable' => $this->getData(['page', $this->getUrl(0), 'disable']),
'contentRight' => $contentRight,
'contentLeft' => $contentLeft,
'inlineStyle' => $inlineStyle,
'inlineScript' => $inlineScript,
]);
} else {
$moduleId = $this->getUrl(0);
$pageContent = '';
}
// Check l'existence du module
if (class_exists($moduleId)) {
/** @var common $module */
$module = new $moduleId;
// Check l'existence de l'action
$action = '';
$ignore = true;
if (!is_null($this->getUrl(1))) {
foreach (explode('-', $this->getUrl(1)) as $actionPart) {
if ($ignore) {
$action .= $actionPart;
$ignore = false;
} else {
$action .= ucfirst($actionPart);
}
}
}
$action = array_key_exists($action, $module::$actions) ? $action : 'index';
if (array_key_exists($action, $module::$actions)) {
$module->$action();
$output = $module->output;
// Check le groupe de l'utilisateur
if (
($module::$actions[$action] === common::GROUP_VISITOR
or ($this->isConnected() === true
and $this->getUser('group') >= $module::$actions[$action]
and $this->getUser('permission', $moduleId, $action)
)
)
and $output['access'] === true
) {
// Enregistrement du contenu de la méthode POST lorsqu'une notice est présente
if (common::$inputNotices) {
foreach ($_POST as $postId => $postValue) {
if (is_array($postValue)) {
foreach ($postValue as $subPostId => $subPostValue) {
common::$inputBefore[$postId . '_' . $subPostId] = $subPostValue;
}
} else {
common::$inputBefore[$postId] = $postValue;
}
}
}
// Sinon traitement des données de sortie qui requiert qu'aucune notice ne soit présente
else {
// Notification
if ($output['notification']) {
if ($output['state'] === true) {
$notification = 'ZWII_NOTIFICATION_SUCCESS';
} elseif ($output['state'] === false) {
$notification = 'ZWII_NOTIFICATION_ERROR';
} else {
$notification = 'ZWII_NOTIFICATION_OTHER';
}
$_SESSION[$notification] = $output['notification'];
}
// Redirection
if ($output['redirect']) {
http_response_code(301);
header('Location:' . $output['redirect']);
exit();
}
}
// Données en sortie applicables même lorsqu'une notice est présente
// Affichage
if ($output['display']) {
$this->addOutput([
'display' => $output['display']
]);
}
// Contenu brut
if ($output['content']) {
$this->addOutput([
'content' => $output['content']
]);
}
// Contenu par vue
elseif ($output['view']) {
// Chemin en fonction d'un module du coeur ou d'un module
$modulePath = in_array($moduleId, common::$coreModuleIds) ? 'core/' : '';
// CSS
$stylePath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.css';
if (file_exists($stylePath)) {
$this->addOutput([
'style' => file_get_contents($stylePath)
]);
}
if ($output['style']) {
$this->addOutput([
'style' => file_get_contents($output['style'])
]);
}
// JS
$scriptPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.js.php';
if (file_exists($scriptPath)) {
ob_start();
include $scriptPath;
$this->addOutput([
'script' => ob_get_clean()
]);
}
// Vue
$viewPath = $modulePath . common::MODULE_DIR . $moduleId . '/view/' . $output['view'] . '/' . $output['view'] . '.php';
if (file_exists($viewPath)) {
ob_start();
include $viewPath;
$modpos = $this->getData(['page', $this->getUrl(0), 'modulePosition']);
if ($modpos === 'top') {
$this->addOutput([
'content' => ob_get_clean() . ($output['showPageContent'] ? $pageContent : '')
]);
} elseif ($modpos === 'free' && strstr($pageContent, '[MODULE]')) {
if (strstr($pageContent, '[MODULE]', true) === false) {
$begin = strstr($pageContent, '[]', true);
} else {
$begin = strstr($pageContent, '[MODULE]', true);
}
if (strstr($pageContent, '[MODULE]') === false) {
$end = strstr($pageContent, '[]');
} else {
$end = strstr($pageContent, '[MODULE]');
}
$cut = 8;
$end = substr($end, -strlen($end) + $cut);
$this->addOutput([
'content' => ($output['showPageContent'] ? $begin : '') . ob_get_clean() . ($output['showPageContent'] ? $end : '')
]);
} else {
$this->addOutput([
'content' => ($output['showPageContent'] ? $pageContent : '') . ob_get_clean()
]);
}
}
}
// Librairies
if ($output['vendor'] !== $this->output['vendor']) {
$this->addOutput([
'vendor' => array_merge($this->output['vendor'], $output['vendor'])
]);
}
if ($output['title'] !== null) {
$this->addOutput([
'title' => $output['title']
]);
}
// Affiche le bouton d'édition de la page dans la barre de membre
if ($output['showBarEditButton']) {
$this->addOutput([
'showBarEditButton' => $output['showBarEditButton']
]);
}
}
// Erreur 403
else {
$access = false;
}
}
}
}
// Erreurs
if ($access === 'login') {
http_response_code(302);
header('Location:' . helper::baseUrl() . 'user/login/');
exit();
}
if ($access === false) {
http_response_code(403);
if ($accessInfo['userName']) {
$this->addOutput([
'title' => 'Accès verrouillé',
'content' => template::speech('<p>' . sprintf(helper::translate('La page %s est ouverte par l\'utilisateur %s</p><p><a style="color:inherit" href="javascript:history.back()">%s</a></p>'), $accessInfo['pageId'], $accessInfo['userName'], helper::translate('Retour')))
]);
} else {
if (
$this->getData(['locale', 'page403']) !== 'none'
and $this->getData(['page', $this->getData(['locale', 'page403'])])
) {
header('Location:' . helper::baseUrl() . $this->getData(['locale', 'page403']));
} else {
$this->addOutput([
'title' => 'Accès interdit',
'content' => template::speech('<p>' . helper::translate('Vous n\'êtes pas autorisé à consulter cette page (erreur 403)') . '</p><p><a style="color:inherit" href="javascript:history.back()">' . helper::translate('Retour') . '</a></p>')
]);
}
}
} elseif ($this->output['content'] === '') {
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 (
$this->getData(['locale', 'page404']) !== 'none'
and $this->getData(['page', $this->getData(['locale', 'page404'])])
) {
header('Location:' . helper::baseUrl() . $this->getData(['locale', 'page404']));
} else {
$this->addOutput([
'title' => 'Page indisponible',
'content' => template::speech('<p>' . helper::translate('La page demandée n\'existe pas ou est introuvable (erreur 404)') . '</p><p><a style="color:inherit" href="javascript:history.back()">' . helper::translate('Retour') . '</a></p>')
]);
}
}
// Mise en forme des métas
if ($this->output['metaTitle'] === '') {
if ($this->output['title']) {
$this->addOutput([
'metaTitle' => strip_tags($this->output['title']) . ' - ' . $this->getData(['locale', 'title'])
]);
} else {
$this->addOutput([
'metaTitle' => $this->getData(['locale', 'title'])
]);
}
}
if ($this->output['metaDescription'] === '') {
$this->addOutput([
'metaDescription' => $this->getData(['locale', 'metaDescription'])
]);
}
switch ($this->output['display']) {
// Layout brut
case common::DISPLAY_RAW:
echo $this->output['content'];
break;
// Layout vide
case common::DISPLAY_LAYOUT_BLANK:
require 'core/layout/blank.php';
break;
// Affichage en JSON
case common::DISPLAY_JSON:
header('Content-Type: application/json');
echo json_encode($this->output['content']);
break;
// RSS feed
case common::DISPLAY_RSS:
header('Content-type: application/rss+xml; charset=UTF-8');
echo $this->output['content'];
break;
// Layout allégé
case common::DISPLAY_LAYOUT_LIGHT:
ob_start();
require 'core/layout/light.php';
$content = ob_get_clean();
// Convertit la chaîne en UTF-8 pour conserver les caractères accentués
$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;
break;
// Layout principal
case common::DISPLAY_LAYOUT_MAIN:
ob_start();
require 'core/layout/main.php';
$content = ob_get_clean();
// Convertit la chaîne en UTF-8 pour conserver les caractères accentués
$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;
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

@ -28,7 +28,7 @@ class template
$attributes['value'] = helper::translate($attributes['value']); $attributes['value'] = helper::translate($attributes['value']);
$attributes['help'] = helper::translate($attributes['help']); $attributes['help'] = helper::translate($attributes['help']);
// Retourne le html // Retourne le html
return sprintf( return sprintf(
'<a %s class="button %s %s %s" %s>%s</a>', '<a %s class="button %s %s %s" %s>%s</a>',
helper::sprintAttributes($attributes, ['class', 'disabled', 'ico', 'value']), helper::sprintAttributes($attributes, ['class', 'disabled', 'ico', 'value']),
$attributes['disabled'] ? 'disabled' : '', $attributes['disabled'] ? 'disabled' : '',
@ -65,12 +65,12 @@ class template
// Limite addition et soustraction selon le type de captcha // Limite addition et soustraction selon le type de captcha
$numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20]; $numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20];
$letters = ['u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']; $letters = ['u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a'];
$limit = $attributes['limit'] ? count($letters) - 1 : 10; $limit = $attributes['limit'] ? count($letters) - 1 : 10;
// Tirage de l'opération // Tirage de l'opération
mt_srand((float) microtime() * 1000000); mt_srand();
// Captcha simple limité à l'addition // Captcha simple limité à l'addition
$operator = $attributes['limit'] ? mt_rand(1, 4) : 1; $operator = $attributes['limit'] ? mt_rand(1, 4) : 1;
// Limite si multiplication ou division // Limite si multiplication ou division
if ($operator > 2) { if ($operator > 2) {
@ -78,9 +78,9 @@ class template
} }
// Tirage des nombres // Tirage des nombres
mt_srand( microtime(true) * 1000000); mt_srand();
$firstNumber = mt_rand(1, $limit); $firstNumber = mt_rand(1, $limit);
mt_srand( microtime(true) * 1000000); mt_srand();
$secondNumber = mt_rand(1, $limit); $secondNumber = mt_rand(1, $limit);
// Permutation si addition ou soustraction // Permutation si addition ou soustraction
@ -93,26 +93,26 @@ 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];
} }
mt_srand((float) microtime() * 1000000); mt_srand();
$secondNumber = mt_rand(1, $limit); $secondNumber = mt_rand(1, $limit);
$firstNumber = $firstNumber * $secondNumber; $firstNumber = $firstNumber * $secondNumber;
$result = $firstNumber / $secondNumber; $result = $firstNumber / $secondNumber;
break; break;
} }
@ -125,8 +125,8 @@ class template
$secondLetter = uniqid(); $secondLetter = uniqid();
// Masquage image source pour éviter un décodage // Masquage image source pour éviter un décodage
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$firstNumber] . '.png', 'site/tmp/' . $firstLetter . '.png'); copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$firstNumber] . '.png', 'site/tmp/' . $firstLetter . '.png');
copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$secondNumber] . '.png', 'site/tmp/' . $secondLetter . '.png'); copy('core/vendor/zwiico/png/' . $attributes['type'] . '/' . $letters[$secondNumber] . '.png', 'site/tmp/' . $secondLetter . '.png');
// Début du wrapper // Début du wrapper
@ -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,6 +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 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 = [])
@ -241,18 +242,34 @@ class template
'label' => '', 'label' => '',
'name' => $nameId, 'name' => $nameId,
'placeholder' => '', 'placeholder' => '',
'readonly' => true, 'readonly' => false,
'value' => '' 'value' => '',
'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'] . '">';
@ -272,15 +289,11 @@ class template
// Date visible // Date visible
$html .= '<div class="inputDateManagerWrapper">'; $html .= '<div class="inputDateManagerWrapper">';
$html .= sprintf( $html .= sprintf(
'<input type="text" class="datepicker %s" value="%s" %s>', '<input type="' . $attributes['type'] . '" class="datepicker %s" value="%s" %s>',
$attributes['class'], $attributes['class'],
$attributes['value'], $attributes['value'],
helper::sprintAttributes($attributes, ['class', 'value']) helper::sprintAttributes($attributes, ['class', 'value'])
); );
$html .= self::button($attributes['id'] . 'Delete', [
'class' => 'inputDateDelete',
'value' => self::ico('cancel')
]);
$html .= '</div>'; $html .= '</div>';
// Fin du wrapper // Fin du wrapper
$html .= '</div>'; $html .= '</div>';
@ -288,6 +301,7 @@ class template
return $html; return $html;
} }
/** /**
* Crée un champ d'upload de fichier * Crée un champ d'upload de fichier
* @param string $nameId Nom et id du champ * @param string $nameId Nom et id du champ
@ -311,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
@ -347,19 +362,21 @@ class template
$html .= sprintf( $html .= sprintf(
'<a '<a
href="' . href="' .
helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php' . helper::baseUrl(false) . 'core/vendor/filemanager/dialog.php' .
'?relative_url=1' . '?relative_url=1' .
'&lang=' . $attributes['language'] . '&lang=' . $attributes['language'] .
'&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') .
($attributes['extensions'] ? '&extensions=' . $attributes['extensions'] : '') // Ajoute le nom du dossier si la variable est passée
. '" (!empty($attributes['folder']) ? '&fldr=' . $attributes['folder'] : '') .
($attributes['extensions'] ? '&extensions=' . $attributes['extensions'] : '')
. '"
class="inputFile %s %s" 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'],
@ -398,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;
@ -468,12 +485,12 @@ class template
'attr' => '', 'attr' => '',
'help' => '', 'help' => '',
'id' => '', 'id' => '',
'alt' => '',
], $attributes); ], $attributes);
// Traduction de l'aide // Traduction de l'aide
$attributes['help'] = helper::translate($attributes['help']); $attributes['help'] = helper::translate($attributes['help']);
// Contenu de l'icône // Contenu de l'icône
$item = $attributes['href'] ? '<a id="' . $attributes['id'] . '" data-tippy-content="' . $attributes['help'] . '" alt="' . $attributes['help'] . '" href="' . $attributes['href'] . '" ' . $attributes['attr'] . ' >' : ''; $alt = $attributes['help'] ? $attributes['help'] : $ico;
$item = $attributes['href'] ? '<a id="' . $attributes['id'] . '" data-tippy-content="' . $attributes['help'] . '" alt="' . $alt . '" href="' . $attributes['href'] . '" ' . $attributes['attr'] . ' >' : '';
$item .= '<span class="zwiico-' . $ico . ($attributes['margin'] ? ' zwiico-margin-' . $attributes['margin'] : '') . ($attributes['animate'] ? ' animate-spin' : '') . '" style="font-size:' . $attributes['fontSize'] . '"><!----></span>'; $item .= '<span class="zwiico-' . $ico . ($attributes['margin'] ? ' zwiico-margin-' . $attributes['margin'] : '') . ($attributes['animate'] ? ' animate-spin' : '') . '" style="font-size:' . $attributes['fontSize'] . '"><!----></span>';
$item .= ($attributes['href']) ? '</a>' : ''; $item .= ($attributes['href']) ? '</a>' : '';
return $item; return $item;
@ -495,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';
} }
@ -523,8 +540,10 @@ class template
'for' => $for, 'for' => $for,
'help' => '' 'help' => ''
], $attributes); ], $attributes);
// Traduction de l'étiquette si déjà appelée par une fonction de template // Traduction de l'aide et de l'étiquette
; $text = helper::translate($text);
$attributes['help'] = helper::translate($attributes['help']);
if ( if (
get_called_class() !== 'template' get_called_class() !== 'template'
) { ) {
@ -685,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)) {
@ -714,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>',
@ -721,7 +746,7 @@ class template
); );
foreach ($options as $value => $text) { foreach ($options as $value => $text) {
// Select des liste de fontes // Select des liste de fontes
$html .= isset($fonts) ? sprintf( $html .= isset($fonts) ? sprintf(
'<option value="%s"%s style="font-family: %s;">%s</option>', '<option value="%s"%s style="font-family: %s;">%s</option>',
$value, $value,
$attributes['selected'] == $value ? ' selected' : '', // Double == pour ignorer le type de variable car $_POST change les types en string $attributes['selected'] == $value ? ' selected' : '', // Double == pour ignorer le type de variable car $_POST change les types en string
@ -732,7 +757,7 @@ class template
'<option value="%s"%s>%s</option>', '<option value="%s"%s>%s</option>',
$value, $value,
$attributes['selected'] == $value ? ' selected' : '', // Double == pour ignorer le type de variable car $_POST change les types en string $attributes['selected'] == $value ? ' selected' : '', // Double == pour ignorer le type de variable car $_POST change les types en string
$text helper::translate($text)
); );
} }
// Fin sélection // Fin sélection
@ -743,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
@ -750,7 +776,7 @@ class template
*/ */
public static function speech($text) public static function speech($text)
{ {
return '<div class="speech"><div class="speechBubble">' . $text . '</div>' . template::ico('mimi speechMimi', ['fontSize' => '7em']) . '</div>'; return '<div class="speech"><div class="speechBubble">' . helper::translate($text) . '</div>' . template::ico('mimi speechMimi', ['fontSize' => '7em']) . '</div>';
} }
/** /**
@ -774,7 +800,7 @@ class template
// Traduction de l'aide et de l'étiquette // Traduction de l'aide et de l'étiquette
$attributes['value'] = helper::translate($attributes['value']); $attributes['value'] = helper::translate($attributes['value']);
// Retourne le html // Retourne le html
return sprintf( return sprintf(
'<button type="submit" class="%s%s" %s>%s</button>', '<button type="submit" class="%s%s" %s>%s</button>',
$attributes['class'], $attributes['class'],
$attributes['uniqueSubmission'] ? 'uniqueSubmission' : '', $attributes['uniqueSubmission'] ? 'uniqueSubmission' : '',
@ -802,7 +828,7 @@ class template
], $attributes); ], $attributes);
// Traduction de l'aide et de l'étiquette // Traduction de l'aide et de l'étiquette
foreach ($head as $value) { foreach ($head as $value) {
$head[array_search($value, $head)] = helper::translate($value); $head[array_search($value, $head)] = helper::translate($value);
} }
// Début du wrapper // Début du wrapper
$html = '<div id="' . $attributes['id'] . 'Wrapper" class="tableWrapper ' . $attributes['classWrapper'] . '">'; $html = '<div id="' . $attributes['id'] . 'Wrapper" class="tableWrapper ' . $attributes['classWrapper'] . '">';
@ -869,7 +895,8 @@ class template
'name' => $nameId, 'name' => $nameId,
'placeholder' => '', 'placeholder' => '',
'readonly' => false, 'readonly' => false,
'value' => '' 'value' => '',
'type' => 'text'
], $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']);
@ -896,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="text" %s>', '<input type="' . $attributes['type'] . '" %s>',
helper::sprintAttributes($attributes) helper::sprintAttributes($attributes)
); );
// Fin du wrapper // Fin du wrapper

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

56
core/include/checkup.php Normal file
View File

@ -0,0 +1,56 @@
<?php
/**
* Vérification de la version de PHP
*/
if(version_compare(PHP_VERSION, '7.2.0', '<') ) {
exit('PHP 7.2+ mini requis - PHP 7.2+ mini required');
}
if ( version_compare(PHP_VERSION, '8.3.999', '>') ) {
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');
}
/**
* Check les modules installés
*/
$e = [
'gd',
'json',
'date',
'mbstring',
'zip',
'intl',
'exif',
'Phar',
'fileinfo',
'session'
];
$m = get_loaded_extensions();
$b = false;
foreach ($e as $k => $v) {
if (array_search($v,$m) === false) {
$b = true;
echo '<pre><p>Module PHP : ' . $v . ' manquant - Module PHP ' . $v . ' missing.</p></pre>';
}
}
if ($b)
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
*/
$d = [
'',
'site/data/',
'site/backup/',
'site/tmp/',
// 'site/i18n/', pas contrôler pour éviter les pbs de mise à jour
];
foreach ($d as $key) {
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.</pre>' );
}

View File

@ -0,0 +1,52 @@
<?php
/**
* Mise à jour avant v12
* */
if (file_exists('site/data/core.json')) {
$core = json_decode(file_get_contents('site/data/core.json'), true);
$version = $core['core']['dataVersion'];
// Avant version 12.0.00
if (
$version < 12000
) {
// Correspondance pour les dossiers de langue à convertir
$languages = [
'fr' => 'fr_FR',
'en' => 'en_EN',
'pt' => 'pt_PT'
];
// Convertit les dossiers vers la nouvelle structure
foreach ($languages as $key => $value) {
if (
is_dir('site/data/' . $key) &&
!is_dir('site/data/' . $value)
) {
$end = rename('site/data/' . $key, 'site/data/' . $value);
}
}
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,19 +18,19 @@ 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
$tempData = $this->getData(['module', $parent]); $tempData = $this->getData(['module', $parent]);
$i = 1; $i = 1;
foreach ($tempData as $galleryKey => $galleryItem) { foreach ($tempData as $galleryKey => $galleryItem) {
// Ordre de tri des galeries // Ordre de tri des galeries
@ -58,7 +62,7 @@ if ($this->getData(['core', 'dataVersion']) < 10000) {
} }
} }
// Contrôle des options php.ini pour la mise à jour auto // Contrôle des options php.ini pour la mise à jour auto
if (helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/version') === false) { if (helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/version') === false) {
$this->setData(['config', 'autoUpdate', false]); $this->setData(['config', 'autoUpdate', false]);
} }
@ -71,7 +75,8 @@ if ($this->getData(['core', 'dataVersion']) < 10092) {
$dir = getcwd(); $dir = getcwd();
chdir('core/vendor/fullpage'); chdir('core/vendor/fullpage');
$files = glob('*'); $files = glob('*');
foreach ($files as $file) unlink($file); foreach ($files as $file)
unlink($file);
chdir($dir); chdir($dir);
rmdir('core/vendor/fullpage/'); rmdir('core/vendor/fullpage/');
} }
@ -130,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
@ -163,7 +168,8 @@ if ($this->getData(['core', 'dataVersion']) < 10300) {
$dir = getcwd(); $dir = getcwd();
chdir('core/module/search'); chdir('core/module/search');
$files = glob('*'); $files = glob('*');
foreach ($files as $file) unlink($file); foreach ($files as $file)
unlink($file);
chdir($dir); chdir($dir);
rmdir('core/module/search/'); rmdir('core/module/search/');
} }
@ -173,16 +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(); $hierarchy = array(); foreach ($this->getHierarchy() as $parentKey => $parentValue) {
foreach ($this->getHierarchy(null, null, null) as $parentKey => $parentValue) { $hierarchy[] = $parentKey;
$pageList[] = $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) {
@ -234,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]))) {
@ -257,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]))) {
@ -292,37 +297,37 @@ 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'));
foreach ($articleIds as $key => $article) { foreach ($articleIds as $key => $article) {
// Droits les deux groupes // Droits les deux groupes
$this->setData(['module', $parent, 'posts', $article, 'editConsent', 3]); $this->setData(['module', $parent, 'posts', $article, 'editConsent', 3]);
// Limite de taille 500 // Limite de taille 500
$this->setData(['module', $parent, 'posts', $article, 'commentMaxlength', '500']); $this->setData(['module', $parent, 'posts', $article, 'commentMaxlength', '500']);
// Pas d'approbation des commentaires // Pas d'approbation des commentaires
$this->setData(['module', $parent, 'posts', $article, 'commentApproved', false]); $this->setData(['module', $parent, 'posts', $article, 'commentApproved', false]);
// pas de notification // pas de notification
$this->setData(['module', $parent, 'posts', $article, 'commentNotification', false]); $this->setData(['module', $parent, 'posts', $article, 'commentNotification', false]);
// groupe de notification // groupe de notification
$this->setData(['module', $parent, 'posts', $article, 'commentGroupNotification', 3]); $this->setData(['module', $parent, 'posts', $article, 'commentGroupNotification', 3]);
} }
// Traitement des commentaires // Traitement des commentaires
if (is_array($this->getData(['module', $parent, 'posts', $article, 'comment']))) { if (is_array($this->getData(['module', $parent, 'posts', $article, 'comment']))) {
foreach ($this->getData(['module', $parent, 'posts', $article, 'comment']) as $commentId => $comment) { foreach ($this->getData(['module', $parent, 'posts', $article, 'comment']) as $commentId => $comment) {
// Approbation // Approbation
$this->setData(['module', $parent, 'posts', $article, 'comment', $commentId, 'approval', true]); $this->setData(['module', $parent, 'posts', $article, 'comment', $commentId, 'approval', true]);
} }
} }
} }
@ -383,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'
@ -430,7 +435,8 @@ if ($this->getData(['core', 'dataVersion']) < 11000) {
$this->setData(['config', 'i18n', 'pt', 'none']); $this->setData(['config', 'i18n', 'pt', 'none']);
// Supprimer les fichiers de backup // Supprimer les fichiers de backup
if (file_exists('site/data/.backup')) unlink('site/data/.backup'); if (file_exists('site/data/.backup'))
unlink('site/data/.backup');
$path = realpath('site/data'); $path = realpath('site/data');
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) { foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
if (strpos($filename, 'backup.json')) { if (strpos($filename, 'backup.json')) {
@ -440,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']);
} }
@ -503,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'])]);
} }
@ -521,7 +527,7 @@ if ($this->getData(['core', 'dataVersion']) < 11200) {
// Option des cookies dans le footer // Option des cookies dans le footer
$this->setData(['theme', 'footer', 'displayCookie', false]); $this->setData(['theme', 'footer', 'displayCookie', false]);
// Acceptation et paramétres des cookies RGPD // Acceptation et Paramètres des cookies RGPD
$this->setData(['locale', 'cookies', 'cookiesZwiiText', '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.']); $this->setData(['locale', 'cookies', 'cookiesZwiiText', '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.']);
$this->setData(['locale', 'cookies', 'cookiesTitleText', 'Gérer les cookies']); $this->setData(['locale', 'cookies', 'cookiesTitleText', 'Gérer les cookies']);
$this->setData(['locale', 'cookies', 'cookiesLinkMlText', 'Consulter les mentions légales']); $this->setData(['locale', 'cookies', 'cookiesLinkMlText', 'Consulter les mentions légales']);
@ -541,10 +547,10 @@ if ($this->getData(['core', 'dataVersion']) < 11200) {
if ($this->getData(['core', 'dataVersion']) < 11202) { if ($this->getData(['core', 'dataVersion']) < 11202) {
// Renommer les champs // Renommer les champs
$this->setData(['locale', 'cookies', 'mainLabel', $this->getData(['locale', 'cookies', 'cookiesZwiiText'])]); $this->setData(['locale', 'cookies', 'mainLabel', $this->getData(['locale', 'cookies', 'cookiesZwiiText'])]);
$this->setData(['locale', 'cookies', 'gaLabel', $this->getData(['locale', 'cookies', 'cookiesGaText'])]); $this->setData(['locale', 'cookies', 'gaLabel', $this->getData(['locale', 'cookies', 'cookiesGaText'])]);
$this->setData(['locale', 'cookies', 'titleLabel', $this->getData(['locale', 'cookies', 'cookiesTitleText'])]); $this->setData(['locale', 'cookies', 'titleLabel', $this->getData(['locale', 'cookies', 'cookiesTitleText'])]);
$this->setData(['locale', 'cookies', 'linkLegalLabel', $this->getData(['locale', 'cookies', 'cookiesLinkMlText'])]); $this->setData(['locale', 'cookies', 'linkLegalLabel', $this->getData(['locale', 'cookies', 'cookiesLinkMlText'])]);
$this->setData(['locale', 'cookies', 'checkboxGaLabel', $this->getData(['locale', 'cookies', 'cookiesCheckboxGaText'])]); $this->setData(['locale', 'cookies', 'checkboxGaLabel', $this->getData(['locale', 'cookies', 'cookiesCheckboxGaText'])]);
$this->setData(['locale', 'cookies', 'buttonValidLabel', $this->getData(['locale', 'cookies', 'cookiesButtonText'])]); $this->setData(['locale', 'cookies', 'buttonValidLabel', $this->getData(['locale', 'cookies', 'cookiesButtonText'])]);
// Effacer les anciens champs // Effacer les anciens champs
@ -567,26 +573,26 @@ 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);
$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($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;
} }
} }
@ -646,11 +652,11 @@ if ($this->getData(['core', 'dataVersion']) < 11300) {
$this->setData(['theme', 'footer', 'font', $fonts[$this->getData(['theme', 'footer', 'font'])]]); $this->setData(['theme', 'footer', 'font', $fonts[$this->getData(['theme', 'footer', 'font'])]]);
$this->setData(['theme', 'header', 'font', $fonts[$this->getData(['theme', 'header', 'font'])]]); $this->setData(['theme', 'header', 'font', $fonts[$this->getData(['theme', 'header', 'font'])]]);
$this->setData(['theme', 'menu', 'font', $fonts[$this->getData(['theme', 'menu', 'font'])]]); $this->setData(['theme', 'menu', 'font', $fonts[$this->getData(['theme', 'menu', 'font'])]]);
$this->setData(['theme', 'text', 'font', $fonts[$this->getData(['theme', 'text', 'font'])]]); $this->setData(['theme', 'text', 'font', $fonts[$this->getData(['theme', 'text', 'font'])]]);
$this->setData(['theme', 'title', 'font', $fonts[$this->getData(['theme', 'title', 'font'])]]); $this->setData(['theme', 'title', 'font', $fonts[$this->getData(['theme', 'title', 'font'])]]);
$this->setData(['admin', 'fontTitle', $fonts[$this->getData(['admin', 'fontTitle'])]]); $this->setData(['admin', 'fontTitle', $fonts[$this->getData(['admin', 'fontTitle'])]]);
$this->setData(['admin', 'fontText', $fonts[$this->getData(['admin', 'fontText'])]]); $this->setData(['admin', 'fontText', $fonts[$this->getData(['admin', 'fontText'])]]);
unlink(self::DATA_DIR . 'admin.css'); unlink(self::DATA_DIR . 'admin.css');
unlink(self::DATA_DIR . 'theme.css'); unlink(self::DATA_DIR . 'theme.css');
@ -663,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]);
} }
@ -682,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
@ -697,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');
} }
@ -714,12 +720,12 @@ if ($this->getData(['core', 'dataVersion']) < 11400) {
], ],
'droid-sans-2' => [ 'droid-sans-2' => [
'name' => 'Droid Sans', 'name' => 'Droid Sans',
'font-family' => '\'Droid Sans\', sans-serif', 'font-family' => '\'Droid Sans\', sans-serif',
'resource' => 'https://fonts.cdnfonts.com/css/droid-sans-2' 'resource' => 'https://fonts.cdnfonts.com/css/droid-sans-2'
], ],
'droid-serif-2' => [ 'droid-serif-2' => [
'name' => 'Droid Serif', 'name' => 'Droid Serif',
'font-family' => '\'Droid Serif\', serif', 'font-family' => '\'Droid Serif\', serif',
'resource' => 'https://fonts.cdnfonts.com/css/droid-serif-2' 'resource' => 'https://fonts.cdnfonts.com/css/droid-serif-2'
], ],
'indie-flower' => [ 'indie-flower' => [
@ -795,39 +801,51 @@ 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 (
gettype($fontName) === 'string' gettype($fontName) === 'string'
&& file_exists(self::DATA_DIR . 'fonts/' . $fontName) && file_exists(self::DATA_DIR . 'fonts/' . $fontName)
) { ) {
$this->setData(['fonts', 'files', $fontId, [ $this->setData([
'name' => ucfirst($fontId), 'font',
'font-family' => '\'' . ucfirst($fontId) . '\', sans-serif', 'files',
'resource' => $fontName $fontId,
]]); [
'name' => ucfirst($fontId),
'font-family' => '\'' . ucfirst($fontId) . '\', sans-serif',
'resource' => $fontName
]
]);
} }
} }
} }
// 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(['fonts', 'imported', $fontId, [ $this->setData([
'name' => ucfirst($fontId), 'font',
'font-family' => '\'' . ucfirst($fontId) . '\', sans-serif', 'imported',
'resource' => 'https:\\fonts.cdnfonts.com\css' . $fontUrl $fontId,
]]); [
'name' => ucfirst($fontId),
'font-family' => '\'' . ucfirst($fontId) . '\', sans-serif',
'resource' => 'https:\\fonts.cdnfonts.com\css' . $fontUrl
]
]);
} }
} }
} }
// 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
@ -879,16 +897,16 @@ if ($this->getData(['core', 'dataVersion']) < 12000) {
helper::deleteCookie('ZWII_CONTENTSCRIPT'); helper::deleteCookie('ZWII_CONTENTSCRIPT');
// Nettoyage de fichiers inutiles // Nettoyage de fichiers inutiles
if (file_exists('core\module\user\view\import\import.help.html')) { if (file_exists('core/module/user/view/import/import.help.html')) {
unlink('core\module\user\view\import\import.help.html'); unlink('core/module/user/view/import/import.help.html');
} }
// 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');
@ -901,7 +919,7 @@ if ($this->getData(['core', 'dataVersion']) < 12000) {
} }
// Copier les fichiers de l'interface // Copier les fichiers de l'interface
if (!is_dir(self::I18N_DIR)) { if (!is_dir(self::I18N_DIR)) {
// Créer le d$ossier // Créer le dossier
$this->copyDir('core/module/install/ressource/i18n', self::I18N_DIR); $this->copyDir('core/module/install/ressource/i18n', self::I18N_DIR);
} }
// Langue de l'interface // Langue de l'interface
@ -914,3 +932,187 @@ if ($this->getData(['core', 'dataVersion']) < 12000) {
// Mise à jour // Mise à jour
$this->setData(['core', 'dataVersion', 12000]); $this->setData(['core', 'dataVersion', 12000]);
} }
// Version 12.3.01
if ($this->getData(['core', 'dataVersion']) < 12301) {
// Valeur par défaut du délai de recherche de mise à jour en ligne
$this->setData(['config', 'autoUpdateDelay', 86400]);
// Nettoyage de flatPickr
if (is_dir('core/vendor/flatpickr')) {
$this->deleteDir('core/vendor/flatpickr');
}
// email reply
$this->deleteData(['config', 'smtp', 'sender']);
$this->setData(['config', 'smtp', 'from', 'no-reply@' . str_replace('www.', '', $_SERVER['HTTP_HOST'])]);
// Mise à jour
$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,8 +6,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */

View File

@ -1,22 +1,27 @@
<!DOCTYPE html> <!DOCTYPE html>
<html prefix="og: http://ogp.me/ns#" lang="<?php echo self::$i18nContent;?>"> <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 name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<?php $this->showMetaTitle(); ?> <?php $layout->showMetaTitle(); ?>
<?php $this->showMetaDescription(); ?> <?php $layout->showMetaDescription(); ?>
<?php $this->showMetaType(); ?> <?php $layout->showMetaType(); ?>
<?php $this->showMetaImage(); ?> <?php $layout->showMetaImage(); ?>
<?php $this->showFavicon(); ?> <?php $layout->showFavicon(); ?>
<?php $this->showVendor(); ?> <?php $layout->showVendor(); ?>
<?php $this->showStyle(); ?> <?php $layout->showStyle(); ?>
<?php $layout->showFonts(); ?>
<?php if (file_exists(self::DATA_DIR . 'font/font.css')): ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>font/font.css?<?php echo md5_file(self::DATA_DIR . 'font/font.css'); ?>">
<?php endif; ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/common.css"> <link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/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'); ?>">
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>custom.css?<?php echo md5_file(self::DATA_DIR.'custom.css'); ?>"> <link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>custom.css?<?php echo md5_file(self::DATA_DIR.'custom.css'); ?>">
</head> </head>
<body> <body>
<?php $this->showContent(); ?> <?php $layout->showContent(); ?>
<?php $this->showScript(); ?> <?php $layout->showScript(); ?>
</body> </body>
</html> </html>

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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,25 +1,30 @@
<!DOCTYPE html> <!DOCTYPE html>
<html prefix="og: http://ogp.me/ns#" lang="<?php echo self::$i18nContent;?>"> <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 name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<?php $this->showMetaTitle(); ?> <?php $layout->showMetaTitle(); ?>
<?php $this->showMetaDescription(); ?> <?php $layout->showMetaDescription(); ?>
<?php $this->showMetaType(); ?> <?php $layout->showMetaType(); ?>
<?php $this->showMetaImage(); ?> <?php $layout->showMetaImage(); ?>
<?php $this->showFavicon(); ?> <?php $layout->showFavicon(); ?>
<?php $this->showVendor(); ?> <?php $layout->showVendor(); ?>
<?php $this->showStyle(); ?> <?php $layout->showStyle(); ?>
<?php $layout->showFonts(); ?>
<?php if (file_exists(self::DATA_DIR . 'font/font.css')): ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>font/font.css?<?php echo md5_file(self::DATA_DIR . 'font/font.css'); ?>">
<?php endif; ?>
<link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/common.css"> <link rel="stylesheet" href="<?php echo helper::baseUrl(false); ?>core/layout/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'); ?>">
<link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>custom.css?<?php echo md5_file(self::DATA_DIR.'custom.css'); ?>"> <link rel="stylesheet" href="<?php echo helper::baseUrl(false) . self::DATA_DIR; ?>custom.css?<?php echo md5_file(self::DATA_DIR.'custom.css'); ?>">
</head> </head>
<body> <body>
<?php $this->showNotification(); ?> <?php $layout->showNotification(); ?>
<div id="site" class="container light"> <div id="site" class="container light">
<section><?php $this->showContent(); ?></section> <section><?php $layout->showContent(); ?></section>
</div> </div>
<?php $this->showScript(); ?> <?php $layout->showScript(); ?>
</body> </body>
</html> </html>

View File

@ -1,7 +1,8 @@
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr"> <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 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,196 +1,217 @@
<!DOCTYPE html> <!DOCTYPE html>
<html prefix="og: http://ogp.me/ns#" lang="<?php echo self::$i18nContent;?>"> <html prefix="og: http://ogp.me/ns#" lang="<?php echo substr(self::$siteContent, 0, 2); ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php $this->showMetaTitle(); ?>
<?php $this->showMetaDescription(); ?>
<?php $this->showMetaType(); ?>
<?php $this->showMetaImage(); ?>
<?php $this->showFavicon(); ?>
<?php $this->showVendor(); ?>
<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 --> <head>
<?php if ( ( $this->getData(['page', $this->getUrl(0), 'moduleId']) === 'blog' <meta charset="UTF-8">
OR $this->getData(['page', $this->getUrl(0), 'moduleId']) === 'news' ) <meta http-equiv="content-type" content="text/html; charset=UTF-8">
AND $this->getData(['module', $this->getUrl(0), 'config', 'feeds']) === TRUE ): ?> <meta meta="description=" content="ZwiiCMS le CMS multilingue sans base de données">
<link rel="alternate" type="application/rss+xml" href="'<?php echo helper::baseUrl(). $this->getUrl(0) . '/rss';?>" title="fLUX rss"> <meta name="generator" content="ZiiCMS https://forge.chapril.org/ZwiiCMS-Team/ZwiiCMS">
<?php endif; ?> <meta name="viewport" content="width=device-width, initial-scale=1">
<?php $this->showStyle(); ?> <?php $layout->showMetaTitle(); ?>
<!-- Script perso dans le header --> <?php $layout->showMetaDescription(); ?>
<?php if (file_exists(self::DATA_DIR .'head.inc.html')) { <?php $layout->showMetaType(); ?>
include(self::DATA_DIR .'head.inc.html'); <?php $layout->showMetaImage(); ?>
}?> <?php $layout->showFavicon(); ?>
</head> <?php $layout->showVendor(); ?>
<body> <?php $layout->showFonts(); ?>
<!-- Barre d'administration --> <?php if (file_exists(self::DATA_DIR . 'font/font.css')): ?>
<?php if($this->getUser('group') > self::GROUP_MEMBER): ?> <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 $this->showBar(); ?> <?php endif; ?>
<?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 -->
<?php if (
($this->getData(['page', $this->getUrl(0), 'moduleId']) === 'blog'
or $this->getData(['page', $this->getUrl(0), 'moduleId']) === 'news')
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">
<?php endif; ?>
<?php $layout->showStyle(); ?>
<?php $layout->showInlineStyle(); ?>
<!-- Script perso dans le header -->
<?php if (file_exists(self::DATA_DIR . 'head.inc.html')) {
include(self::DATA_DIR . 'head.inc.html');
} ?>
</head>
<!-- Notifications --> <body>
<?php $this->showNotification(); ?> <!-- Barre d'administration -->
<?php if ($this->getUser('group') > self::GROUP_MEMBER): ?>
<!-- Menu dans le fond du site avant la bannière --> <?php $layout->showBar(); ?>
<?php if($this->getData(['theme', 'menu', 'position']) === 'body-first' || $this->getData(['theme', 'menu', 'position']) === 'top' ): ?> <?php endif; ?>
<!-- Détermine si le menu est fixe en haut de page lorsque l'utilisateur n'est pas connecté --> <!-- Notifications -->
<?php <?php $layout->showNotification(); ?>
if ( $this->getData(['theme', 'menu', 'position']) === 'top' <!-- Menu dans le fond du site avant la bannière -->
AND $this->getData(['theme', 'menu', 'fixed']) === true <?php if ($this->getData(['theme', 'menu', 'position']) === 'body-first' || $this->getData(['theme', 'menu', 'position']) === 'top'): ?>
AND $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') <!-- Détermine si le menu est fixe en haut de page lorsque l'utilisateur n'est pas connecté -->
AND $this->getUser('group') > self::GROUP_MEMBER) { <?php
echo '<nav id="navfixedconnected" >'; if (
} else { $this->getData(['theme', 'menu', 'position']) === 'top'
echo '<nav id="navfixedlogout" >'; and $this->getData(['theme', 'menu', 'fixed']) === true
} and $this->isConnected() === true
?> and $this->getUser('group') > self::GROUP_MEMBER
<!-- Menu Burger --> ) {
echo '<nav id="navfixedconnected" >';
} else {
echo '<nav id="navfixedlogout" >';
}
?>
<!-- Menu Burger -->
<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']) === '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>
<!-- fin du menu burger -->
<?php
$menuClass = $this->getData(['theme', 'menu', 'position']) === 'top' ? 'class="container-large"' : 'class="container"';
$menuClass = $this->getData(['theme', 'menu', 'wide']) === 'none' ? 'class="container-large"' : 'class="container"';
?>
<div id="menu" <?php echo $menuClass; ?>>
<?php $layout->showMenu(); ?>
</div> <!--fin menu -->
</nav>
<?php endif; ?>
<!-- Bannière dans le fond du site -->
<?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
$headerClass = $this->getData(['theme', 'header', 'position']) === 'hide' ? 'displayNone' : '';
$headerClass .= $this->getData(['theme', 'header', 'tinyHidden']) ? ' bannerDisplay ' : '';
$headerClass .= $this->getData(['theme', 'header', 'wide']) === 'none' ? '' : 'container';
?>
<header <?php echo empty($headerClass) ? '' : 'class="' . $headerClass . '"'; ?>>
<?php if ($this->getData(['theme', 'header', 'feature']) === 'wallpaper'): ?>
<?php if (
$this->getData(['theme', 'header', 'textHide']) === false
// Affiche toujours le titre de la bannière pour l'édition du thème
or ($this->getUrl(0) === 'theme' and $this->getUrl(1) === 'header')
): ?>
<span id="themeHeaderTitle">
<?php echo $this->getData(['locale', 'title']); ?>
</span>
<?php else: ?>
<span id="themeHeaderTitle">&nbsp;</span>
<?php endif; ?>
<?php else: ?>
<div id="featureContent">
<?php echo $this->getData(['theme', 'header', 'featureContent']); ?>
</div>
<?php endif; ?>
</header>
<?php echo ($this->getData(['theme', 'header', 'linkHomePage']) && $this->getData(['theme', 'header', 'feature']) === 'wallpaper') ? '</a>' : ''; ?>
<?php endif; ?>
<!-- Menu dans le fond du site après la bannière -->
<?php if ($this->getData(['theme', 'menu', 'position']) === 'body-second'): ?>
<nav>
<!-- Menu burger -->
<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']) === '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>
<!-- fin du menu burger -->
<?php
$menuClass = $this->getData(['theme', 'menu', 'wide']) === 'none' ? 'class="container-large"' : 'class="container"';
?>
<div id="menu" <?php echo $menuClass; ?>>
<?php $layout->showMenu(); ?>
</div>
</nav>
<?php endif; ?>
<!-- Site -->
<div id="site" class="container">
<?php if ($this->getData(['theme', 'menu', 'position']) === 'site-first'): ?>
<!-- Menu dans le site avant la bannière -->
<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']); ?>
<!-- fin du menu burger --> </div>
<?php <div id="menu" class="container">
$menuClass = $this->getData(['theme', 'menu', 'position']) === 'top' ? 'class="container-large"' : 'class="container"'; <?php $layout->showMenu(); ?>
$menuClass = $this->getData(['theme', 'menu', 'wide']) === 'none' ? 'class="container-large"' : 'class="container"'; </div>
?>
<div id="menu" <?php echo $menuClass; ?> >
<?php $this->showMenu(); ?>
</div> <!--fin menu -->
</nav> </nav>
<?php endif; ?> <?php endif; ?>
<?php if (
<!-- Bannière dans le fond du site --> $this->getData(['theme', 'header', 'position']) === 'site'
<?php if($this->getData(['theme', 'header', 'position']) === 'body'): ?> // Affiche toujours la bannière pour l'édition du thème
or ($this->getData(['theme', 'header', 'position']) === 'hide'
and $this->getUrl(0) === 'theme'
)
): ?>
<!-- Bannière dans le site -->
<?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' : '';
$headerClass .= $this->getData(['theme', 'header', 'tinyHidden']) ? ' bannerDisplay ' : ''; $headerClass .= $this->getData(['theme', 'header', 'tinyHidden']) ? ' bannerDisplay ' : '';
$headerClass .= $this->getData(['theme', 'header', 'wide']) === 'none' ? '' : 'container';
?> ?>
<header <?php echo empty($headerClass) ? '' : 'class="' . $headerClass . '"';?>> <header <?php echo empty($headerClass) ? '' : 'class="' . $headerClass . '"'; ?>>
<?php echo ($this->getData(['theme','header','linkHomePage']) && $this->getData(['theme','header','feature']) === 'wallpaper' ) ? '<a href="' . helper::baseUrl(false) . '">' : ''; ?> <?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 echo $this->getData(['locale', 'title']); ?>
</span>
<?php else: ?> <?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>
<?php endif; ?> <?php endif; ?>
<?php echo ($this->getData(['theme','header','linkHomePage']) && $this->getData(['theme','header','feature']) === 'wallpaper' ) ? '</a>' : '';?>
</header> </header>
<?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 --> <?php if (
<?php if($this->getData(['theme', 'menu', 'position']) === 'body-second'): ?> $this->getData(['theme', 'menu', 'position']) === 'site-second' ||
$this->getData(['theme', 'menu', 'position']) === 'site'
<nav> // Affiche toujours le menu pour l'édition du thème
<!-- Menu burger --> or ($this->getData(['theme', 'menu', 'position']) === 'hide'
<div id="toggle"> and $this->getUrl(0) === 'theme'
<?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 template::ico('menu', ['fontSize' => '2em']); ?></div>
<!-- fin du menu burger -->
<?php
$menuClass = $this->getData(['theme', 'menu', 'wide']) === 'none' ? 'class="container-large"' : 'class="container"';
?>
<div id="menu" <?php echo $menuClass; ?> >
<?php $this->showMenu(); ?></div>
</nav>
<?php endif; ?>
<!-- Site -->
<div id="site" class="container">
<?php if($this->getData(['theme', 'menu', 'position']) === 'site-first'): ?>
<!-- Menu dans le site avant la bannière -->
<nav>
<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']) === '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>
<div id="menu" class="container"><?php $this->showMenu(); ?></div>
</nav>
<?php endif; ?>
<?php if(
$this->getData(['theme', 'header', 'position']) === 'site'
// Affiche toujours la bannière pour l'édition du thème
OR (
$this->getData(['theme', 'header', 'position']) === 'hide'
AND $this->getUrl(0) === 'theme'
)
): ?>
<!-- Bannière dans le site -->
<?php echo ( $this->getData(['theme','header','linkHomePage']) && $this->getData(['theme','header','feature']) === 'wallpaper' ) ? '<a href="' . helper::baseUrl(false) . '">' : ''; ?>
<?php
$headerClass = $this->getData(['theme', 'header', 'position']) === 'hide' ? 'displayNone' : '';
$headerClass .= $this->getData(['theme', 'header', 'tinyHidden']) ? ' bannerDisplay ' : '';
?>
<header <?php echo empty($headerClass) ? '' : 'class="' . $headerClass . '"';?>>
<?php if ($this->getData(['theme','header','feature']) === 'wallpaper' ): ?>
<?php if(
$this->getData(['theme', 'header', 'textHide']) === false
// Affiche toujours le titre de la bannière pour l'édition du thème
OR ($this->getUrl(0) === 'theme' AND $this->getUrl(1) === 'header')
): ?>
<span id="themeHeaderTitle"><?php echo $this->getData(['locale', 'title']); ?></span>
<?php else: ?>
<span id="themeHeaderTitle">&nbsp;</span>
<?php endif; ?>
<?php else: ?>
<div id="featureContent">
<?php echo $this->getData(['theme','header','featureContent']);?>
</diV>
<?php endif; ?>
</header>
<?php echo ( $this->getData(['theme','header','linkHomePage']) && $this->getData(['theme','header','feature']) === 'wallpaper' ) ? '</a>' : ''; ?>
<?php endif; ?>
<?php if(
$this->getData(['theme', 'menu', 'position']) === 'site-second' ||
$this->getData(['theme', 'menu', 'position']) === 'site'
// Affiche toujours le menu pour l'édition du thème
OR (
$this->getData(['theme', 'menu', 'position']) === 'hide'
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 $this->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->showMain(); ?>
<?php $this->showSection();?> <!-- footer -->
<?php $layout->showFooter(); ?>
<!-- footer -->
<?php $this->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 $this->showCookies(); ?> <?php $layout->showCookies(); ?>
<!-- Les scripts --> <!-- Les scripts -->
<?php $this->showScript();?> <?php $layout->showScript(); ?>
<!-- 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,8 +9,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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,123 +30,124 @@ 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,
'register' => self::GROUP_ADMIN,
]; ];
public static $timezones = [ public static $timezones = [
'Pacific/Midway' => '(GMT-11:00) Midway Island', 'Pacific/Midway' => '(GMT-11:00) Midway Island',
'US/Samoa' => '(GMT-11:00) Samoa', 'US/Samoa' => '(GMT-11:00) Samoa',
'US/Hawaii' => '(GMT-10:00) Hawaii', 'US/Hawaii' => '(GMT-10:00) Hawaii',
'US/Alaska' => '(GMT-09:00) Alaska', 'US/Alaska' => '(GMT-09:00) Alaska',
'US/Pacific' => '(GMT-08:00) Pacific Time (US &amp; Canada)', 'US/Pacific' => '(GMT-08:00) Pacific Time (US &amp; Canada)',
'America/Tijuana' => '(GMT-08:00) Tijuana', 'America/Tijuana' => '(GMT-08:00) Tijuana',
'US/Arizona' => '(GMT-07:00) Arizona', 'US/Arizona' => '(GMT-07:00) Arizona',
'US/Mountain' => '(GMT-07:00) Mountain Time (US &amp; Canada)', 'US/Mountain' => '(GMT-07:00) Mountain Time (US &amp; Canada)',
'America/Chihuahua' => '(GMT-07:00) Chihuahua', 'America/Chihuahua' => '(GMT-07:00) Chihuahua',
'America/Mazatlan' => '(GMT-07:00) Mazatlan', 'America/Mazatlan' => '(GMT-07:00) Mazatlan',
'America/Mexico_City' => '(GMT-06:00) Mexico City', 'America/Mexico_City' => '(GMT-06:00) Mexico City',
'America/Monterrey' => '(GMT-06:00) Monterrey', 'America/Monterrey' => '(GMT-06:00) Monterrey',
'Canada/Saskatchewan' => '(GMT-06:00) Saskatchewan', 'Canada/Saskatchewan' => '(GMT-06:00) Saskatchewan',
'US/Central' => '(GMT-06:00) Central Time (US &amp; Canada)', 'US/Central' => '(GMT-06:00) Central Time (US &amp; Canada)',
'US/Eastern' => '(GMT-05:00) Eastern Time (US &amp; Canada)', 'US/Eastern' => '(GMT-05:00) Eastern Time (US &amp; Canada)',
'US/East-Indiana' => '(GMT-05:00) Indiana (East)', 'US/East-Indiana' => '(GMT-05:00) Indiana (East)',
'America/Bogota' => '(GMT-05:00) Bogota', 'America/Bogota' => '(GMT-05:00) Bogota',
'America/Lima' => '(GMT-05:00) Lima', 'America/Lima' => '(GMT-05:00) Lima',
'America/Caracas' => '(GMT-04:30) Caracas', 'America/Caracas' => '(GMT-04:30) Caracas',
'Canada/Atlantic' => '(GMT-04:00) Atlantic Time (Canada)', 'Canada/Atlantic' => '(GMT-04:00) Atlantic Time (Canada)',
'America/La_Paz' => '(GMT-04:00) La Paz', 'America/La_Paz' => '(GMT-04:00) La Paz',
'America/Santiago' => '(GMT-04:00) Santiago', 'America/Santiago' => '(GMT-04:00) Santiago',
'Canada/Newfoundland' => '(GMT-03:30) Newfoundland', 'Canada/Newfoundland' => '(GMT-03:30) Newfoundland',
'America/Buenos_Aires' => '(GMT-03:00) Buenos Aires', 'America/Buenos_Aires' => '(GMT-03:00) Buenos Aires',
'Greenland' => '(GMT-03:00) Greenland', 'Greenland' => '(GMT-03:00) Greenland',
'Atlantic/Stanley' => '(GMT-02:00) Stanley', 'Atlantic/Stanley' => '(GMT-02:00) Stanley',
'Atlantic/Azores' => '(GMT-01:00) Azores', 'Atlantic/Azores' => '(GMT-01:00) Azores',
'Atlantic/Cape_Verde' => '(GMT-01:00) Cape Verde Is.', 'Atlantic/Cape_Verde' => '(GMT-01:00) Cape Verde Is.',
'Africa/Casablanca' => '(GMT) Casablanca', 'Africa/Casablanca' => '(GMT) Casablanca',
'Europe/Dublin' => '(GMT) Dublin', 'Europe/Dublin' => '(GMT) Dublin',
'Europe/Lisbon' => '(GMT) Lisbon', 'Europe/Lisbon' => '(GMT) Lisbon',
'Europe/London' => '(GMT) London', 'Europe/London' => '(GMT) London',
'Africa/Monrovia' => '(GMT) Monrovia', 'Africa/Monrovia' => '(GMT) Monrovia',
'Europe/Amsterdam' => '(GMT+01:00) Amsterdam', 'Europe/Amsterdam' => '(GMT+01:00) Amsterdam',
'Europe/Belgrade' => '(GMT+01:00) Belgrade', 'Europe/Belgrade' => '(GMT+01:00) Belgrade',
'Europe/Berlin' => '(GMT+01:00) Berlin', 'Europe/Berlin' => '(GMT+01:00) Berlin',
'Europe/Bratislava' => '(GMT+01:00) Bratislava', 'Europe/Bratislava' => '(GMT+01:00) Bratislava',
'Europe/Brussels' => '(GMT+01:00) Brussels', 'Europe/Brussels' => '(GMT+01:00) Brussels',
'Europe/Budapest' => '(GMT+01:00) Budapest', 'Europe/Budapest' => '(GMT+01:00) Budapest',
'Europe/Copenhagen' => '(GMT+01:00) Copenhagen', 'Europe/Copenhagen' => '(GMT+01:00) Copenhagen',
'Europe/Ljubljana' => '(GMT+01:00) Ljubljana', 'Europe/Ljubljana' => '(GMT+01:00) Ljubljana',
'Europe/Madrid' => '(GMT+01:00) Madrid', 'Europe/Madrid' => '(GMT+01:00) Madrid',
'Europe/Paris' => '(GMT+01:00) Paris', 'Europe/Paris' => '(GMT+01:00) Paris',
'Europe/Prague' => '(GMT+01:00) Prague', 'Europe/Prague' => '(GMT+01:00) Prague',
'Europe/Rome' => '(GMT+01:00) Rome', 'Europe/Rome' => '(GMT+01:00) Rome',
'Europe/Sarajevo' => '(GMT+01:00) Sarajevo', 'Europe/Sarajevo' => '(GMT+01:00) Sarajevo',
'Europe/Skopje' => '(GMT+01:00) Skopje', 'Europe/Skopje' => '(GMT+01:00) Skopje',
'Europe/Stockholm' => '(GMT+01:00) Stockholm', 'Europe/Stockholm' => '(GMT+01:00) Stockholm',
'Europe/Vienna' => '(GMT+01:00) Vienna', 'Europe/Vienna' => '(GMT+01:00) Vienna',
'Europe/Warsaw' => '(GMT+01:00) Warsaw', 'Europe/Warsaw' => '(GMT+01:00) Warsaw',
'Europe/Zagreb' => '(GMT+01:00) Zagreb', 'Europe/Zagreb' => '(GMT+01:00) Zagreb',
'Europe/Athens' => '(GMT+02:00) Athens', 'Europe/Athens' => '(GMT+02:00) Athens',
'Europe/Bucharest' => '(GMT+02:00) Bucharest', 'Europe/Bucharest' => '(GMT+02:00) Bucharest',
'Africa/Cairo' => '(GMT+02:00) Cairo', 'Africa/Cairo' => '(GMT+02:00) Cairo',
'Africa/Harare' => '(GMT+02:00) Harare', 'Africa/Harare' => '(GMT+02:00) Harare',
'Europe/Helsinki' => '(GMT+02:00) Helsinki', 'Europe/Helsinki' => '(GMT+02:00) Helsinki',
'Europe/Istanbul' => '(GMT+02:00) Istanbul', 'Europe/Istanbul' => '(GMT+02:00) Istanbul',
'Asia/Jerusalem' => '(GMT+02:00) Jerusalem', 'Asia/Jerusalem' => '(GMT+02:00) Jerusalem',
'Europe/Kiev' => '(GMT+02:00) Kyiv', 'Europe/Kiev' => '(GMT+02:00) Kyiv',
'Europe/Minsk' => '(GMT+02:00) Minsk', 'Europe/Minsk' => '(GMT+02:00) Minsk',
'Europe/Riga' => '(GMT+02:00) Riga', 'Europe/Riga' => '(GMT+02:00) Riga',
'Europe/Sofia' => '(GMT+02:00) Sofia', 'Europe/Sofia' => '(GMT+02:00) Sofia',
'Europe/Tallinn' => '(GMT+02:00) Tallinn', 'Europe/Tallinn' => '(GMT+02:00) Tallinn',
'Europe/Vilnius' => '(GMT+02:00) Vilnius', 'Europe/Vilnius' => '(GMT+02:00) Vilnius',
'Asia/Baghdad' => '(GMT+03:00) Baghdad', 'Asia/Baghdad' => '(GMT+03:00) Baghdad',
'Asia/Kuwait' => '(GMT+03:00) Kuwait', 'Asia/Kuwait' => '(GMT+03:00) Kuwait',
'Europe/Moscow' => '(GMT+03:00) Moscow', 'Europe/Moscow' => '(GMT+03:00) Moscow',
'Africa/Nairobi' => '(GMT+03:00) Nairobi', 'Africa/Nairobi' => '(GMT+03:00) Nairobi',
'Asia/Riyadh' => '(GMT+03:00) Riyadh', 'Asia/Riyadh' => '(GMT+03:00) Riyadh',
'Europe/Volgograd' => '(GMT+03:00) Volgograd', 'Europe/Volgograd' => '(GMT+03:00) Volgograd',
'Asia/Tehran' => '(GMT+03:30) Tehran', 'Asia/Tehran' => '(GMT+03:30) Tehran',
'Asia/Baku' => '(GMT+04:00) Baku', 'Asia/Baku' => '(GMT+04:00) Baku',
'Asia/Muscat' => '(GMT+04:00) Muscat', 'Asia/Muscat' => '(GMT+04:00) Muscat',
'Asia/Tbilisi' => '(GMT+04:00) Tbilisi', 'Asia/Tbilisi' => '(GMT+04:00) Tbilisi',
'Asia/Yerevan' => '(GMT+04:00) Yerevan', 'Asia/Yerevan' => '(GMT+04:00) Yerevan',
'Asia/Kabul' => '(GMT+04:30) Kabul', 'Asia/Kabul' => '(GMT+04:30) Kabul',
'Asia/Yekaterinburg' => '(GMT+05:00) Ekaterinburg', 'Asia/Yekaterinburg' => '(GMT+05:00) Ekaterinburg',
'Asia/Karachi' => '(GMT+05:00) Karachi', 'Asia/Karachi' => '(GMT+05:00) Karachi',
'Asia/Tashkent' => '(GMT+05:00) Tashkent', 'Asia/Tashkent' => '(GMT+05:00) Tashkent',
'Asia/Kolkata' => '(GMT+05:30) Kolkata', 'Asia/Kolkata' => '(GMT+05:30) Kolkata',
'Asia/Kathmandu' => '(GMT+05:45) Kathmandu', 'Asia/Kathmandu' => '(GMT+05:45) Kathmandu',
'Asia/Almaty' => '(GMT+06:00) Almaty', 'Asia/Almaty' => '(GMT+06:00) Almaty',
'Asia/Dhaka' => '(GMT+06:00) Dhaka', 'Asia/Dhaka' => '(GMT+06:00) Dhaka',
'Asia/Novosibirsk' => '(GMT+06:00) Novosibirsk', 'Asia/Novosibirsk' => '(GMT+06:00) Novosibirsk',
'Asia/Bangkok' => '(GMT+07:00) Bangkok', 'Asia/Bangkok' => '(GMT+07:00) Bangkok',
'Asia/Jakarta' => '(GMT+07:00) Jakarta', 'Asia/Jakarta' => '(GMT+07:00) Jakarta',
'Asia/Krasnoyarsk' => '(GMT+07:00) Krasnoyarsk', 'Asia/Krasnoyarsk' => '(GMT+07:00) Krasnoyarsk',
'Asia/Chongqing' => '(GMT+08:00) Chongqing', 'Asia/Chongqing' => '(GMT+08:00) Chongqing',
'Asia/Hong_Kong' => '(GMT+08:00) Hong Kong', 'Asia/Hong_Kong' => '(GMT+08:00) Hong Kong',
'Asia/Irkutsk' => '(GMT+08:00) Irkutsk', 'Asia/Irkutsk' => '(GMT+08:00) Irkutsk',
'Asia/Kuala_Lumpur' => '(GMT+08:00) Kuala Lumpur', 'Asia/Kuala_Lumpur' => '(GMT+08:00) Kuala Lumpur',
'Australia/Perth' => '(GMT+08:00) Perth', 'Australia/Perth' => '(GMT+08:00) Perth',
'Asia/Singapore' => '(GMT+08:00) Singapore', 'Asia/Singapore' => '(GMT+08:00) Singapore',
'Asia/Taipei' => '(GMT+08:00) Taipei', 'Asia/Taipei' => '(GMT+08:00) Taipei',
'Asia/Ulaanbaatar' => '(GMT+08:00) Ulaan Bataar', 'Asia/Ulaanbaatar' => '(GMT+08:00) Ulaan Bataar',
'Asia/Urumqi' => '(GMT+08:00) Urumqi', 'Asia/Urumqi' => '(GMT+08:00) Urumqi',
'Asia/Seoul' => '(GMT+09:00) Seoul', 'Asia/Seoul' => '(GMT+09:00) Seoul',
'Asia/Tokyo' => '(GMT+09:00) Tokyo', 'Asia/Tokyo' => '(GMT+09:00) Tokyo',
'Asia/Yakutsk' => '(GMT+09:00) Yakutsk', 'Asia/Yakutsk' => '(GMT+09:00) Yakutsk',
'Australia/Adelaide' => '(GMT+09:30) Adelaide', 'Australia/Adelaide' => '(GMT+09:30) Adelaide',
'Australia/Darwin' => '(GMT+09:30) Darwin', 'Australia/Darwin' => '(GMT+09:30) Darwin',
'Australia/Brisbane' => '(GMT+10:00) Brisbane', 'Australia/Brisbane' => '(GMT+10:00) Brisbane',
'Australia/Canberra' => '(GMT+10:00) Canberra', 'Australia/Canberra' => '(GMT+10:00) Canberra',
'Pacific/Guam' => '(GMT+10:00) Guam', 'Pacific/Guam' => '(GMT+10:00) Guam',
'Australia/Hobart' => '(GMT+10:00) Hobart', 'Australia/Hobart' => '(GMT+10:00) Hobart',
'Australia/Melbourne' => '(GMT+10:00) Melbourne', 'Australia/Melbourne' => '(GMT+10:00) Melbourne',
'Pacific/Port_Moresby' => '(GMT+10:00) Port Moresby', 'Pacific/Port_Moresby' => '(GMT+10:00) Port Moresby',
'Australia/Sydney' => '(GMT+10:00) Sydney', 'Australia/Sydney' => '(GMT+10:00) Sydney',
'Asia/Vladivostok' => '(GMT+10:00) Vladivostok', 'Asia/Vladivostok' => '(GMT+10:00) Vladivostok',
'Asia/Magadan' => '(GMT+11:00) Magadan', 'Asia/Magadan' => '(GMT+11:00) Magadan',
'Pacific/Auckland' => '(GMT+12:00) Auckland', 'Pacific/Auckland' => '(GMT+12:00) Auckland',
'Pacific/Fiji' => '(GMT+12:00) Fiji', 'Pacific/Fiji' => '(GMT+12:00) Fiji',
'Asia/Kamchatka' => '(GMT+12:00) Kamchatka' 'Asia/Kamchatka' => '(GMT+12:00) Kamchatka'
]; ];
// Type de proxy // Type de proxy
public static $proxyType = [ public static $proxyType = [
@ -187,7 +188,14 @@ class config extends common
]; ];
public static $captchaTypes = [ public static $captchaTypes = [
'num' => 'Chiffres', 'num' => 'Chiffres',
'alpha' => 'Lettres' 'alpha' => 'Lettres'
];
public static $updateDelay = [
86400 => '1',
172800 => '2',
345600 => '4',
604800 => '7',
1209600 => '14',
]; ];
// Langue traduite courante // Langue traduite courante
@ -197,23 +205,35 @@ 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
$successSitemap = $this->updateSitemap();
// Mettre à jour le site map // Valeurs en sortie
$successSitemap = $this->createSitemap(); $this->addOutput([
'redirect' => helper::baseUrl() . 'config',
'notification' => $successSitemap ? helper::translate('La carte du site a été mise à jour') : helper::translate('Echec de l\'écriture, vérifiez les permissions'),
'state' => $successSitemap
]);
}
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'config',
'notification' => $successSitemap ? helper::translate('La carte du site a été mise à jour') : helper::translate('Echec de l\'écriture, vérifiez les permissions'),
'state' => $successSitemap
]);
} }
@ -223,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);
@ -279,10 +302,8 @@ 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);
$img = $data['screenshot']; $img = $data['screenshot'];
// Effacer l'image et la miniature png // Effacer l'image et la miniature png
@ -295,9 +316,9 @@ class config extends common
$success = copy($img, self::FILE_DIR . 'source/screenshot.jpg'); $success = copy($img, self::FILE_DIR . 'source/screenshot.jpg');
} }
$notification = empty($token) $notification = empty($token)
? 'La clé de l\'API ne peut pas être vide' ? 'La clé de l\'API ne peut pas être vide'
: ($success === false ? 'Service en ligne inaccessible' : 'Capture d\'écran générée avec succès'); : ($success === false ? 'Service en ligne inaccessible' : 'Capture d\'écran générée avec succès');
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
@ -313,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;
@ -342,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);
@ -355,7 +374,7 @@ class config extends common
$data = json_decode(file_get_contents(self::TEMP_DIR . $tmpDir . '/data/core.json'), true); $data = json_decode(file_get_contents(self::TEMP_DIR . $tmpDir . '/data/core.json'), true);
$dataVersion = $data['core']['dataVersion']; $dataVersion = $data['core']['dataVersion'];
// Version non prises en charge <9 ou erreur d'extraction // Version non prises en charge <9 ou erreur d'extraction
if (intval(substr($dataVersion, 0, 1)) <= 9 or !$success) { if (intval(substr($dataVersion, 0, 1)) <= 9 or !$success) {
// Valeurs en sortie erreur // Valeurs en sortie erreur
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Restaurer'), 'title' => helper::translate('Restaurer'),
@ -375,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 (
@ -386,8 +405,8 @@ class config extends common
} }
// Message de notification // Message de notification
$notification = $success === true ? 'Restauration effectuée avec succès' : 'Erreur inconnue'; $notification = $success === true ? 'Restauration effectuée avec succès' : 'Erreur inconnue';
$redirect = $this->getInput('configRestoreImportUser', helper::FILTER_BOOLEAN) === true ? helper::baseUrl() . 'config/restore' : helper::baseUrl() . 'user/login/'; $redirect = $this->getInput('configRestoreImportUser', helper::FILTER_BOOLEAN) === true ? helper::baseUrl() . 'config/restore' : helper::baseUrl() . 'user/login/';
// Valeurs en sortie erreur // Valeurs en sortie erreur
$this->addOutput([ $this->addOutput([
'redirect' => $redirect, 'redirect' => $redirect,
@ -410,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 (
@ -420,7 +442,6 @@ class config extends common
$this->setData(['core', 'lastAutoUpdate', 0]); $this->setData(['core', 'lastAutoUpdate', 0]);
} }
// Sauvegarder la configuration // Sauvegarder la configuration
$this->setData([ $this->setData([
'config', 'config',
@ -436,6 +457,7 @@ class config extends common
'proxyType' => $this->getInput('configProxyType'), 'proxyType' => $this->getInput('configProxyType'),
'proxyUrl' => $this->getInput('configProxyUrl'), 'proxyUrl' => $this->getInput('configProxyUrl'),
'proxyPort' => $this->getInput('configProxyPort', helper::FILTER_INT), 'proxyPort' => $this->getInput('configProxyPort', helper::FILTER_INT),
'autoUpdateDelay' => $this->getInput('configAutoUpdateDelay', helper::FILTER_INT),
'social' => [ 'social' => [
'facebookId' => $this->getInput('socialFacebookId'), 'facebookId' => $this->getInput('socialFacebookId'),
'linkedinId' => $this->getInput('socialLinkedinId'), 'linkedinId' => $this->getInput('socialLinkedinId'),
@ -444,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_BOOLEAN), '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)),
'sender' => $this->getInput('smtpSender', helper::FILTER_MAIL) '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),
@ -483,7 +509,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');
} }
@ -497,8 +524,8 @@ 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 .
"\tRewriteBase " . helper::baseUrl(false, false) . PHP_EOL . "\tRewriteBase " . helper::baseUrl(false, false) . PHP_EOL .
@ -506,9 +533,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
); );
@ -524,7 +551,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
); );
@ -543,10 +570,72 @@ class config extends common
]); ]);
} }
// Activation du bouton de mise à jour
if (
helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)
&& $this->getData(['core', 'updateAvailable']) === false
&& $this->getData(['config', 'autoUpdate'])
) {
$this->setData(['core', 'updateAvailable', true]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'config',
]);
}
// Variable de version // Variable de version
self::$onlineVersion = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/version'); if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) {
if (self::$onlineVersion > common::ZWII_VERSION) { self::$updateButtonText = helper::translate('Mise à jour');
self::$updateButtonText = helper::translate('Mettre à jour'); }
// Sélecteur de délais, compléter avec la traduction en jours
foreach (self::$updateDelay as $key => $value) {
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
@ -560,13 +649,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([
@ -595,26 +687,36 @@ class config extends common
public function logReset() public function logReset()
{ {
if (file_exists(self::DATA_DIR . 'journal.log')) { // Action interdite
unlink(self::DATA_DIR . 'journal.log'); if (
// Créer les en-têtes des journaux $this->getUser('permission', __CLASS__, __FUNCTION__) !== true
$d = 'Date;Heure;IP;Id;Action' . PHP_EOL; ) {
file_put_contents(self::DATA_DIR . 'journal.log', $d);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Configuration'), 'access' => false
'view' => 'index',
'notification' => helper::translate('Journal réinitialisé avec succès'),
'state' => true
]); ]);
} else { } else {
// Valeurs en sortie if (file_exists(self::DATA_DIR . 'journal.log')) {
$this->addOutput([ unlink(self::DATA_DIR . 'journal.log');
'title' => helper::translate('Configuration'), // Créer les en-têtes des journaux
'view' => 'index', $d = 'Date;Heure;IP;Id;Action' . PHP_EOL;
'notification' => helper::translate('Aucun journal à effacer'), $this->secure_file_put_contents(self::DATA_DIR . 'journal.log', $d);
'state' => false // Valeurs en sortie
]); $this->addOutput([
'title' => helper::translate('Configuration'),
'view' => 'index',
'notification' => helper::translate('Journal réinitialisé avec succès'),
'state' => true
]);
} else {
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Configuration'),
'view' => 'index',
'notification' => helper::translate('Aucun journal à effacer'),
'state' => false
]);
}
} }
} }
@ -625,24 +727,35 @@ class config extends common
*/ */
public function logDownload() public function logDownload()
{ {
$fileName = self::DATA_DIR . 'journal.log'; // Action interdite
if (file_exists($fileName)) { if (
ob_start(); $this->getUser('permission', __CLASS__, __FUNCTION__) !== true
header('Content-Type: application/octet-stream'); ) {
header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Content-Length: ' . filesize($fileName));
ob_clean();
ob_end_flush();
readfile($fileName);
exit();
} else {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Configuration'), 'access' => false
'view' => 'index',
'notification' => helper::translate('Aucun fichier journal à télécharger'),
'state' => false
]); ]);
} else {
$fileName = self::DATA_DIR . 'journal.log';
if (file_exists($fileName)) {
ob_start();
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Content-Length: ' . filesize($fileName));
ob_clean();
ob_end_flush();
readfile($fileName);
exit();
} else {
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Configuration'),
'view' => 'index',
'notification' => helper::translate('Aucun fichier journal à télécharger'),
'state' => false
]);
}
} }
} }
@ -651,34 +764,46 @@ class config extends common
*/ */
public function blacklistDownload() public function blacklistDownload()
{ {
ob_start(); // Action interdite
$fileName = self::TEMP_DIR . 'blacklist.log'; if (
$d = 'Date dernière tentative;Heure dernière tentative;Id;Adresse IP;Nombre d\'échecs' . PHP_EOL; $this->getUser('permission', __CLASS__, __FUNCTION__) !== true
file_put_contents($fileName, $d); ) {
if (file_exists($fileName)) {
$d = $this->getData(['blacklist']);
$data = '';
foreach ($d as $key => $item) {
$data .= helper::dateUTF8('%Y %m %d', $item['lastFail']) . ' - ' . helper::dateUTF8('%H:%M', time());
$data .= $key . ';' . $item['ip'] . ';' . $item['connectFail'] . PHP_EOL;
}
file_put_contents($fileName, $data, FILE_APPEND);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $fileName . '"');
header('Content-Length: ' . filesize($fileName));
ob_clean();
ob_end_flush();
readfile($fileName);
unlink(self::TEMP_DIR . 'blacklist.log');
exit();
} else {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Confighelper::translate(uration'), 'access' => false
'view' => 'index',
'notification' => helper::translate('Aucune liste noire à télécharger'),
'state' => false
]); ]);
} else {
ob_start();
$fileName = self::TEMP_DIR . 'blacklist.log';
$d = 'Date dernière tentative;Heure dernière tentative;Id;Adresse IP;Nombre d\'échecs' . PHP_EOL;
$this->secure_file_put_contents($fileName, $d);
if (file_exists($fileName)) {
$d = $this->getData(['blacklist']);
$data = '';
foreach ($d as $key => $item) {
$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;
}
$this->secure_file_put_contents($fileName, $data, FILE_APPEND);
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($fileName));
ob_clean();
ob_end_flush();
readfile($fileName);
unlink(self::TEMP_DIR . 'blacklist.log');
exit();
} else {
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Configuration'),
'view' => 'index',
'notification' => helper::translate('Aucune liste noire à télécharger'),
'state' => false
]);
}
} }
} }
@ -688,23 +813,33 @@ class config extends common
public function blacklistReset() public function blacklistReset()
{ {
if (file_exists(self::DATA_DIR . 'blacklist.json')) { // Action interdite
$this->setData(['blacklist', []]); if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Configuration'), 'access' => false
'view' => 'index',
'notification' => helper::translate('Liste noire réinitialisée avec succès'),
'state' => true
]); ]);
} else { } else {
// Valeurs en sortie if (file_exists(self::DATA_DIR . 'blacklist.json')) {
$this->addOutput([ $this->setData(['blacklist', []]);
'title' => helper::translate('Configuration'), // Valeurs en sortie
'view' => 'index', $this->addOutput([
'notification' => helper::translate('Aucune liste noire à effacer'), 'title' => helper::translate('Configuration'),
'state' => false 'view' => 'index',
]); 'notification' => helper::translate('Liste noire réinitialisée avec succès'),
'state' => true
]);
} else {
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Configuration'),
'view' => 'index',
'notification' => helper::translate('Aucune liste noire à effacer'),
'state' => false
]);
}
} }
} }
@ -713,16 +848,26 @@ class config extends common
*/ */
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');
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Configuration'), 'title' => helper::translate('Configuration'),
'view' => 'index', 'view' => 'index',
'notification' => $success ? helper::translate('Copie terminée avec succès') : helper::translate('Copie terminée avec des erreurs'), 'notification' => $success ? helper::translate('Copie terminée avec succès') : helper::translate('Copie terminée avec des erreurs'),
'state' => $success 'state' => $success
]); ]);
}
} }
/** /**
@ -730,22 +875,69 @@ class config extends common
*/ */
public function delBackups() public function delBackups()
{ {
$path = realpath(self::BACKUP_DIR); // Action interdite
$success = $fail = 0; if (
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) { $this->getUser('permission', __CLASS__, __FUNCTION__) !== true
if (strpos($filename, '.zip')) { ) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
$path = realpath(self::BACKUP_DIR);
$success = $fail = 0;
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
if (strpos($filename, '.zip')) {
$r = unlink($filename); $r = unlink($filename);
$success = $r === true ? $success + 1 : $success; $success = $r === true ? $success + 1 : $success;
$fail = $r === false ? $fail + 1 : $fail; $fail = $r === false ? $fail + 1 : $fail;
}
} }
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Configuration'),
'view' => 'index',
'notification' => $success . helper::translate('Fichiers effacés') . ' - ' . helper::translate('Échecs') . ': ' . $fail,
'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';
}
}
/**
* Stocke la variable dans les paramètres de l'utilisateur pour activer la tab à sa prochaine visite
* @return never
*/
public function register(): void
{
$this->setData([
'user',
$this->getUser('id'),
'view',
[
'config' => $this->getUrl(2),
'page' => $this->getData(['user', $this->getUser('id'), 'view', 'page']),
]
]);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Configuration'), 'redirect' => helper::baseUrl() . 'config/' . $this->getUrl(2),
'view' => 'index',
'notification' => $success . helper::translate('Fichiers effacés') . ' - ' . helper::translate('Échecs') . ': ' . $fail,
'state' => true
]); ]);
} }
} }

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,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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

@ -109,7 +109,7 @@
<?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 class="col3 verticalAlignBottom">

View File

@ -7,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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 offset6">
<?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,21 +21,24 @@
<div class="tab"> <div class="tab">
<?php echo template::button('configSetupButton', [ <?php echo template::button('configSetupButton', [
'value' => 'Configuration', 'value' => 'Configuration',
'class' => 'buttonTab' 'class' => 'buttonTab',
'href' => helper::baseUrl() . 'config/register/setup'
]); ?> ]); ?>
<?php echo template::button('configSocialButton', [ <?php echo template::button('configSocialButton', [
'value' => 'Référencement', 'value' => 'Référencement',
'class' => 'buttonTab' 'class' => 'buttonTab',
'href' => helper::baseUrl() . 'config/register/social'
]); ?> ]); ?>
<?php echo template::button('configConnectButton', [ <?php echo template::button('configConnectButton', [
'value' => 'Connexion', 'value' => 'Connexion',
'class' => 'buttonTab' 'class' => 'buttonTab',
'href' => helper::baseUrl() . 'config/register/connect'
]); ?> ]); ?>
<?php echo template::button('configNetworkButton', [ <?php echo template::button('configNetworkButton', [
'value' => 'Réseau', 'value' => 'Réseau',
'class' => 'buttonTab' 'class' => 'buttonTab',
'href' => helper::baseUrl() . 'config/register/network'
]); ?> ]); ?>
</div> </div>

View File

@ -2,7 +2,8 @@
<div class="row"> <div class="row">
<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="specialeHelpButton" class="helpDisplayButton"> <!--<span id="specialeHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/reseau" target="_blank" title="Cliquer pour consulter l'aide en ligne"> <a href="https://doc.zwiicms.fr/reseau" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']); ?> <?php //echo template::ico('help', ['margin' => 'left']); ?>
@ -37,7 +38,8 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<div class="block"> <div class="block">
<h4><?php echo helper::translate('SMTP'); ?> <h4>
<?php echo helper::translate('SMTP'); ?>
<!--<span id="specialeHelpButton" class="helpDisplayButton"> <!--<span id="specialeHelpButton" class="helpDisplayButton">
<a href="https://doc.zwiicms.fr/smtp" target="_blank" title="Cliquer pour consulter l'aide en ligne"> <a href="https://doc.zwiicms.fr/smtp" target="_blank" title="Cliquer pour consulter l'aide en ligne">
<?php //echo template::ico('help', ['margin' => 'left']); ?> <?php //echo template::ico('help', ['margin' => 'left']); ?>
@ -45,61 +47,69 @@
</span>--> </span>-->
</h4> </h4>
<div class="row"> <div class="row">
<div class="col12"> <div class="col6">
<?php echo template::checkbox('smtpEnable', true, 'Activer SMTP', [ <?php echo template::text('smtpFrom', [
'checked' => $this->getData(['config', 'smtp', 'enable']), 'label' => 'Expéditeur',
'help' => 'Paramètres à utiliser lorsque votre hébergeur ne propose pas la fonctionnalité d\'envoi de mail.' 'placeholder' => 'no-reply@host',
'value' => $this->getData(['config', 'smtp', 'from']),
]); ?> ]); ?>
</div> </div>
</div>
<div id="smtpParam">
<div class="row"> <div class="row">
<div class="col8"> <div class="col12">
<?php echo template::text('smtpHost', [ <?php echo template::checkbox('smtpEnable', true, 'SMTP personnalisé', [
'label' => 'Adresse SMTP', 'checked' => $this->getData(['config', 'smtp', 'enable']),
'placeholder' => 'smtp.fr', 'help' => 'Paramètres à utiliser lorsque votre hébergeur ne propose pas la fonctionnalité d\'envoi de mail.'
'value' => $this->getData(['config', 'smtp', 'host'])
]); ?>
</div>
<div class="col2">
<?php echo template::text('smtpPort', [
'label' => 'Port SMTP',
'placeholder' => '589',
'value' => $this->getData(['config', 'smtp', 'port'])
]); ?>
</div>
<div class="col2">
<?php echo template::select('smtpAuth', $module::$SMTPauth, [
'label' => 'Authentification',
'selected' => $this->getData(['config', 'smtp', 'auth'])
]); ?> ]); ?>
</div> </div>
</div> </div>
<div id="smtpAuthParam"> <div id="smtpParam">
<div class="row"> <div class="row">
<div class="col5"> <div class="col8">
<?php echo template::text('smtpUsername', [ <?php echo template::text('smtpHost', [
'label' => 'Nom utilisateur', 'label' => 'Adresse SMTP',
'value' => $this->getData(['config', 'smtp', 'username']) 'placeholder' => 'smtp.fr',
]); ?> 'value' => $this->getData(['config', 'smtp', 'host'])
</div>
<div class="col5">
<?php echo template::password('smtpPassword', [
'label' => 'Mot de passe',
'autocomplete' => 'off',
'value' => $this->getData(['config', 'smtp', 'username']) ? helper::decrypt($this->getData(['config', 'smtp', 'username']), $this->getData(['config', 'smtp', 'password'])) : ''
]); ?> ]); ?>
</div> </div>
<div class="col2"> <div class="col2">
<?php echo template::select('smtpSecure', $module::$SMTPEnc, [ <?php echo template::text('smtpPort', [
'label' => 'Sécurité', 'label' => 'Port SMTP',
'selected' => $this->getData(['config', 'smtp', 'secure']) 'placeholder' => '589',
'value' => $this->getData(['config', 'smtp', 'port'])
]); ?> ]); ?>
</div> </div>
<div class="col2">
<?php echo template::select('smtpAuth', $module::$SMTPauth, [
'label' => 'Authentification',
'selected' => $this->getData(['config', 'smtp', 'auth'])
]); ?>
</div>
</div>
<div id="smtpAuthParam">
<div class="row">
<div class="col5">
<?php echo template::text('smtpUsername', [
'label' => 'Nom utilisateur',
'value' => $this->getData(['config', 'smtp', 'username'])
]); ?>
</div>
<div class="col5">
<?php echo template::password('smtpPassword', [
'label' => 'Mot de passe',
'autocomplete' => 'off',
'value' => $this->getData(['config', 'smtp', 'password'])
]); ?>
</div>
<div class="col2">
<?php echo template::select('smtpSecure', $module::$SMTPEnc, [
'label' => 'Sécurité',
'selected' => $this->getData(['config', 'smtp', 'secure'])
]); ?>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div>

View File

@ -7,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
$(document).ready((function(){$("#configRestoreSubmit").click((function(event){$("body, .button").css("cursor","wait")}))})); $(document).ready((function(){$("#configRestoreSubmit").click((function(event){$("body, .button").css("cursor","wait")}))}));

View File

@ -1,14 +1,13 @@
<?php echo template::formOpen('configRestoreForm'); ?> <?php echo template::formOpen('configRestoreForm'); ?>
<div class="row"> <div class="row">
<div class="col2"> <div class="col1">
<?php echo template::button('configRestoreBack', [ <?php echo template::button('configRestoreBack', [
'class' => 'buttonGrey', 'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'config', 'href' => helper::baseUrl() . 'config',
'ico' => 'left', 'value' => template::ico('left')
'value' => 'Retour'
]); ?> ]); ?>
</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,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */

View File

@ -1,14 +1,13 @@
<?php echo template::formOpen('configScript'); ?> <?php echo template::formOpen('configScript'); ?>
<div class="row"> <div class="row">
<div class="col2"> <div class="col1">
<?php echo template::button('configManageBack', [ <?php echo template::button('configManageBack', [
'class' => 'buttonGrey', 'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'config', 'href' => helper::baseUrl() . 'config',
'ico' => 'left', 'value' => template::ico('left')
'value' => 'Retour'
]); ?> ]); ?>
</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,11 +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">
@ -16,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">
@ -25,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">
@ -46,8 +43,8 @@
<div class="col6"> <div class="col6">
<?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' => stripos($_SERVER["SERVER_SOFTWARE"], 'Apache') === false and $module->isModRewriteEnabled()
]); ?> ]); ?>
</div> </div>
</div> </div>
@ -58,40 +55,40 @@
<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">
<?php echo template::checkbox('configAutoUpdate', true, 'Rechercher une mise à jour en ligne', [ <?php echo template::checkbox('configAutoUpdate', true, 'Rechercher une mise à jour en ligne', [
'checked' => $this->getData(['config', 'autoUpdate']), 'checked' => $this->getData(['config', 'autoUpdate']),
'help' => 'La vérification est quotidienne. Option désactivée si la configuration du serveur ne le permet pas.', 'help' => 'La vérification est quotidienne. Option désactivée si la configuration du serveur ne le permet pas.',
'disabled' => !$module::$onlineVersion 'disabled' => empty(helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL))
]); ?> ]); ?>
</div> </div>
<div class="col6"> <div class="col6">
<?php echo template::checkbox('configAutoUpdateHtaccess', true, 'Préserver le fichier htaccess racine', [ <?php echo template::checkbox('configAutoUpdateHtaccess', true, 'Préserver le fichier htaccess racine', [
'checked' => $this->getData(['config', 'autoUpdateHtaccess']), 'checked' => $this->getData(['config', 'autoUpdateHtaccess']),
'help' => 'Lors d\'une mise à jour automatique, conserve le fichier htaccess de la racine du site.', 'help' => 'Lors d\'une mise à jour automatique, conserve le fichier htaccess de la racine du site.',
'disabled' => !$module::$onlineVersion 'disabled' => empty(helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL))
]); ?> ]); ?>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col6"> <div class="col3">
<?php echo '<pre>Version installée : <strong>' . common::ZWII_VERSION . '</strong></pre>'; ?> <?php echo template::select('configAutoUpdateDelay', $module::$updateDelay, [
<?php echo $module::$onlineVersion ? '<pre>Version en ligne : <strong>' . $module::$onlineVersion . '</strong></pre>' : ''; ?> 'label' => 'Fréquence de recherche',
'selected' => $this->getData(['config', 'autoUpdateDelay']),
]); ?>
</div> </div>
<div class="col4 verticalAlignBottom"> <div class="col3 offset1 verticalAlignBottom">
<pre>Version installée : <strong><?php echo common::ZWII_VERSION; ?></strong></pre>
<pre>Version en ligne : <strong><?php echo helper::getOnlineVersion(common::ZWII_UPDATE_CHANNEL); ?></strong></pre>
</div>
<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',
'value' => $module::$updateButtonText, 'value' => $module::$updateButtonText,
'class' => 'buttonRed', 'class' => 'buttonRed',
'disabled' => !$module::$onlineVersion
]); ?> ]); ?>
</div> </div>
</div> </div>
@ -102,11 +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">
@ -161,11 +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">
@ -186,4 +173,27 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="col12">
<div class="block">
<h4>ZwiiCMS <a href="https://zwiicms.fr" target="_blank">Site Web</a> - <a
href="https://forum.zwiicms.fr" target="_blank">Forum</a>
</h4>
<div class="row textAlignCenter">
<div class="col12">
<a rel="license" href="http://creativecommons.org/licenses/by-nc-nd/4.0/"><img
alt="Licence Creative Commons" style="border-width:0"
src="https://i.creativecommons.org/l/by-nc-nd/4.0/88x31.png" /></a>
<p>Cette œuvre est mise à disposition selon les termes de la <a rel="license"
href="http://creativecommons.org/licenses/by-nc-nd/4.0/">Licence Creative Commons
Attribution - Pas d&#39;Utilisation Commerciale - Pas de Modification 4.0
International.</a></p>
<p>Pour voir une copie de cette licence, visitez
http://creativecommons.org/licenses/by-nc-nd/4.0/ ou écrivez à Creative Commons, PO Box
1866, Mountain View, CA 94042, USA.</p>
</div>
</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-2024, 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,8 +8,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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,37 +49,35 @@ class install extends common
'access' => false 'access' => false
]); ]);
} }
// Accès autorisé
else { // Soumission du formulaire
// Soumission du formulaire if (
if ($this->isPost()) { //$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$lang = $this->getInput('installLanguage'); $this->isPost()
setcookie('ZWII_UI', $lang, time() + 3600, helper::baseUrl(false, false), '', helper::isHttps(), true); ) {
// Valeurs en sortie
$this->addOutput([ $lang = $this->getInput('installLanguage');
'redirect' => helper::baseUrl() . 'install/postinstall/' . $lang // Pour la suite de l'installation
]); // setcookie('ZWII_UI', $lang, time() + 3600, helper::baseUrl(false, false), '', false, false);
}
$_SESSION['ZWII_UI'] = $this->getInput('installLanguage');
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'install/postinstall'
]);
} }
// Liste des langues UI disponibles // Liste des langues UI disponibles
if (is_dir(self::I18N_DIR)) { if (is_dir(self::I18N_DIR)) {
$dir = getcwd(); foreach ($this->getData(['language']) as $lang => $value) {
chdir(self::I18N_DIR); self::$i18nFiles[$lang] = self::$languages[$lang];
$files = glob('*.json');
// Ajouter une clé au tableau avec le code de langue
foreach ($files as $file) {
// La langue est-elle référencée ?
if (array_key_exists(basename($file, '.json'), self::$languages)) {
self::$i18nFiles[basename($file, '.json')] = self::$languages[basename($file, '.json')];
}
} }
chdir($dir);
} }
$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'
]); ]);
} }
@ -100,13 +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
$lang = array_key_exists($this->getUrl(2), self::$languages) ? $this->getUrl(2) : 'fr_FR';
// 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';
@ -118,137 +115,120 @@ 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';
// 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
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' => $lang 'language' => $_SESSION['ZWII_SITE_CONTENT']
] ]
]); ]);
// Compte créé, envoi du mail et création des données du site // Envoie le mail
if ($success) { // Formulaire complété envoi du mail // Sent contient true si réussite sinon code erreur d'envoi en clair
// Envoie le mail $this->sendMail(
// Sent contient true si réussite sinon code erreur d'envoi en clair $userMail,
$sent = $this->sendMail( 'Installation de votre site',
$userMail, 'Bonjour' . ' <strong>' . $userFirstname . ' ' . $userLastname . '</strong>,<br><br>' .
'Installation de votre site', 'Voici les détails de votre installation.<br><br>' .
'Bonjour' . ' <strong>' . $userFirstname . ' ' . $userLastname . '</strong>,<br><br>' . '<strong>URL du site :</strong> <a href="' . helper::baseUrl(false) . '" target="_blank">' . helper::baseUrl(false) . '</a><br>' .
'Voici les détails de votre installation.<br><br>' . '<strong>Identifiant du compte :</strong> ' . $this->getInput('installId') . '<br>',
'<strong>URL du site :</strong> <a href="' . helper::baseUrl(false) . '" target="_blank">' . helper::baseUrl(false) . '</a><br>' . null,
'<strong>Identifiant du compte :</strong> ' . $this->getInput('installId') . '<br>', 'no-reply@localhost'
null );
);
// Nettoyer les cookies de langue d'une précédente installation // Nettoyage fr par défaut
helper::deleteCookie('ZWII_CONTENT'); if (
$_SESSION['ZWII_SITE_CONTENT'] !== 'fr_FR'
) {
// Effacer le dossier de contenu fr créé par défaut si la langue est différente. if (is_dir(self::DATA_DIR . 'fr_FR'))
$this->deleteDir(self::DATA_DIR . 'fr_FR');
/*if (
self::$i18nContent !== 'fr_FR'
&& is_dir('site/data/fr')
) {
$this->removeDir('site/data/fr');
}*/
// Installation du site de test
if ($this->getInput('installDefaultData', helper::FILTER_BOOLEAN) === false
&& $lang === 'fr_FR' ) {
$this->initData('page', self::$i18nContent, true);
$this->initData('module', self::$i18nContent, true);
$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 ( $lang !== 'fr_FR') {
$this->initData('page', self::$i18nContent, false);
$this->initData('module', self::$i18nContent, false);
}
// Sauvegarder la configuration du Proxy
$this->setData(['config', 'proxyType', $this->getInput('installProxyType')]);
$this->setData(['config', 'proxyUrl', $this->getInput('installProxyUrl')]);
$this->setData(['config', 'proxyPort', $this->getInput('installProxyPort', helper::FILTER_INT)]);
// Images exemples livrées dans tous les cas
try {
// Décompression dans le dossier de fichier temporaires
if (file_exists(self::TEMP_DIR . 'files.tar.gz')) {
unlink(self::TEMP_DIR . 'files.tar.gz');
}
if (file_exists(self::TEMP_DIR . 'files.tar')) {
unlink(self::TEMP_DIR . 'files.tar');
}
copy('core/module/install/ressource/files.tar.gz', self::TEMP_DIR . 'files.tar.gz');
$pharData = new PharData(self::TEMP_DIR . 'files.tar.gz');
$pharData->decompress();
// Installation
$pharData->extractTo(__DIR__ . '/../../../', null, true);
} catch (Exception $e) {
$success = $e->getMessage();
}
// Nettoyage
unlink(self::TEMP_DIR . 'files.tar.gz');
unlink(self::TEMP_DIR . 'files.tar');
helper::deleteCookie('ZWII_UI');
// Créer le dossier des fontes
if (!is_dir(self::DATA_DIR . 'fonts')) {
mkdir(self::DATA_DIR . 'fonts');
}
// Installation du thème sélectionné
$dataThemes = file_get_contents('core/module/install/ressource/themes/themes.json');
$dataThemes = json_decode($dataThemes, true);
$themeId = $dataThemes[$this->getInput('installTheme', helper::FILTER_STRING_SHORT)]['filename'];
if ($themeId !== 'default') {
$theme = new theme;
$theme->import('core/module/install/ressource/themes/' . $themeId);
}
// 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');
// Créer sitemap
$this->createSitemap();
// Mise à jour de la liste des pages pour TinyMCE
$this->listPages();
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl(false),
'notification' => $sent === true ? helper::translate('Installation terminée') : $sent,
'state' => ($sent === true && $success === true) ? true : null
]);
} }
// Sauvegarder la configuration du Proxy
$this->setData(['config', 'proxyType', $this->getInput('installProxyType')]);
$this->setData(['config', 'proxyUrl', $this->getInput('installProxyUrl')]);
$this->setData(['config', 'proxyPort', $this->getInput('installProxyPort', helper::FILTER_INT)]);
// Images exemples livrées dans tous les cas
try {
// Décompression dans le dossier de fichier temporaires
if (file_exists(self::TEMP_DIR . 'files.tar.gz')) {
unlink(self::TEMP_DIR . 'files.tar.gz');
}
if (file_exists(self::TEMP_DIR . 'files.tar')) {
unlink(self::TEMP_DIR . 'files.tar');
}
copy('core/module/install/ressource/files.tar.gz', self::TEMP_DIR . 'files.tar.gz');
$pharData = new PharData(self::TEMP_DIR . 'files.tar.gz');
$pharData->decompress();
// Installation
$pharData->extractTo(__DIR__ . '/../../../', null, true);
} catch (Exception $e) {
$success = $e->getMessage();
}
// Nettoyage
unlink(self::TEMP_DIR . 'files.tar.gz');
unlink(self::TEMP_DIR . 'files.tar');
// Créer le dossier des fontes
if (!is_dir(self::DATA_DIR . 'font')) {
mkdir(self::DATA_DIR . 'font');
}
// Copie des langues de l'UI et génération de la base de données
if (is_dir(self::I18N_DIR) === false) {
mkdir(self::I18N_DIR);
}
// Créer la base de données des langues
$this->copyDir('core/module/install/ressource/i18n', self::I18N_DIR);
// Fixe l'adresse from pour les envois d'email
$this->setData(['config', 'smtp', 'from', 'no-reply@' . str_replace('www.', '', $_SERVER['HTTP_HOST'])]);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl(),
'notification' => helper::translate('Installation terminée'),
'state' => true
]);
} }
// Affichage du formulaire
// Récupération de la liste des thèmes
$dataThemes = file_get_contents('core/module/install/ressource/themes/themes.json');
$dataThemes = json_decode($dataThemes, true);
self::$themes = helper::arrayColumn($dataThemes, 'name');
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'display' => self::DISPLAY_LAYOUT_LIGHT, 'display' => self::DISPLAY_LAYOUT_LIGHT,
@ -263,122 +243,204 @@ class install extends common
*/ */
public function steps() public function steps()
{ {
switch ($this->getInput('step', helper::FILTER_INT)) { // Action interdite
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'access' => false
]);
} else {
switch ($this->getInput('step', helper::FILTER_INT)) {
// Préparation // Préparation
case 1: case 1:
$success = true; $success = true;
// RAZ la mise à jour auto $message = '';
$this->setData(['core', 'updateAvailable', false]); // RAZ la mise à jour auto
// Backup du dossier Data $this->setData(['core', 'updateAvailable', false]);
helper::autoBackup(self::BACKUP_DIR, ['backup', 'tmp', 'file']); // Backup du dossier Data
// Sauvegarde htaccess helper::autoBackup(self::BACKUP_DIR, ['backup', 'tmp', 'file']);
if ($this->getData(['config', 'autoUpdateHtaccess'])) { // Sauvegarde htaccess
$success = copy('.htaccess', '.htaccess' . '.bak'); if ($this->getData(['config', 'autoUpdateHtaccess'])) {
} $success = copy('.htaccess', '.htaccess' . '.bak');
// Nettoyage des fichiers d'installation précédents $message = $success ? '' : 'Erreur de copie du fichier htaccess';
if (file_exists(self::TEMP_DIR . 'update.tar.gz') && $success) { }
$success = unlink(self::TEMP_DIR . 'update.tar.gz'); // Nettoyage des fichiers d'installation précédents
} if ($success && file_exists(self::TEMP_DIR . 'update.tar.gz')) {
if (file_exists(self::TEMP_DIR . 'update.tar') && $success) { $success = unlink(self::TEMP_DIR . 'update.tar.gz');
$success = unlink(self::TEMP_DIR . 'update.tar'); $message = $success ? '' : 'Impossible d\'effacer la mise à jour précédente';
} }
// Valeurs en sortie if ($success && file_exists(self::TEMP_DIR . 'update.tar')) {
$this->addOutput([ $success = unlink(self::TEMP_DIR . 'update.tar');
'display' => self::DISPLAY_JSON, $message = $success ? '' : 'Impossible d\'effacer la mise à jour précédente';
'content' => [ }
'success' => $success, // Sauvegarde le message dans le journal
'data' => null if (!empty($message)) {
] $this->saveLog($message);
]); }
break; // Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
'content' => [
'success' => $success,
'data' => $success ? null : json_encode($message, JSON_UNESCAPED_UNICODE)
]
]);
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;
$md5origin = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.md5'); $message = '';
$md5origin = (explode(' ', $md5origin)); $this->secure_file_put_contents(self::TEMP_DIR . 'update.tar.gz', helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.tar.gz'));
$md5target = md5_file(self::TEMP_DIR . 'update.tar.gz'); $md5origin = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.md5');
// Valeurs en sortie $md5origin = explode(' ', $md5origin);
$this->addOutput([ $md5target = md5_file(self::TEMP_DIR . 'update.tar.gz');
'display' => self::DISPLAY_JSON, // Vérifier si les checksums correspondent
'content' => [ if ($md5origin[0] === $md5target) {
'success' => $md5origin[0] === $md5target, $success = true;
'data' => null $message = "";
] } else {
]); $success = false;
break; $message = 'Erreur de téléchargement ou de somme de contrôle';
if (file_exists(self::TEMP_DIR . 'update.tar.gz')) {
unlink(self::TEMP_DIR . 'update.tar.gz');
http_response_code(500);
}
}
// Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
'content' => [
'success' => $success,
'data' => json_encode($message, JSON_UNESCAPED_UNICODE)
]
]);
break;
// Installation // Installation
case 3: case 3:
$success = true; $success = true;
// Check la réécriture d'URL avant d'écraser les fichiers $message = '';
$rewrite = helper::checkRewrite();
// Décompression et installation // Check la réécriture d'URL avant d'écraser les fichiers
try { if (helper::checkRewrite()) {
// Décompression dans le dossier de fichier temporaires touch(self::DATA_DIR . '.rewrite');
$pharData = new PharData(self::TEMP_DIR . 'update.tar.gz'); }
$pharData->decompress();
// Installation // Décompression et installation
$pharData->extractTo(__DIR__ . '/../../../', null, true); try {
} catch (Exception $e) { // Décompression dans le dossier de fichier temporaires
$success = $e->getMessage(); $pharData = new PharData(self::TEMP_DIR . 'update.tar.gz');
} $pharData->decompress();
// Nettoyage du dossier // Installation
if (file_exists(self::TEMP_DIR . 'update.tar.gz')) { $pharData->extractTo(__DIR__ . '/../../../', null, true);
unlink(self::TEMP_DIR . 'update.tar.gz'); } catch (Exception $e) {
} $message = $e->getMessage();
if (file_exists(self::TEMP_DIR . 'update.tar')) { $success = false;
unlink(self::TEMP_DIR . 'update.tar'); http_response_code(500);
} }
// Valeurs en sortie
$this->addOutput([ // Nettoyage du dossier
'display' => self::DISPLAY_JSON, if (file_exists(self::TEMP_DIR . 'update.tar.gz')) {
'content' => [ unlink(self::TEMP_DIR . 'update.tar.gz');
'success' => $success, }
'data' => $rewrite if (file_exists(self::TEMP_DIR . 'update.tar')) {
] unlink(self::TEMP_DIR . 'update.tar');
]); }
break; // Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
'content' => [
'success' => $success,
'data' => json_encode($message, JSON_UNESCAPED_UNICODE)
]
]);
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 /**
$fileContent = file_get_contents('.htaccess'); * Restaure le fichier htaccess
$rewriteData = PHP_EOL . */
'# URL rewriting' . PHP_EOL . // Recopie htaccess
'<IfModule mod_rewrite.c>' . PHP_EOL . if (
"\tRewriteEngine on" . PHP_EOL . $this->getData(['config', 'autoUpdateHtaccess']) === true
"\tRewriteBase " . helper::baseUrl(false, false) . PHP_EOL . ) {
"\tRewriteCond %{REQUEST_FILENAME} !-f" . PHP_EOL . // L'écraser avec le backup
"\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL . $success = copy('.htaccess.bak', '.htaccess');
"\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL . if ($success === false) {
'</IfModule>' . PHP_EOL . $message = helper::translate('La copie de sauvegarde du fichier htaccess n\'a pas été restaurée !');
'# URL rewriting' . PHP_EOL; http_response_code(500);
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent); }
file_put_contents( // Effacer le backup
'.htaccess', unlink('.htaccess.bak');
$fileContent } else {
); /**
} * Restaure la réécriture d'URL
// Recopie htaccess */
if ( if (file_exists(self::DATA_DIR . '.rewrite')) { // Ajout des lignes dans le .htaccess
$this->getData(['config', 'autoUpdateHtaccess']) && $fileContent = file_get_contents('.htaccess');
$success && file_exists('.htaccess.bak') $rewriteData = PHP_EOL .
) { '# URL rewriting' . PHP_EOL .
// L'écraser avec le backup '<IfModule mod_rewrite.c>' . PHP_EOL .
$success = copy('.htaccess.bak', '.htaccess'); "\tRewriteEngine on" . PHP_EOL .
// Effacer le backup "\tRewriteBase " . helper::baseUrl(false, false) . PHP_EOL .
unlink('.htaccess.bak'); "\tRewriteCond %{REQUEST_FILENAME} !-f" . PHP_EOL .
} "\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL .
// Valeurs en sortie "\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL .
$this->addOutput([ '</IfModule>' . PHP_EOL .
'display' => self::DISPLAY_JSON, '# URL rewriting' . PHP_EOL;
'content' => [ $fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
'success' => $success, $success = $this->secure_file_put_contents(
'data' => null '.htaccess',
] $fileContent
]); );
break; unlink(self::DATA_DIR . '.rewrite');
}
}
/**
* 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) {
if (
isset($defaultLanguages[$key]['date']) &&
$defaultLanguages[$key]['date'] > $value['date'] &&
isset($defaultLanguages[$key]['version']) &&
$defaultLanguages[$key]['version'] >= $value['version']
) {
copy('core/module/install/ressource/i18n/' . $key . '.json', self::I18N_DIR . $key . '.json');
$this->setData(['language', $key, $defaultLanguages[$key]]);
}
}
// Sauvegarde le message dans le journal
if (!empty($message)) {
$this->saveLog($message);
}
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_JSON,
'content' => [
'success' => $success,
'data' => json_encode($message, JSON_UNESCAPED_UNICODE)
]
]);
}
} }
} }
@ -387,13 +449,31 @@ class install extends common
*/ */
public function update() public function update()
{ {
// Nouvelle version // Action interdite
self::$newVersion = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/version'); if (
// Valeurs en sortie $this->getUser('permission', __CLASS__, __FUNCTION__) !== true
$this->addOutput([ ) {
'display' => self::DISPLAY_LAYOUT_LIGHT, // Valeurs en sortie
'title' => helper::translate('Mise à jour'), $this->addOutput([
'view' => 'update' 'access' => false
]); ]);
} else {
// Nouvelle version
self::$newVersion = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/version');
// Variable de version
if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) {
self::$updateButtonText = helper::translate('Mise à jour');
}
// Valeurs en sortie
$this->addOutput([
'display' => self::DISPLAY_LAYOUT_LIGHT,
'title' => helper::translate(self::$updateButtonText),
'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' => 11600, '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' => [
@ -90,12 +72,12 @@ class init extends common
], ],
'droid-sans-2' => [ 'droid-sans-2' => [
'name' => 'Droid Sans', 'name' => 'Droid Sans',
'font-family' => '\'Droid Sans\', sans-serif', 'font-family' => '\'Droid Sans\', sans-serif',
'resource' => 'https://fonts.cdnfonts.com/css/droid-sans-2' 'resource' => 'https://fonts.cdnfonts.com/css/droid-sans-2'
], ],
'droid-serif-2' => [ 'droid-serif-2' => [
'name' => 'Droid Serif', 'name' => 'Droid Serif',
'font-family' => '\'Droid Serif\', serif', 'font-family' => '\'Droid Serif\', serif',
'resource' => 'https://fonts.cdnfonts.com/css/droid-serif-2' 'resource' => 'https://fonts.cdnfonts.com/css/droid-serif-2'
], ],
'indie-flower' => [ 'indie-flower' => [
@ -175,39 +157,8 @@ 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' => [
'backgroundColor' => 'rgba(236, 239, 241, 1)', 'backgroundColor' => 'rgba(236, 239, 241, 1)',
'image' => '', 'image' => '',
@ -330,12 +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' => [],
'language' => [
"fr_FR" => [
"version" => 13007,
"date" => 1699354723
],
"es" => [
"version" => 13007,
"date" => 1699354723
],
"en_EN" => [
"version" => 13007,
"date" => 1699354723
]
],
'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',
@ -345,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!',
@ -372,8 +801,9 @@ 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' => 'HomePage', 'title' => 'Home page',
'shortTitle' => 'Home', 'shortTitle' => 'Home',
'block' => '12', 'block' => '12',
'barLeft' => '', 'barLeft' => '',
@ -386,12 +816,11 @@ class init extends common
'js' => '' 'js' => ''
] ]
], ],
'html' => 'Welcome in this ZiiCMS, 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',
@ -408,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',
@ -435,13 +865,14 @@ 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',
'block' => '12', 'block' => '12',
'barLeft' => '', 'barLeft' => '',
'barRight' => '', 'barRight' => '',
'displayMenu' => 'none', 'displayMenu' => 'none',
'hideMenuSide' => false, 'hideMenuSide' => false,
'hideMenuChildren' => false, 'hideMenuChildren' => false,
'extraPosition' => false, 'extraPosition' => false,
@ -462,13 +893,14 @@ 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',
'block' => '12', 'block' => '12',
'barLeft' => '', 'barLeft' => '',
'barRight' => '', 'barRight' => '',
'displayMenu' => 'none', 'displayMenu' => 'none',
'hideMenuSide' => false, 'hideMenuSide' => false,
'hideMenuChildren' => false, 'hideMenuChildren' => false,
'extraPosition' => false, 'extraPosition' => false,
@ -489,13 +921,14 @@ 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',
'block' => '4-8', 'block' => '4-8',
'barLeft' => 'barre', 'barLeft' => 'barre',
'barRight' => '', 'barRight' => '',
'displayMenu' => 'none', 'displayMenu' => 'none',
'hideMenuSide' => false, 'hideMenuSide' => false,
'hideMenuChildren' => false, 'hideMenuChildren' => false,
'extraPosition' => false, 'extraPosition' => false,
@ -516,13 +949,14 @@ 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',
'block' => '9-3', 'block' => '9-3',
'barLeft' => '', 'barLeft' => '',
'barRight' => 'barrelateraleavecmenu', 'barRight' => 'barrelateraleavecmenu',
'displayMenu' => 'none', 'displayMenu' => 'none',
'hideMenuSide' => false, 'hideMenuSide' => false,
'hideMenuChildren' => false, 'hideMenuChildren' => false,
'extraPosition' => false, 'extraPosition' => false,
@ -543,13 +977,14 @@ 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',
'block' => '12', 'block' => '12',
'barLeft' => '', 'barLeft' => '',
'barRight' => '', 'barRight' => '',
'displayMenu' => 'none', 'displayMenu' => 'none',
'hideMenuSide' => false, 'hideMenuSide' => false,
'hideMenuChildren' => false, 'hideMenuChildren' => false,
'extraPosition' => false, 'extraPosition' => false,
@ -570,13 +1005,14 @@ 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',
'block' => '12', 'block' => '12',
'barLeft' => '', 'barLeft' => '',
'barRight' => '', 'barRight' => '',
'displayMenu' => 'none', 'displayMenu' => 'none',
'hideMenuSide' => false, 'hideMenuSide' => false,
'hideMenuChildren' => false, 'hideMenuChildren' => false,
'extraPosition' => false, 'extraPosition' => false,
@ -598,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',
@ -625,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',
@ -652,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',
@ -679,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',
@ -705,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',
@ -734,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',
@ -762,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',
@ -789,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',
@ -816,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',
@ -854,17 +1299,17 @@ 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,
'commentClose' => false, 'commentClose' => false,
'commentNotification' => false, 'commentNotification' => false,
'commentGroupNotification' => 1 'commentGroupNotification' => 1
], ],
'mon-deuxieme-article' => [ 'mon-deuxieme-article' => [
'closeComment' => false, 'closeComment' => false,
@ -874,17 +1319,17 @@ 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,
'commentClose' => false, 'commentClose' => false,
'commentNotification' => false, 'commentNotification' => false,
'commentGroupNotification' => 1 'commentGroupNotification' => 1
], ],
'mon-troisieme-article' => [ 'mon-troisieme-article' => [
'closeComment' => true, 'closeComment' => true,
@ -894,17 +1339,17 @@ 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,
'commentClose' => false, 'commentClose' => false,
'commentNotification' => false, 'commentNotification' => false,
'commentGroupNotification' => 1 'commentGroupNotification' => 1
], ],
], ],
], ],
@ -916,7 +1361,9 @@ class init extends common
'directory' => self::FILE_DIR . 'source/galerie/landscape', 'directory' => self::FILE_DIR . 'source/galerie/landscape',
'homePicture' => 'iceberg.jpg', 'homePicture' => 'iceberg.jpg',
'sort' => 'SORT_ASC', 'sort' => 'SORT_ASC',
'position' => 1 'position' => 1,
'showPageContent' => false,
'fullScreen' => false
], ],
'legend' => [ 'legend' => [
'desertjpg' => 'Un désert', 'desertjpg' => 'Un désert',
@ -935,7 +1382,9 @@ class init extends common
'directory' => self::FILE_DIR . 'source/galerie/space', 'directory' => self::FILE_DIR . 'source/galerie/space',
'homePicture' => 'nebula.jpg', 'homePicture' => 'nebula.jpg',
'sort' => 'SORT_ASC', 'sort' => 'SORT_ASC',
'position' => 2 'position' => 2,
'showPageContent' => false,
'fullScreen' => false
], ],
'legend' => [ 'legend' => [
'earthjpg' => 'La Terre et la Lune', 'earthjpg' => 'La Terre et la Lune',
@ -950,24 +1399,24 @@ class init extends common
], ],
], ],
'theme' => [ 'theme' => [
'thumbAlign' => 'center', 'thumbAlign' => 'center',
'thumbWidth' => '18em', 'thumbWidth' => '18em',
'thumbHeight' => '15em', 'thumbHeight' => '15em',
'thumbMargin' => '.5em', 'thumbMargin' => '.5em',
'thumbBorder' => '.1em', 'thumbBorder' => '.1em',
'thumbOpacity' => '.7', 'thumbOpacity' => '.7',
'thumbBorderColor' => 'rgba(221, 221, 221, 1)', 'thumbBorderColor' => 'rgba(221, 221, 221, 1)',
'thumbRadius' => '.3em', 'thumbRadius' => '.3em',
'thumbShadows' => '1px 1px 10px', 'thumbShadows' => '1px 1px 10px',
'thumbShadowsColor' => 'rgba(125, 125, 125, 1)', 'thumbShadowsColor' => 'rgba(125, 125, 125, 1)',
'legendHeight' => '.375em', 'legendHeight' => '.375em',
'legendAlign' => 'center', 'legendAlign' => 'center',
'legendTextColor' => 'rgba(255, 255, 255, 1)', 'legendTextColor' => 'rgba(255, 255, 255, 1)',
'legendBgColor' => 'rgba(0, 0, 0, .6)', 'legendBgColor' => 'rgba(0, 0, 0, .6)',
'style' => 'site/data/modules/gallery/galeries.css' 'style' => 'site/data/modules/gallery/galeries.css'
], ],
'config' => [ 'config' => [
'versionData' => '3.0' 'versionData' => '3.0'
], ],
], ],
'site-de-zwii' => [ 'site-de-zwii' => [
@ -985,7 +1434,7 @@ class init extends common
'data' => [], 'data' => [],
'input' => [ 'input' => [
[ [
'name' => 'Adresse mail', 'name' => 'Adresse électronique',
'position' => 1, 'position' => 1,
'required' => true, 'required' => true,
'type' => 'mail', 'type' => 'mail',
@ -1015,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 = [
@ -1090,11 +1550,11 @@ class init extends common
<p justify="">Le site internet propose les services suivants :</p> <p justify="">Le site internet propose les services suivants :</p>
<p justify="">Publication</p> <p justify="">Publication</p>
<p justify="">Le site est accessible gratuitement en tout lieu &agrave; tout Utilisateur ayant un acc&egrave;s &agrave; Internet. Tous les frais support&eacute;s par l\'Utilisateur pour acc&eacute;der au service (mat&eacute;riel informatique, logiciels, connexion Internet, etc.) sont &agrave; sa charge.</p> <p justify="">Le site est accessible gratuitement en tout lieu &agrave; tout Utilisateur ayant un acc&egrave;s &agrave; Internet. Tous les frais support&eacute;s par l\'Utilisateur pour acc&eacute;der au service (mat&eacute;riel informatique, logiciels, connexion Internet, etc.) sont &agrave; sa charge.</p>
<p justify="">L&rsquo;Utilisateur non membre n\'a pas acc&egrave;s aux services r&eacute;serv&eacute;s. Pour cela, il doit s&rsquo;inscrire en remplissant le formulaire. En acceptant de s&rsquo;inscrire aux services r&eacute;serv&eacute;s, l&rsquo;Utilisateur membre s&rsquo;engage &agrave; fournir des informations sinc&egrave;res et exactes concernant son &eacute;tat civil et ses coordonn&eacute;es, notamment son adresse email.</p> <p justify="">L&rsquo;Utilisateur non membre n\'a pas acc&egrave;s aux services r&eacute;serv&eacute;s. Pour cela, il doit s&rsquo;inscrire en remplissant le formulaire. En acceptant de s&rsquo;inscrire aux services r&eacute;serv&eacute;s, l&rsquo;Utilisateur membre s&rsquo;engage &agrave; fournir des informations sinc&egrave;res et exactes concernant son &eacute;tat civil et ses coordonn&eacute;es, notamment son Adresse électronique.</p>
<p justify="">Pour acc&eacute;der aux services, l&rsquo;Utilisateur doit ensuite s\'identifier &agrave; l\'aide de son identifiant et de son mot de passe qui lui seront communiqu&eacute;s apr&egrave;s son inscription.</p> <p justify="">Pour acc&eacute;der aux services, l&rsquo;Utilisateur doit ensuite s\'identifier &agrave; l\'aide de son identifiant et de son mot de passe qui lui seront communiqu&eacute;s apr&egrave;s son inscription.</p>
<p justify="">Tout Utilisateur membre r&eacute;guli&egrave;rement inscrit pourra &eacute;galement solliciter sa d&eacute;sinscription en se rendant &agrave; la page d&eacute;di&eacute;e sur son espace personnel. Celle-ci sera effective dans un d&eacute;lai raisonnable.</p> <p justify="">Tout Utilisateur membre r&eacute;guli&egrave;rement inscrit pourra &eacute;galement solliciter sa d&eacute;sinscription en se rendant &agrave; la page d&eacute;di&eacute;e sur son espace personnel. Celle-ci sera effective dans un d&eacute;lai raisonnable.</p>
<p justify="">Tout &eacute;v&eacute;nement d&ucirc; &agrave; un cas de force majeure ayant pour cons&eacute;quence un dysfonctionnement du site ou serveur et sous r&eacute;serve de toute interruption ou modification en cas de maintenance, n\'engage pas la responsabilit&eacute; de www.site.com. Dans ces cas, l&rsquo;Utilisateur accepte ainsi ne pas tenir rigueur &agrave; l&rsquo;&eacute;diteur de toute interruption ou suspension de service, m&ecirc;me sans pr&eacute;avis.</p> <p justify="">Tout &eacute;v&eacute;nement d&ucirc; &agrave; un cas de force majeure ayant pour cons&eacute;quence un dysfonctionnement du site ou serveur et sous r&eacute;serve de toute interruption ou modification en cas de maintenance, n\'engage pas la responsabilit&eacute; de www.site.com. Dans ces cas, l&rsquo;Utilisateur accepte ainsi ne pas tenir rigueur &agrave; l&rsquo;&eacute;diteur de toute interruption ou suspension de service, m&ecirc;me sans pr&eacute;avis.</p>
<p justify="">L\'Utilisateur a la possibilit&eacute; de contacter le site par messagerie &eacute;lectronique &agrave; l&rsquo;adresse email de l&rsquo;&eacute;diteur communiqu&eacute; &agrave; l&rsquo;ARTICLE 1.</p> <p justify="">L\'Utilisateur a la possibilit&eacute; de contacter le site par messagerie &eacute;lectronique &agrave; l&rsquo;Adresse électronique de l&rsquo;&eacute;diteur communiqu&eacute; &agrave; l&rsquo;ARTICLE 1.</p>
<h2>ARTICLE 3 : Collecte des donn&eacute;es</h2> <h2>ARTICLE 3 : Collecte des donn&eacute;es</h2>
<p justify="">Le site est exempt&eacute; de d&eacute;claration &agrave; la Commission Nationale Informatique et Libert&eacute;s (CNIL) dans la mesure o&ugrave; il ne collecte aucune donn&eacute;e concernant les Utilisateurs.</p> <p justify="">Le site est exempt&eacute; de d&eacute;claration &agrave; la Commission Nationale Informatique et Libert&eacute;s (CNIL) dans la mesure o&ugrave; il ne collecte aucune donn&eacute;e concernant les Utilisateurs.</p>
<h2>ARTICLE 4&nbsp;: Propri&eacute;t&eacute; intellectuelle</h2> <h2>ARTICLE 4&nbsp;: Propri&eacute;t&eacute; intellectuelle</h2>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,490 +0,0 @@
{
"Se déconnecter ?": "Log out?",
"Mettre à jour ?": "Aggiornamento?",
"Confirmez-vous la suppression de cette page ?": "Confermi la cancellazione di questa pagina?",
"Format incorrect": "Formato non corretto",
"Les modifications que vous avez apportées ne seront peut-être pas enregistrées.": "Le modifiche apportate potrebbero non essere salvate",
"Oui": "Sì",
"Non": "No",
"Identifiant": "Nome utente",
"Mot de passe": "Password",
"Confirmation": "Conferma",
"Adresse électronique": "Indirizzo e-mail",
"Prénom": "Nome",
"Nom": "Cognome",
"Ne pas charger l'exemple de site (utilisateurs avancés)": "Non caricare il sito di esempio (utenti avanzati)",
"Type de proxy": "Tipo di proxy",
"Adresse du proxy": "Indirizzo proxy",
"Port du proxy": "Porta proxy",
"Thème": "Tema",
"Installer": "Installa",
"Consulter l'aide en ligne": "Consultare la guida in linea",
"favicon.ico": "favicon.ico",
"Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.": "Considerate di cancellare la cache del browser se la favicon non cambia",
"faviconDark.ico": "faviconDark.ico",
"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.": "Selezionare un'icona adatta a un tema scuro.<br>Ricordarsi di cancellare la cache del browser se la favicon non cambia.",
"Fuseau horaire": "Fuso orario",
"Le fuseau horaire est utile au bon référencement": "Il fuso orario è utile per una buona SEO.",
"Message de consentement aux cookies": "Messaggio di consenso ai cookie",
"Activation obligatoire selon les lois françaises sauf si vous utilisez votre propre système de consentement.": "Attivazione obbligatoria secondo le leggi francesi, a meno che non si utilizzi il proprio sistema di consenso.",
"Apache URL intelligentes": "Apache Smart URLs",
"Supprime le point d'interrogation dans les URL, l'option est indisponible avec les autres serveurs Web": "Rimuove il punto interrogativo negli URL; l'opzione non è disponibile con altri server web",
"Rechercher une mise à jour en ligne": "Cercare un aggiornamento online",
"La vérification est quotidienne. Option désactivée si la configuration du serveur ne le permet pas.": "La verifica è quotidiana. Disattivato se la configurazione del server non lo consente.",
"Préserver le fichier htaccess racine": "Conserva il file htaccess principale",
"Lors d'une mise à jour automatique, conserve le fichier htaccess de la racine du site.": "Durante un aggiornamento automatico, conserva il file htaccess principale del sito.",
"Sauvegarde automatique quotidienne du site": "Backup automatico giornaliero del sito",
"Une archive du dossier /site/data est conservée pendant 30 jours. Activation recommandée": "Un archivio della directory /sito/dati viene conservato per 30 giorni. Attivazione consigliata",
"Site en maintenance": "Sito in mantenimento",
"Clé de l'API <a href='https://app.screenshotapi.net/' target='_blank'>ScreenShotApi</a>": "Chiave API <a href='https://app.screenshotapi.net/' target='_blank'>ScreenShotApi</a>",
"Saisir la clé, puis valider le formulaire avant de cliquer sur le bouton de génération": "Inserire la chiave, quindi convalidare il modulo prima di fare clic sul pulsante di generazione",
"Autoriser les robots à référencer le site": "Consentire ai robot di fare riferimento al sito",
"Facebook": "Facebook",
"Saisissez votre ID : https://www.facebook.com/[ID].": "Inserire il proprio ID: https://www.facebook.com/[ID].",
"Instagram": "Instagram",
"Saisissez votre ID : https://www.instagram.com/[ID].": "Inserire il proprio ID: https://www.instagram.com/[ID].",
"Chaîne Youtube": "Canale Youtube",
"ID de la chaîne : https://www.youtube.com/channel/[ID].": "ID del canale: https://www.youtube.com/channel/[ID].",
"Youtube": "Youtube",
"Saisissez votre ID Utilisateur : https://www.youtube.com/user/[ID].": "Inserire il proprio ID: https://www.youtube.com/user/[ID].",
"Twitter": "Twitter",
"Saisissez votre ID : https://twitter.com/[ID].": "Inserire il proprio ID: https://twitter.com/[ID].",
"Pinterest": "Pinterest",
"Saisissez votre ID : https://pinterest.com/[ID].": "Inserire il proprio ID: https://pinterest.com/[ID].",
"Linkedin": "Linkedin",
"Saisissez votre ID Linkedin : https://fr.linkedin.com/in/[ID].": "Inserire il proprio ID Linkedin: https://fr.linkedin.com/in/[ID].",
"Github": "Github",
"Saisissez votre ID Github : https://github.com/[ID].": "Inserire il proprio ID Github: https://github.com/[ID].",
"Dévoiler le mot de passe": "Svelare il password",
"Le survol d'une icône de l'écran de connexion affiche temporairement le mot de passe.": "Passando il mouse su un'icona nella schermata di accesso si visualizza temporaneamente la password",
"Déconnexion automatique": "Auto Logout",
"Déconnecte les sessions ouvertes précédemment sur d'autres navigateurs ou terminaux. Activation recommandée.": "Disconnette le sessioni precedentemente aperte su altri browser o terminali. Consigliata l'abilitazione",
"Redirection vers la connexion": "Reindirizzamento al login",
"Cette redirection ne concerne que les pages d'administration du site.": "Questo reindirizzamento è solo per le pagine di amministrazione del sito",
"Limitation des tentatives": "Limitazione dei tentativi",
"Blocage après échecs": "Blocco dopo i fallimenti",
"Captcha à la connexion": "Captcha al login",
"Captcha complexe": "captcha complesso",
"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.": "Opzione consigliata per proteggere la connessione. Si applica a tutti i captchas del sito. Il captcha semplice si limita all'aggiunta di numeri da 0 a 10. Il captcha complesso utilizza quattro operazioni su numeri da 0 a 20. Attivazione consigliata.",
"Type de captcha": "Tipo di Captcha",
"Activer la journalisation": "Abilita la registrazione",
"Anonymat des adresses IP": "Anonimato degli indirizzi IP",
"La réglementation française impose un anonymat de niveau 2": "La legge francese richiede l'anonimato di livello 2",
"Activer SMTP": "Attivare SMTP",
"Paramètres à utiliser lorsque votre hébergeur ne propose pas la fonctionnalité d'envoi de mail.": "Impostazioni da utilizzare quando l'host non offre la funzionalità di invio della posta.",
"Adresse SMTP": "Indirizzo SMTP",
"Port SMTP": "Porta SMTP",
"Authentification": "Autenticazione",
"Nom utilisateur": "Nome utente",
"Sécurité": "Sicurezza",
"Nouvelle page ou barre latérale": "Nuova pagina o barra laterale",
"Éditer la page": "Modifica pagina",
"Supprimer la page": "Cancella pagina",
"Gérer les modules": "Gestisci moduli",
"Configuration": "Configurazione",
"Utilisateurs": "Utenti",
"Déconnecter": "Disconnessione",
"Éditer": "Modifica",
"Supprimer": "Cancella",
"Importer des utilisateurs en masse": "Importazione di utenti in blocco",
"Ajouter un utilisateur": "Aggiungere utente",
"Pseudo": "Nickname",
"Signature": "Firma",
"Groupe": "Gruppo",
"Impossible de modifier votre propre groupe.": "Impossibile modificare il proprio gruppo",
"Partage de fichiers autorisé": "Condivisione di file consentita",
"Ce membre pourra téléverser ou télécharger des fichiers dans le dossier 'partage' et ses sous-dossiers": "Questo membro potrà caricare o scaricare file nella cartella 'share' e nelle sue sottocartelle",
"L'identifiant est défini lors de la création du compte, il ne peut pas être modifié.": "Il nome utente viene impostato alla creazione dell'account, non può essere modificato",
"Ancien mot de passe": "Password precedente",
"Nouveau mot de passe": "Nuova password",
"Séparateur": "Separatore",
"Envoyer un message de confirmation": "Invia messaggio di conferma",
"Prévenir l'utilisateur par mail": "Notifica all'utente via e-mail",
"Copie de sites inter-langues": "Copia di siti in più lingue",
"Titre du site": "Titolo del sito",
"Il apparaît dans la barre de titre et les partages sur les réseaux sociaux.": "Appare nella barra del titolo e viene condiviso sui social network",
"Description du site": "Descrizione del sito",
"La description d'une page participe à son référencement, chaque page doit disposer d'une description différente.": "La descrizione di una pagina contribuisce alla sua referenziazione; ogni pagina deve avere una descrizione diversa.",
"Accueil du site": "Home page",
"La première page que vos visiteurs verront.": "La prima pagina che i visitatori vedranno",
"Accès interdit, erreur 403": "Accesso negato, errore 403",
"Cette page ne doit pas apparaître dans l'arborescence du menu. Créez une page orpheline.": "Questa pagina non dovrebbe apparire nell'albero dei menu. Creare una pagina orfana",
"Page inexistante, erreur 404": "La pagina non esiste, errore 404",
"Mentions légales": "Avviso legale",
"Les mentions légales sont obligatoires en France. Une option du pied de page ajoute un lien discret vers cette page.": "Le comunicazioni legali sono obbligatorie in Francia. Un'opzione a piè di pagina aggiunge un link discreto a questa pagina",
"Recherche dans le site": "Cerca nel sito",
"Sélectionnez une page contenant le module 'Recherche'. Une option du pied de page ajoute un lien discret vers cette page.": "Selezionare una pagina contenente il modulo 'Ricerca'. Un'opzione a piè di pagina aggiunge un link discreto a questa pagina.",
"Rechercher": "Ricerca",
"Plan du site": "Mappa del sito",
"Cookies": "Cookies",
"Titre de la fenêtre": "Titolo della finestra",
"Saisissez le titre de la fenêtre de gestion des cookies.": "Inserire il titolo della finestra di gestione dei cookie",
"Bouton de validation": "Pulsante di convalida",
"Cookies Zwii": "Zwii Cookies",
"Saisissez le message pour les cookies déposés par ZwiiCMS, nécessaires au fonctionnement et qui ne nécessitent pas de consentement.": "Inserire il messaggio per i cookie depositati da ZwiiCMS, che sono necessari per il funzionamento e non richiedono consenso.",
"Lien page des mentions légales.": "Link alla pagina delle note legali.",
"Saisissez le texte du lien vers les mentions légales,la page doit être définie dans la configuration du site.": "Inserire il testo del link alla nota legale; la pagina deve essere definita nella configurazione del sito.",
"Pages et les modules de": "Pagine e moduli di",
"Vers": "A",
"Supprimer le module": "Elimina modulo",
"Sauvegarder le module dans le gestionnaire de fichiers": "Salva il modulo nel file manager",
"Sauvegarder et télécharger le module": "Salva e scarica il modulo",
"Sauvegarder les données du module dans le gestionnaire de fichiers": "Salva i dati del modulo nel file manager",
"'Sauvegarder et télécharger les données du module": "Salva e scarica i dati del modulo",
"Installer depuis le catalogue en ligne": "Installa dal catalogo online",
"Installer depuis une archive": "Installa da archivio",
"Mettre à jour le module orphelin": "Aggiornamento del modulo orfano",
"Télécharger le module dans le gestionnaire de fichiers": "Scarica il modulo nel file manager",
"Connexion": "Login",
"Ajouter une fonte": "Aggiungi un carattere",
"Fonte en ligne": "Font online",
"Fonte installée": "Font installata",
"Identifiant (sans espace ni majuscule)": "Identificatore (senza spazi o lettere maiuscole)",
"Famille": "Famiglia",
"Url du fichier de fonte": "Url del file di font",
"Réinitialiser avec le thème par défaut": "Reimpostare il tema predefinito",
"Arrière plan": "Sfondo",
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence.": "Colore visibile senza immagine. Il cursore orizzontale imposta il livello di trasparenza",
"Titres": "Titoli",
"Texte": "Testo",
"Arrière plan des champs": "Sfondo dei campi",
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence. La couleur du texte est automatique.": "Colore visibile senza immagine. Il cursore orizzontale imposta il livello di trasparenza. Il colore del testo è automatico",
"Bordure des champs": "Bordo campo",
"Bouton Aide": "Pulsante di aiuto",
"Bouton retour": "Pulsante posteriore",
"Bouton standard": "Pulsante standard",
"Bouton effacement": "Pulsante di cancellazione",
"Bouton validation": "Pulsante di convalida",
"Police du texte": "Font di testo",
"Taille": "Dimensione",
"Police des titres": "Font del titolo",
"Réinitialiser la feuille de style": "Reimpostare il foglio di stile",
"Rester connecté sur ce navigateur": "Rimani connesso su questo browser",
"Effacer la page": "Cancella pagina",
"Titre": "Titolo",
"Titre court": "Titolo breve",
"Le titre court est affiché dans les menus. Il peut être identique au titre de la page.": "Il titolo breve viene visualizzato nei menu. Può essere identico al titolo della pagina",
"Titre masqué dans la page": "Titolo nascosto nella pagina",
"Fil d'Ariane dans le titre": "Breadcrumb nel titolo",
"Affiche le nom de la page parente suivi du nom de la page, le titre ne doit pas être masqué.": "Visualizza il nome della pagina madre seguito dal nome della pagina; il titolo non deve essere nascosto",
"Position": "Posizione",
"'Ne pas afficher' crée une page orpheline non accessible par le biais des menus.": "'Non mostrare' crea una pagina orfana a cui non si può accedere tramite i menu",
"Page parent": "Pagina madre",
"Emplacement :": "Posizione:",
"Le menu accessoire est aligné à droite de la barre de menu, c'est un emplacement réservé aux drapeaux et au bouton de connexion.": "Il menu accessorio è allineato a destra della barra dei menu, è un segnaposto per le bandiere e il pulsante di accesso.",
"Page non cliquable": "Pagina non cliccabile",
"Option active en mode déconnecté uniquement, les pages enfants sont visibles et accessibles.": "Opzione attiva solo in modalità offline, le pagine dei bambini sono visibili e accessibili",
"S'ouvre dans un nouvel onglet": "Si apre in una nuova scheda",
"Apparence": "Aspetto",
"Sélectionnez une image ou une icône de petite dimension": "Selezionare un'immagine o un'icona piccola",
"Masquer les pages enfants dans le menu horizontal": "Nascondi le pagine figlio nel menu orizzontale",
"Masquer la page et les pages enfants dans le menu d'une barre latérale": "Nascondi pagina e pagine figlio in un menu della barra laterale",
"La page est affichée dans un menu horizontal mais pas dans le menu vertical d'une barre latérale.": "La pagina viene visualizzata in un menu orizzontale ma non nel menu verticale di una barra laterale.",
"Module": "Modulo",
"En cas de changement de module, les données du module précédent seront supprimées.": "Quando si cambia il modulo, i dati del modulo precedente vengono cancellati.",
"Position du module": "Posizione del modulo",
"En position libre ajoutez le module en plaçant [MODULE] à l'endroit voulu dans votre page.": "In posizione libera aggiungere il modulo posizionando [MODULO] nel punto desiderato della pagina.",
"Feuille de style spécifique à la page.": "Foglio di stile specifico della pagina.",
"Instructions JS ou jquery spécifiques à la page.": "Istruzioni JS o jquery specifiche della pagina.",
"Gabarits de page - Barre latérale": "Modelli di pagina - Barra laterale",
"Pour définir la page comme barre latérale, choisissez l'option dans la liste.": "Per impostare la pagina come barra laterale, scegliere l'opzione dall'elenco.",
"Barre latérale gauche :": "Barra laterale sinistra:",
"Barre latérale droite :": "Barra laterale destra:",
"Contenu du menu vertical": "Contenuto del menu verticale",
"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.": "Per impostazione predefinita, il menu viene visualizzato DOPO il contenuto della pagina. Per posizionarlo in una posizione specifica, inserire [MENU] nel contenuto della pagina.",
"Groupe requis pour accéder à la page :": "Gruppo richiesto per accedere alla pagina:",
"Méta-titre": "Meta titolo",
"Méta-description": "Meta descrizione",
"Module de la page": "Modulo pagina",
"Paramètres de la sauvegarde": "Impostazioni di backup",
"Sécurité de la connexion": "Sicurezza della connessione",
"Journalisation": "Registrazione",
"Paramètres": "Impostazioni",
"SMTP": "SMTP",
"Archive à restaurer": "Archivio da ripristinare",
"Mise à jour automatisée": "Aggiornamento automatico",
"Capture d'écran Open Graph": "Schermata Open Graph",
"Référencement": "Referenziamento",
"Réseaux sociaux": "Reti sociali",
"Renseignez les champs ci-dessous pour finaliser l'installation.": "Compilare i campi sottostanti per completare l'installazione.",
"Compte administrateur": "Account amministratore",
"Options avancées": "Opzioni avanzate",
"Mise à jour de ZwiiCMS": "Aggiornare ZwiiCMS",
"vers ZwiiCMS": "a ZwiiCMS",
"Afin d'assurer le bon fonctionnement de Zwii, veuillez ne pas fermer cette page avant la fin de l'opération.": "Per garantire il corretto funzionamento di Zwii, non chiudere questa pagina fino al completamento dell'operazione.",
"1/4 : Préparation...": "1/4 : Preparazione...",
"2/4 : Téléchargement...": "2/4 : Download...",
"3/4 : Installation...": "3/4: Installazione...",
"4/4 : Configuration...": "4/4 : Configurazione...",
"Une erreur est survenue lors de l'étape :": "Si è verificato un errore nel passaggio:",
"Mise à jour terminée avec succès.": "Aggiornamento completato con successo.",
"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.": "Il nostro sito è attualmente in manutenzione. Ci scusiamo per l'inconveniente e stiamo facendo del nostro meglio per tornare presto",
"Installer les données d'un module": "Installazione di dati da un modulo",
"Sauvegarde": "Backup",
"Modules orphelins": "Moduli orfani",
"Modules configurés": "Moduli configurati",
"Modules installés": "Moduli installati",
"Données des modules": "Dati dei moduli",
"Version n°": "Versione n°",
"Du": "Da",
"Auteur :": "Autore:",
"Licence :": "Licenza:",
"Installer ou mettre à jour un module téléchargé": "Installare o aggiornare un modulo scaricato",
"Couleurs": "Colori",
"Mise en forme du texte": "Formattazione del testo",
"Image": "Immagine",
"Identité de la fonte": "Identità del carattere",
"Disposition": "Layout",
"Contenu personnalisé": "Contenuto personalizzato",
"Informations": "Informazioni",
"Mise en forme du titre": "Formattazione del titolo",
"Papier peint": "Sfondo",
"Largeur de l'image :": "Larghezza immagine :",
"Hauteur de l'image :": "Altezza immagine:",
"largeur du site": "Larghezza del sito",
"Ratio :": "Rapporto :",
"largeur de site :": "larghezza del sito:",
"Installer un thème archivé (site ou administration)": "Installa il tema archiviato (sito o amministrazione)",
"Sauvegarde du thème dans le": "Salva tema nel",
"gestionnaire de fichiers": "File manager",
"Télécharger le thème": "Scarica il tema",
"Contenu": "Contenuto",
"Mise en forme des titres": "Formattazione dei titoli",
"Copie des traductions rédigées": "Copia di traduzioni scritte",
"Identité": "Identità",
"Permissions :": "Autorizzazioni:",
"Accès aux pages privées": "Accesso alle pagine private",
"Ajout - Édition - Suppression de fichiers": "Aggiungi - Modifica - Elimina file",
"Administration complète du site": "Amministrazione completa del sito",
"Importation de fichier plat CSV": "Importazione di un file piatto CSV",
"Confirmer la suppression de cet utilisateur": "Confermare la cancellazione di questo utente",
"Sauvegarde générée avec succès.": "Backup generato con successo",
"Erreur : sauvegarde non générée !": "Errore: backup non generato!",
"Sauvegarder": "Salva",
"La sauvegarde des fichiers peut prendre du temps. Continuer ?": "Il backup dei file può richiedere del tempo. Continuare?",
"Supprimer toutes les sauvegardes automatiques ?": "Cancellare tutti i backup automatici?",
"Préparation de la mise à jour": "Preparazione dell'aggiornamento",
"Téléchargement et validation de l'archive": "Scaricare e convalidare l'archivio",
"Installation": "Installazione",
"Confirmer la suppression de la page": "Confermare la cancellazione della pagina",
"Confirmer la suppression des données du module": "Confermare la cancellazione dei dati del modulo",
"Ne pas afficher": "Non visualizzare",
"Au début": "All'inizio",
"Après": "Dopo",
"Confirmer la désinstallation du module": "Confermare la disinstallazione del modulo",
"Confirmer la dissociation du module de cette page": "Confermare la dissociazione del modulo da questa pagina",
"Sauvegarder les données du site": "Salva i dati del sito",
"Restaurer les données du site": "Ripristino dei dati del sito",
"Vider dossier sauvegardes auto": "Svuota la cartella di backup automatico",
"Copier sauvegardes auto": "Copia dei backup automatici",
"Réinstaller": "Reinstallare",
"Script dans head": "Scrittura in testa",
"Script dans body": "Script nel corpo",
"Générer une capture Open Graph": "Generare l'acquisizione di Open Graph",
"Générer sitemap.xml et robots.txt": "Generare sitemap.xml e robots.txt",
"Télécharger la liste": "Scaricare l'elenco",
"Réinitialiser la liste": "Reset del elenco",
"Télécharger le journal": "Scaricare log",
"Réinitialiser le journal": "Registrazione reset",
"Fond du sous-menu": "Sfondo del sottomenu",
"Liens": "Link",
"Arrière plan des blocs": "Sfondo dei blocchi",
"Bordure des blocs": "Confini dei blocchi",
"Boutons": "Pulsanti",
"Thème du site": "Tema del sito",
"Thème de l'administration": "Tema dell'amministrazione",
"Appliquer": "Applicare",
"Enregistrer": "Salva",
"Éditeur CSS": "Editor CSS",
"Éditeur JS": "Editor JS",
"Ne pas saisir les balises": "Non inserire i tag",
"Accueil": "Casa",
"Aide": "Aiuto",
"Fontes": "Caratteri",
"Gestion": "Gestione",
"Administration": "Amministrazione",
"Langues": "Lingue",
"Langues de l'interface": "Linguaggi di interfaccia",
"Éditer les dialogues": "Modifica finestre",
"Langues installées": "Lingue installate",
"Langues du site": "Lingue del sito",
"Interface": "Interfaccia",
"Langue de l'administration": "Lingua dell'amministrazione",
"Dans quelle langue utiliserez-vous Zwii ?": "In quale lingua utilizzerete Zwii?",
"Maintenance": "Manutenzione",
"Scripts externes": "Script esterni",
"Version": "Versione",
"Catégorie": "Categoria",
"Page": "Pagina",
"Page associée": "Pagina correlata",
"Copie de contenus localisés": "Copia del contenuto localizzato",
"Nouveau contenu localisé": "Nuovo contenuto localizzato",
"Sélectionnez une langue": "Selezionare una lingua",
"Langues disponibles": "Lingue disponibili",
"Sélectionnez la langue à copier vers une langue cible": "Selezionare la lingua da copiare in una lingua di destinazione",
"De": "Da",
"vers": "A",
"Action interdite": "Azione vietata",
"Modifications enregistrées": "Modifiche salvate",
"Éditeur de script %s": "Script Editor %s",
"Journal réinitialisé avec succès": "Registro resettato con successo",
"Aucun journal à effacer": "Nessun registro da eliminare",
"Aucun fichier journal à télécharger": "Nessun file di log da scaricare",
"Aucune liste noire à télécharger": "Nessuna lista nera da scaricare",
"Liste noire réinitialisée avec succès": "Lista nera resettata con successo",
"Aucune liste noire à effacer": "Nessuna lista nera da cancellare",
"Copie terminée avec succès": "Copia completata con successo",
"Copie terminée avec des erreurs": "Copia completata con errori",
"Fichiers effacés": "File eliminati",
"Restaurer": "Ripristino",
"Restauration effectuée avec succès": "Ripristino completato con successo",
"Échecs": "Fallito",
"Erreur inconnue": "Errore sconosciuto",
"Archive invalide": "Archivio non valido",
"URL incorrecte": "URL non corretto",
"Paramètres de la localisation": "Impostazioni di posizione",
"Mise à jour": "Aggiornamento",
"Gestion des modules": "Gestione dei moduli",
"Installer un module": "Installare un modulo",
"Pied de page": "Piè di pagina",
"Bannière": "Banner",
"Thèmes": "Temi",
"Menu": "Menu",
"Site": "Sito",
"Gestion des thèmes": "Gestione del tema",
"Nouvel utilisateur": "Nuovo utente",
"Mot de passe oublié": "Password dimenticata",
"Réinitialisation du mot de passe": "Reimpostare la password",
"Importation d'utilisateurs": "Importazione di utenti",
"Contenu avancé": "Contenuto avanzato",
"Mise en page": "Layout",
"Permission et référencement": "Permessi e riferimenti",
"Le curseur horizontal règle le niveau de transparence, le placer tout à la gauche pour un surlignement invisible.": "Il cursore orizzontale regola il livello di trasparenza; posizionarlo all'estrema sinistra per ottenere un'evidenziazione invisibile",
"Contenu multilangues": "Contenuto multilingue",
"Multilangue": "Multilingua",
"Extension": "Estensione",
"Permission": "Autorizzazione",
"Emplacement dans le menu": "Posizione nel menu",
"Réseau": "Rete",
"Étiquettes des pages spéciales": "Etichette di pagina speciali",
"Identité du site": "Identità del sito",
"Message d'acceptation des Cookies": "Messaggio di accettazione dei cookie",
"Favicon thème sombre": "Favicon tema scuro",
"Apache URL intelligent": "Apache URL smart",
"Liste noire": "Liste nera",
"Ajout - Édition - Suppression de pages": "Aggiungere - Modificare - Cancellare pagine",
"Importer": "Importazione",
"Clé de l'API <a href=\"https://app.screenshotapi.net/\" target=\"_blank\">ScreenShotApi</a>": "Chiave API<a href=\"https://app.screenshotapi.net/\" target=\"_blank\">ScreenShotApi</a>",
"Créez un compte gratuit, recopier la clé , puis valider le formulaire avant de cliquer sur le bouton de génération": "Creare un account gratuito, copiare la chiave, quindi convalidare il modulo prima di fare clic sul pulsante genera",
"La clé de l'API ne peut pas être vide": "La chiave API non può essere vuota",
"Service en ligne inaccessible": "Servizio online inaccessibile",
"La carte du site a été mise à jour": "La mappa del sito è stata aggiornata",
"Echec de l'écriture, vérifiez les permissions": "Scrittura fallita, controllare i permessi",
"Capture d'écran générée avec succès": "Screenshot generato con successo",
"Inclure le contenu du gestionnaire de fichiers": "Includi il contenuto del gestore del sito",
"Si le contenu du gestionnaire de fichiers est très volumineux, mieux vaut une copie par FTP.": "Se il contenuto del file manager è molto grande, meglio copiare via FTP",
"Retour": "Indietro",
"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'archivio è stato scaricato nel file manager. Gli archivi inferiori alla versione 9 non sono accettati.",
"Préserver les comptes des utilisateurs déjà installés": "Conserva gli account utente già installati",
"Éditeur de script dans Head": "Editor di script in Head.",
"Valider": "Convalidare",
"Éditeur de script dans Body": "Editor di script in Body",
"FontId": "FontId",
"Affectation": "Assegnazione",
"Origine": "Origine",
"Bouton Standard": "Pulsante standard",
"Configuration du module": "Configurazione del modulo",
"Installation terminée": "Installazione completata",
"Jeton invalide": "Token non valido",
"Suppression interdite": "Cancellazione vietata",
"Page dupliquée": "Pagina duplicata",
"Page et module dupliqués": "Pagina e modulo duplicati",
"Nouvelle page créée": "Nuova pagina creata",
"Suppression interdite, page active dans la configuration du site": "Cancellazione vietata, pagina attiva nella configurazione del sito",
"Impossible de supprimer une page contenant des pages enfants": "Impossibile cancellare una pagina contenente pagine figlio",
"Page supprimée": "Pagina eliminata",
"La suppression a échoué": "Cancellazione fallita",
"Le module %s est désinstallé, il reste peut-être des données dans %s": "Il modulo %s è stato disinstallato, potrebbero essere rimasti dei dati in %s",
"Archive invalide, le descripteur est absent": "Archivio non valido, manca il descrittore",
"Archive invalide, les dossiers ne correspondent pas au descripteur": "Archivio non valido, le cartelle non corrispondono al descrittore",
"Archive invalide, l'écriture dans le dossier core est interdite": "Archivio non valido, la scrittura nella cartella core non è consentita",
"Archive invalide, le fichier de classe est absent": "Archivio non valido, manca il file di classe.",
"La version installée est plus récente": "La versione installata è più recente.",
"actualisé": "aggiornato",
"installé": "installato",
"Erreur inconnue, le module n'est pas installé": "Errore sconosciuto, modulo non installato",
"Impossible d'ouvrir l'archive": "Impossibile aprire l'archivio",
"Archive copiée dans le dossier Modules du gestionnaire de fichier": "Archivio copiato nella cartella Modulo del file manager.",
"Erreur de copie": "Errore di copia",
"Le module %s de la page %s a été supprimé": "Il modulo %s a pagina %s è stato cancellato",
"Le module %s a été %s": "Il modulo %s è stato %s",
"Données importées": "Dati importati",
"Sélectionnez au moins un contenu à afficher": "Selezionare almeno un contenuto da visualizzare",
"Fonte créée":"Font creato",
"Fonte non créée, ressource absente !": "Font non creato, risorsa non presente!",
"Fonte actualisée": "Font aggiornato",
"Fonte supprimée": "Font cancellato",
"Thème importé": "Tema importato",
"Erreur d'extraction, vérifiez les permissions": "Errore di estrazione, controllare le autorizzazioni",
"Archive de thème invalide": "Archivio tema non valido",
"Archive non spécifiée ou introuvable": "Archivio non specificato o non trovato",
"sauvegardé avec succès": "backup riuscito",
"Données %s copiées vers %s": "Dati %s copiati in %s",
"Erreur de copie, vérifiez les permissions": "Errore di copia, controllare le autorizzazioni",
"Les langues sélectionnées sont identiques": "Le lingue selezionate sono identiche",
"Erreur d'URL": "Errore URL",
"Traduction supprimée": "Traduzione cancellata",
"Impossible de supprimer votre propre compte": "Impossibile eliminare il proprio account",
"Utilisateur supprimé": "Utente cancellato",
"Incorrect": "Non corretto",
"Un mail a été envoyé pour confirmer la réinitialisation": "È stata inviata un'e-mail per confermare il reset",
"Utilisateur inexistant": "L'utente non esiste",
"Compte verrouillé": "Account bloccato",
"Captcha, identifiant ou mot de passe incorrects": "Captcha, nome utente o password non corretti",
"Seul un administrateur peut se connecter lors d'une maintenance": "Solo un amministratore può accedere durante la manutenzione",
"Bienvenue %s %s": "Benvenuto %s %s",
"Accès bloqué %d minutes": "Accesso bloccato per %d minuti",
"Déconnexion !": "Logout!",
"Nouveau mot de passe enregistré": "Nuova password salvata",
"Rien à importer, erreur de format ou fichier incorrect": "Niente da importare, errore di formato o file non corretto",
"Importation effectuée": "Importazione completata",
"Erreur de lecture, vérifiez les permissions": "Errore di lettura, controllare le autorizzazioni",
"Sécurité désactivée": "Sicurezza disabilitata",
"3 tentatives": "3 tentativi",
"5 tentatives": "5 tentativi",
"10 tentatives": "10 tentativi",
"5 minutes": "5 minuti",
"10 minutes": "10 minuti",
"15 minutes": "15 minuti",
"Complète": "Completo",
"Niveau 1 (192.168.12.x)": "Livello 1 (192.168.12.x)",
"Niveau 2 (192.168.x.x)": "Livello 2 (192.168.x.x)",
"Niveau 3 (192.x.x.x)": "Livello 3 (192.x.x.x)",
"Chiffres": "Numeri",
"Lettres": "Lettere",
"Icône": "Icona",
"Icône avec bulle de texte": "Icona con bolla di testo",
"Après le contenu de la page": "Dopo il contenuto della pagina",
"Avant le contenu de la page": "Prima del contenuto della pagina",
"À l'emplacement du mot clé [MODULE] dans la page": "Nella posizione della parola chiave [MODULO] nella pagina",
"Page standard": "Pagina standard",
"Barre 1/3 - page 2/3": "Barra 1/3 - pagina 2/3",
"Page 2/3 - barre 1/3": "Pagina 2/3 - barra 1/3",
"Barre 1/4 - page 3/4": "Barra 1/4 - pagina 3/4",
"Page 3/4 - barre 1/4": "Pagina 3/4 - barra 1/4",
"Barre 1/4 - page 1/2 - barre 1/4": "Barra 1/4 - pagina 1/2 - barra 1/4",
"Barre 2/12 - page 7/12 - barre 3/12": "Barra 2/12 - pagina 7/12 - barra 3/12",
"Barre 3/12 - page 7/12 - barre 2/12": "Barra 3/12 - pagina 7/12 - barra 2/12",
"Barre latérale": "Barra laterale",
"Aucun menu": "Nessun menu",
"Le menu horizontal intégral": "Il menu orizzontale completo",
"Le sous-menu de la page parente": "Il sottomenu della pagina madre",
"Menu standard": "Menu standard",
"Menu accessoire": "Menu accessorio",
"Activer": "Attivare",
"Importer dans": "Importazione in",
"Archive": "Archivio",
"Archive ZIP": "Archivio ZIP",
"Langue par défaut": "Lingua predefinita",
"Langue du site sélectionnée": "Lingua del sito selezionata"
}

View File

@ -1,492 +0,0 @@
{
"Adresse électronique": "Endereço de email",
"Une archive du dossier /site/data est conservée pendant 30 jours. Activation recommandée": "Um arquivo da pasta /site/data é mantido por 30 dias. Ativação recomendada",
"Déconnecte les sessions ouvertes précédemment sur d'autres navigateurs ou terminaux. Activation recommandée.": "Desconecta sessões previamente abertas em outros navegadores ou terminais. Ativação recomendada.",
"Sauvegarder les données du module dans le gestionnaire de fichiers": "Salve os dados do módulo no gerenciador de arquivos",
"'Sauvegarder et télécharger les données du module": "Salvar e baixar dados do módulo",
"Le menu accessoire est aligné à droite de la barre de menu, c'est un emplacement réservé aux drapeaux et au bouton de connexion.": "O menu de acessórios está alinhado à direita da barra de menus, é um espaço reservado para sinalizadores e o botão de login.",
"Ne pas saisir les balises": "Não insira tags",
"Langues de l'interface": "Idiomas da interface",
"Éditer les dialogues": "Editar caixas de diálogo",
"Langues du site": "Idiomas do site",
"Page associée": "página relacionada",
"Multilangue": "Multilíngue",
"Rien à importer, erreur de format ou fichier incorrect": "Nada para importar, erro de formatação ou arquivo incorreto",
"Sécurité désactivée": "Segurança desativada",
"3 tentatives": "3 tentativas",
"5 tentatives": "5 tentativas",
"10 tentatives": "10 tentativas",
"5 minutes": "5 minutos",
"10 minutes": "10 minutos",
"15 minutes": "15 minutos",
"Complète": "Completo",
"Niveau 1 (192.168.12.x)": "Nivel 1 (192.168.12.x)",
"Niveau 2 (192.168.x.x)": "Nivel 2 (192.168.x.x)",
"Niveau 3 (192.x.x.x)": "Nivel 3 (192.x.x.x)",
"Chiffres": "Cifras",
"Lettres": "Letras",
"Icône": "Ícone",
"Icône avec bulle de texte": "Ícone com bolha de texto",
"Après le contenu de la page": "Depois do conteúdo da página",
"Avant le contenu de la page": "Antes do conteúdo da página",
"À l'emplacement du mot clé [MODULE] dans la page": "No local da palavra-chave [MODULE] na página",
"Page standard": "Página normal",
"Barre 1/3 - page 2/3": "Barra 1/3 - página 2/3",
"Page 2/3 - barre 1/3": "Página 2/3 - barra 1/3",
"Barre 1/4 - page 3/4": "Barra 1/4 - página 3/4",
"Page 3/4 - barre 1/4": "Página 3/4 - barra 1/4",
"Barre 1/4 - page 1/2 - barre 1/4": "Barra 1/4 - página 1/2 - barra 1/4",
"Barre 2/12 - page 7/12 - barre 3/12": "Barra 2/12 - página 7/12 - barra 3/12",
"Barre 3/12 - page 7/12 - barre 2/12": "Barra 3/12 - página 7/12 - barra 2/12",
"Barre latérale": "Barra lateral",
"Aucun menu": "Sem menu",
"Le menu horizontal intégral": "O menu horizontal completo",
"Le sous-menu de la page parente": "O submenu da página pai",
"Menu standard": "Menu normal",
"Menu accessoire": "Menu de acessórios",
"Activer": "Permitir",
"Importer dans": "Importar para",
"Archive ZIP": "Arquivo ZIP",
"Archive": "Arquivo",
"Langue par défaut": "Idioma padrão",
"Langue du site sélectionnée": "Idioma do site selecionado",
"Se déconnecter ?": "Sair ?",
"Mettre à jour ?": "Actualizar ?",
"Confirmez-vous la suppression de cette page ?": "Confirma a eliminação desta página?",
"Format incorrect": "Formato incorreto",
"Les modifications que vous avez apportées ne seront peut-être pas enregistrées.": "As alterações feitas podem não ser salvas.",
"Oui": "Sim",
"Non": "Não",
"Identifiant": "Identificador",
"Mot de passe": "Senha",
"Confirmation": "Confirmação",
"Prénom": "Primeiro nome",
"Nom": "Nome",
"Ne pas charger l'exemple de site (utilisateurs avancés)": "Não carregue o site de amostra (usuários avançados)",
"Type de proxy": "Tipo de proxy",
"Adresse du proxy": "Endereço proxy",
"Port du proxy": "Porta proxy",
"Thème": "Tema",
"Installer": "Instalar",
"Consulter l'aide en ligne": "Consulte a ajuda online",
"favicon.ico": "",
"Pensez à supprimer le cache de votre navigateur si la favicon ne change pas.": "Lembre-se de excluir o cache do seu navegador se o favicon não mudar.",
"faviconDark.ico": "faviconDark.ico",
"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.": "Selecione um ícone adequado para um tema escuro.<br>Lembre-se de excluir o cache do seu navegador se o favicon não mudar.",
"Fuseau horaire": "Fuso horário",
"Le fuseau horaire est utile au bon référencement": "O fuso horário é útil para uma boa referência",
"Message de consentement aux cookies": "Mensagem de consentimento de cookies",
"Activation obligatoire selon les lois françaises sauf si vous utilisez votre propre système de consentement.": "Ativação obrigatória de acordo com as leis francesas, a menos que você use seu próprio sistema de consentimento.",
"Apache URL intelligentes": "URLs inteligentes do Apache",
"Supprime le point d'interrogation dans les URL, l'option est indisponible avec les autres serveurs Web": "Eliminar el signo de interrogación en las URL, la opción no está disponible con otros servidores web",
"Rechercher une mise à jour en ligne": "verifique se há uma atualização on-line",
"La vérification est quotidienne. Option désactivée si la configuration du serveur ne le permet pas.": "A verificação é diária. Opção desabilitada se a configuração do servidor não permitir.",
"Préserver le fichier htaccess racine": "Preservar o arquivo htaccess raiz",
"Lors d'une mise à jour automatique, conserve le fichier htaccess de la racine du site.": "Durante uma atualização automática, mantém o arquivo htaccess da raiz do site.",
"Sauvegarde automatique quotidienne du site": "Backup diário automático do site",
"Site en maintenance": "Site em manutenção",
"Clé de l'API <a href='https://app.screenshotapi.net/' target='_blank'>ScreenShotApi</a>": "Chave de API <a href='https://app.screenshotapi.net/' target='_blank'>ScreenShotApi</a>",
"Saisir la clé, puis valider le formulaire avant de cliquer sur le bouton de génération": "Digite a chave e valide o formulário antes de clicar no botão gerar",
"Autoriser les robots à référencer le site": "Permitir que robôs façam referência ao site",
"Facebook": "Facebook",
"Saisissez votre ID : https://www.facebook.com/[ID].": "Digite seu ID: https://www.facebook.com/[ID].",
"Instagram": "Instagram",
"Saisissez votre ID : https://www.instagram.com/[ID].": "Digite seu ID: https://www.instagram.com/[ID].",
"Chaîne Youtube": "canal do Youtube",
"ID de la chaîne : https://www.youtube.com/channel/[ID].": "ID do canal: https://www.youtube.com/channel/[ID].",
"Youtube": "YouTube",
"Saisissez votre ID Utilisateur : https://www.youtube.com/user/[ID].": "Digite seu ID de usuário: https://www.youtube.com/user/[ID].",
"Twitter": "Twitter",
"Saisissez votre ID : https://twitter.com/[ID].": "Digite seu ID: https://twitter.com/[ID].",
"Pinterest": "Pinterest",
"Saisissez votre ID : https://pinterest.com/[ID].": "Digite seu ID: https://pinterest.com/[ID].",
"Linkedin": "Linkedin",
"Saisissez votre ID Linkedin : https://fr.linkedin.com/in/[ID].": "Digite seu ID do Linkedin: https://fr.linkedin.com/in/[ID].",
"Github": "Github",
"Saisissez votre ID Github : https://github.com/[ID].": "Digite seu ID do Github: https://github.com/[ID].",
"Dévoiler le mot de passe": "Revele a senha",
"Le survol d'une icône de l'écran de connexion affiche temporairement le mot de passe.": "Passar o mouse sobre um ícone da tela de login exibe temporariamente a senha.",
"Déconnexion automatique": "Logout automático",
"Redirection vers la connexion": "Redirecionar para login",
"Cette redirection ne concerne que les pages d'administration du site.": "Este redirecionamento diz respeito apenas às páginas de administração do site.",
"Limitation des tentatives": "Limitação de tentativa",
"Blocage après échecs": "Bloqueio após falhas",
"Captcha à la connexion": "Captcha no login",
"Captcha complexe": "Captcha Complexo",
"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.": "Opção recomendada para proteger a conexão. Aplica-se a todos os captchas do site. O captcha simples está limitado à adição de números de 0 a 10. O captcha complexo utiliza quatro operações de números de 0 a 20. Ativação recomendada.",
"Type de captcha": "Tipo de captcha",
"Activer la journalisation": "Ativar registro",
"Anonymat des adresses IP": "Anonimato dos endereços IP",
"La réglementation française impose un anonymat de niveau 2": "Regulamentos franceses impõem anonimato de nível 2",
"Activer SMTP": "Ativar SMTP",
"Paramètres à utiliser lorsque votre hébergeur ne propose pas la fonctionnalité d'envoi de mail.": "Parâmetros a serem usados quando seu host não oferece a funcionalidade de envio de e-mail.",
"Adresse SMTP": "Endereço SMTP",
"Port SMTP": "Porta SMTP",
"Authentification": "Autenticação",
"Nom utilisateur": "Nome de usuário",
"Sécurité": "Segurança",
"Nouvelle page ou barre latérale": "Nova página ou barra lateral",
"Éditer la page": "Editar página",
"Supprimer la page": "Excluir página",
"Gérer les modules": "Gerenciar módulos",
"Configuration": "Configuração",
"Utilisateurs": "Usuários",
"Déconnecter": "Desconectar",
"Éditer": "Editar",
"Supprimer": "Deletar",
"Importer des utilisateurs en masse": "Importar usuários em massa",
"Ajouter un utilisateur": "Adicionar usuário",
"Pseudo": "Pseudo",
"Signature": "Assinatura",
"Groupe": "Banda",
"Impossible de modifier votre propre groupe.": "Não foi possível editar seu próprio grupo.",
"Partage de fichiers autorisé": "Compartilhamento de arquivos permitido",
"Ce membre pourra téléverser ou télécharger des fichiers dans le dossier 'partage' et ses sous-dossiers": "Este membro poderá fazer upload ou download de arquivos na pasta 'compartilhar' e suas subpastas",
"L'identifiant est défini lors de la création du compte, il ne peut pas être modifié.": "O identificador é definido ao criar a conta, não pode ser modificado.",
"Ancien mot de passe": "Senha Antiga",
"Nouveau mot de passe": "Nova Senha",
"Séparateur": "Separador",
"Envoyer un message de confirmation": "Envie uma mensagem de confirmação",
"Prévenir l'utilisateur par mail": "Notifique o usuário por e-mail",
"Copie de sites inter-langues": "Copiando sites em vários idiomas",
"Titre du site": "Titulo do site",
"Il apparaît dans la barre de titre et les partages sur les réseaux sociaux.": "Ele aparece na barra de título e nos compartilhamentos de mídia social.",
"Description du site": "Descrição do Site",
"La description d'une page participe à son référencement, chaque page doit disposer d'une description différente.": "A descrição de uma página participa de sua referenciação, cada página deve ter uma descrição diferente.",
"Accueil du site": "Pagina inicial",
"La première page que vos visiteurs verront.": "A primeira página que seus visitantes verão.",
"Accès interdit, erreur 403": "Acesso negado, erro 403",
"Cette page ne doit pas apparaître dans l'arborescence du menu. Créez une page orpheline.": "Esta página não deve aparecer na árvore do menu. Crie uma página órfã..",
"Page inexistante, erreur 404": "A página não existe, erro 404",
"Mentions légales": "Notícia legal",
"Les mentions légales sont obligatoires en France. Une option du pied de page ajoute un lien discret vers cette page.": "Avisos legais são obrigatórios na França. Uma opção de rodapé adiciona um link discreto a esta página.",
"Recherche dans le site": "Pesquisa de sites",
"Sélectionnez une page contenant le module 'Recherche'. Une option du pied de page ajoute un lien discret vers cette page.": "Selecione uma página contendo o módulo 'Pesquisar'. Uma opção de rodapé adiciona um link discreto a esta página.",
"Rechercher": "Buscar",
"Plan du site": "Mapa do site",
"Cookies": "Cookies",
"Titre de la fenêtre": "Título da janela",
"Saisissez le titre de la fenêtre de gestion des cookies.": "Digite o título da janela de gerenciamento de cookies.",
"Bouton de validation": "Botão de validação",
"Cookies Zwii": "Cookies Zwii",
"Saisissez le message pour les cookies déposés par ZwiiCMS, nécessaires au fonctionnement et qui ne nécessitent pas de consentement.": "Insira a mensagem para cookies depositados pelo ZwiiCMS, necessários para o funcionamento e que não requerem consentimento.",
"Lien page des mentions légales.": "Link da página de aviso legal.",
"Saisissez le texte du lien vers les mentions légales,la page doit être définie dans la configuration du site.": "Digite o texto do link para os avisos legais, a página deve ser definida na configuração do site.",
"Pages et les modules de": "Páginas e módulos",
"Vers": "Para",
"Supprimer le module": "Excluir módulo",
"Sauvegarder le module dans le gestionnaire de fichiers": "Salvar módulo no gerenciador de arquivos",
"Sauvegarder et télécharger le module": "Salve e baixe o módulo",
"Installer depuis le catalogue en ligne": "Instalar a partir do catálogo online",
"Installer depuis une archive": "Instalar do arquivo",
"Mettre à jour le module orphelin": "Atualizar módulo órfão",
"Télécharger le module dans le gestionnaire de fichiers": "Carregar módulo para o gerenciador de arquivos",
"Connexion": "Conecte-se",
"Ajouter une fonte": "Adicionar uma fonte",
"Fonte en ligne": "Elenco on-line",
"Fonte installée": "Tipografía instalada",
"Identifiant (sans espace ni majuscule)": "Identificador (sem espaços ou maiúsculas)",
"Famille": "família",
"Url du fichier de fonte": "URL do arquivo de fonte",
"Réinitialiser avec le thème par défaut": "Redefinir para o tema padrão",
"Arrière plan": "Fundo",
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence.": "Cor visível na ausência de uma imagem.<br />O controle deslizante horizontal ajusta o nível de transparência.",
"Titres": "Títulos",
"Texte": "Texto",
"Arrière plan des champs": "Plano de fundo do campo",
"Couleur visible en l'absence d'une image.<br />Le curseur horizontal règle le niveau de transparence. La couleur du texte est automatique.": "Cor visível na ausência de uma imagem.<br />O controle deslizante horizontal ajusta o nível de transparência. A cor do texto é automática.",
"Bordure des champs": "Borda do campo",
"Bouton Aide": "Botão de ajuda",
"Bouton retour": "botão voltar",
"Bouton standard": "botão padrão",
"Bouton effacement": "Botão Excluir",
"Bouton validation": "Botão de validação",
"Police du texte": "Fonte de texto",
"Taille": "Tamanho",
"Police des titres": "tipografia do título",
"Réinitialiser la feuille de style": "redefinir folha de estilo",
"Rester connecté sur ce navigateur": "Permaneça conectado neste navegador",
"Effacer la page": "limpar página",
"Dupliquer la page": "duplicar a página",
"Titre": "Título",
"Titre court": "Título curto",
"Le titre court est affiché dans les menus. Il peut être identique au titre de la page.": "O título curto é exibido nos menus. Pode ser o mesmo que o título da página.",
"Titre masqué dans la page": "Título mascarado na página",
"Fil d'Ariane dans le titre": "Farinha de rosca no título",
"Affiche le nom de la page parente suivi du nom de la page, le titre ne doit pas être masqué.": "Mostre o nome da página principal seguido do nome da página, o título não deve ficar oculto.",
"Position": "Posição",
"'Ne pas afficher' crée une page orpheline non accessible par le biais des menus.": "'Não mostrar' cria uma página órfã que não pode ser acessada pelos menus.",
"Page parent": "Página principal",
"Emplacement :": "Localização",
"Page non cliquable": "A página não é clicável",
"Option active en mode déconnecté uniquement, les pages enfants sont visibles et accessibles.": "Opção ativa apenas no modo offline, as páginas filhas ficam visíveis e acessíveis.",
"S'ouvre dans un nouvel onglet": "Abre em uma nova guia",
"Apparence": "Apariencia",
"Sélectionnez une image ou une icône de petite dimension": "Selecione uma pequena imagem ou ícone",
"Masquer les pages enfants dans le menu horizontal": "Selecione uma pequena imagem ou ícone",
"Masquer la page et les pages enfants dans le menu d'une barre latérale": "Seleccione una imagen o icono pequeño",
"La page est affichée dans un menu horizontal mais pas dans le menu vertical d'une barre latérale.": "A página é exibida em um menu horizontal, mas não no menu vertical de uma barra lateral.",
"Module": "Módulo",
"En cas de changement de module, les données du module précédent seront supprimées.": "Ao alterar o módulo, os dados do módulo anterior serão apagados.",
"Position du module": "Posição do módulo",
"En position libre ajoutez le module en plaçant [MODULE] à l'endroit voulu dans votre page.": "Na posição livre adicione o módulo colocando [MODULE] no local desejado em sua página.",
"Feuille de style spécifique à la page.": "Hoja de estilo específica de la página.",
"Instructions JS ou jquery spécifiques à la page.": "Instrucciones JS o jquery específicas de la página.",
"Gabarits de page - Barre latérale": "Mestre da página - Barra lateral",
"Pour définir la page comme barre latérale, choisissez l'option dans la liste.": "Para definir a página como barra lateral, escolha a opção na lista.",
"Barre latérale gauche :": "barra lateral esquerda:",
"Barre latérale droite :": "Barra lateral direita:",
"Contenu du menu vertical": "Conteúdo do menu vertical",
"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.": "Por padrão, o menu é exibido APÓS o conteúdo da página. Para colocá-lo em um local específico, insira [MENU] no conteúdo da página.",
"Groupe requis pour accéder à la page :": "Grupo necessário para acessar a página:",
"Méta-titre": "Meta-título",
"Méta-description": "Meta Descrição",
"Module de la page": "Módulo de página",
"Paramètres de la sauvegarde": "Configurações de backup",
"Sécurité de la connexion": "segurança de conexão",
"Journalisation": "Conecte-se",
"Paramètres": "Definições",
"SMTP": "SMTP",
"Archive à restaurer": "Arquivo para restaurar",
"Mise à jour automatisée": "atualização automática",
"Capture d'écran Open Graph": "Captura de tela do Open Graph",
"Référencement": "referenciando",
"Réseaux sociaux": "Redes sociais",
"Renseignez les champs ci-dessous pour finaliser l'installation.": "Complete as zonas abaixo para concluir a instalação.",
"Compte administrateur": "Conta de administrador",
"Options avancées": "Opções avançadas",
"Mise à jour de ZwiiCMS": "Atualização do ZwiiCMS",
"vers ZwiiCMS": "Rumo ao ZwiiCMS",
"Afin d'assurer le bon fonctionnement de Zwii, veuillez ne pas fermer cette page avant la fin de l'opération.": "Para garantir o funcionamento adequado do Zwii, não feche esta página antes que a operação seja concluída",
"1/4 : Préparation...": "1/4: Preparando...",
"2/4 : Téléchargement...": "2/4: Baixando...",
"3/4 : Installation...": "3/4: Instalando...",
"4/4 : Configuration...": "4/4: Contexto...",
"Une erreur est survenue lors de l'étape :": "Ocorreu um erro durante o processo",
"Mise à jour terminée avec succès.": "Atualização concluída com sucesso.",
"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.": "Nosso site está atualmente em manutenção. Lamentamos o transtorno e estamos fazendo o possível para retornar o mais breve possível.",
"Installer les données d'un module": "Instalar dados de um módulo",
"Sauvegarde": "Salvaguarda",
"Modules orphelins": "Módulos órfãos",
"Modules configurés": "Módulos Configurados",
"Modules installés": "Módulos instalados",
"Données des modules": "Dados do módulo",
"Version n°": "Número da versão",
"Du": "Del",
"Auteur :": "Autor",
"Licence :": "Licença",
"Installer ou mettre à jour un module téléchargé": "Instalar ou atualizar um módulo baixado",
"Couleurs": "Cores",
"Mise en forme du texte": "Formato de texto",
"Image": "Imagen",
"Identité de la fonte": "Identidade tipográfica",
"Disposition": "Arranjo",
"Contenu personnalisé": "Conteúdo personalizado",
"Informations": "Informação",
"Mise en forme du titre": "Formato do título",
"Papier peint": "Cor de fundo",
"Largeur de l'image :": "Largura da imagem",
"Hauteur de l'image :": "Altura da imagem",
"largeur du site": "Largura do site",
"Ratio :": "Relação",
"largeur de site :": "Largura do site",
"Installer un thème archivé (site ou administration)": "Instale um tema arquivado (site ou administrador)",
"Sauvegarde du thème dans le": "Salvando tema para",
"gestionnaire de fichiers": "Gerenciador de arquivos",
"Télécharger le thème": "Baixar tema",
"Contenu": "Conteúdo",
"Mise en forme des titres": "Formato do título",
"Copie des traductions rédigées": "Cópia de traduções editadas",
"Identité": "Identificação",
"Permissions :": "Permissões",
"Accès aux pages privées": "Acesso a páginas privadas",
"Ajout - Édition - Suppression de fichiers": "Adicionar/editar/excluir arquivos",
"Administration complète du site": "Administração completa do site",
"Importation de fichier plat CSV": "Importar arquivo CSV simples",
"Confirmer la suppression de cet utilisateur": "Confirme a exclusão deste usuário",
"Sauvegarde générée avec succès.": "Backup gerado com sucesso",
"Erreur : sauvegarde non générée !": "Erro: backup não gerado!",
"Sauvegarder": "Para salvaguardar",
"La sauvegarde des fichiers peut prendre du temps. Continuer ?": "O backup de arquivos pode demorar um pouco. Você deseja continuar?",
"Supprimer toutes les sauvegardes automatiques ?": "Remover todos os salvamentos automáticos?",
"Préparation de la mise à jour": "Preparaação para a atualização",
"Téléchargement et validation de l'archive": "Download e validação de arquivos",
"Installation": "Instalação",
"Confirmer la suppression de la page": "Confirmar exclusão de página",
"Confirmer la suppression des données du module": "Confirme a exclusão de dados do módulo",
"Ne pas afficher": "Não exibido",
"Au début": "No princípio",
"Après": "Depois",
"Confirmer la désinstallation du module": "Confirme a desinstalação do módulo",
"Confirmer la dissociation du module de cette page": "Confirme o módulo de desvinculação desta página",
"Sauvegarder les données du site": "Salvar dados do site",
"Restaurer les données du site": "Restaurar dados do site",
"Vider dossier sauvegardes auto": "Pasta de salvamento automático vazia",
"Copier sauvegardes auto": "Copiar salvamentos automáticos",
"Réinstaller": "Reinstalar",
"Script dans head": "Script en el head",
"Script dans body": "Script en el body",
"Générer une capture Open Graph": "Gerar uma captura do Open Graph",
"Générer sitemap.xml et robots.txt": "Gerar sitemap.xml e robots.txt",
"Télécharger la liste": "Baixar lista",
"Réinitialiser la liste": "Redefinir lista",
"Télécharger le journal": "Baixar Registro",
"Réinitialiser le journal": "Restablecer registro",
"Fond du sous-menu": "Plano de fundo do submenu",
"Liens": "Links",
"Arrière plan des blocs": "Fundo de blocos",
"Bordure des blocs": "Borda dos blocos",
"Boutons": "Botões",
"Thème du site": "Tema do site",
"Thème de l'administration": "Tema administrativo",
"Appliquer": "Aplicar",
"Enregistrer": "Registrar",
"Éditeur CSS": "Editor de CSS",
"Éditeur JS": "Editor de JS",
"Accueil": "Começar",
"Aide": "Ajuda",
"Fontes": "Fontes",
"Gestion": "Gerenciar",
"Administration": "Gestão",
"Langues": "Línguas",
"Interface": "Interface",
"Langue de l'administration": "Idioma de administração",
"Langues installées": "Idiomas instalados",
"Dans quelle langue utiliserez-vous Zwii ?": "Qual idioma o Zwii usará?",
"Maintenance": "Manutenção",
"Scripts externes": "Scripts externos",
"Version": "Versão",
"Catégorie": "Categoria",
"Page": "Página",
"Copie de contenus localisés": "Cópia do conteúdo localizado",
"Nouveau contenu localisé": "Novo conteúdo localizado",
"Sélectionnez une langue": "Selecione um idioma",
"Langues disponibles": "Idiomas disponíveis",
"Sélectionnez la langue à copier vers une langue cible": "Selecione o idioma para copiar para outro idioma",
"De": "Do",
"vers": "Para",
"Action interdite": "ação não permitida",
"Modifications enregistrées": "Alterações salvas",
"URL incorrecte": "URL errada",
"Paramètres de la localisation": "Configurações de localização",
"Mise à jour": "Atualizar",
"Gestion des modules": "Gerenciamento de módulo",
"Catalogue de modules": "Catálogo de módulos",
"Installer un module": "Instalar um módulo",
"Pied de page": "Rodapé",
"Bannière": "Bandeira",
"Thèmes": "Temas",
"Menu": "Menu",
"Site": "Sitio",
"Gestion des thèmes": "Gerenciamento de tópicos",
"Nouvel utilisateur": "Novo usuário",
"Mot de passe oublié": "Senha esquecida",
"Réinitialisation du mot de passe": "Redefinir a senha do usuário",
"Importation d'utilisateurs": "Importação de usuários",
"Contenu avancé": "Conteúdo avançado",
"Mise en page": "Esquema",
"Permission et référencement": "Permissão e referência",
"Éditeur de script %s": "Editor de script %s",
"Journal réinitialisé avec succès": "Registro redefinido com sucesso",
"Aucun journal à effacer": "Não há registros para excluir",
"Aucun fichier journal à télécharger": "Nenhum arquivo de log para download",
"Aucune liste noire à télécharger": "Nenhuma lista negra para baixar",
"Liste noire réinitialisée avec succès": "Lista negra redefinida com sucesso",
"Aucune liste noire à effacer": "Não há lista negra para excluir",
"Copie terminée avec succès": "Cópia concluída com sucesso",
"Copie terminée avec des erreurs": "Cópia concluída com erros",
"Fichiers effacés": "arquivos excluídos",
"Restaurer": "Restaurar",
"Restauration effectuée avec succès": "Restauração concluída com sucesso",
"Échecs": "Falhas",
"Erreur inconnue": "Erro desconhecido",
"Archive invalide": "arquivo inválido",
"Le curseur horizontal règle le niveau de transparence, le placer tout à la gauche pour un surlignement invisible.": "O controle deslizante horizontal define o nível de transparência, defina-o totalmente para a esquerda para um destaque invisível.",
"Contenu multilangues": "Conteúdo multilíngue",
"Extension": "Extensão",
"Permission": "Permissão",
"Emplacement dans le menu": "Localização no menu",
"Réseau": "La red",
"Étiquettes des pages spéciales": "Tags de página especiais",
"Identité du site": "Identidade do site",
"Message d'acceptation des Cookies": "Mensagem de aceitação de cookies",
"Favicon thème sombre": "favicon tema escuro",
"Apache URL intelligent": "URL inteligente do Apache",
"Liste noire": "Lista negra",
"Ajout - Édition - Suppression de pages": "Adicionando - Editando - Excluindo páginas",
"Importer": "Importar",
"Clé de l'API <a href=\"https://app.screenshotapi.net/\" target=\"_blank\">ScreenShotApi</a>": "Chave de API <a href=\"https://app.screenshotapi.net/\" target=\"_blank\">ScreenShotApi</a>",
"Créez un compte gratuit, recopier la clé , puis valider le formulaire avant de cliquer sur le bouton de génération": "Crie uma conta gratuita, copie a chave e valide o formulário antes de clicar no botão gerar",
"La clé de l'API ne peut pas être vide": "A chave de API não pode estar vazia",
"Service en ligne inaccessible": "Serviço online inacessível",
"La carte du site a été mise à jour": "O mapa do site foi atualizado.",
"Echec de l'écriture, vérifiez les permissions": "Falha na gravação, verifique as permissões",
"Capture d'écran générée avec succès": "Captura de tela gerada com sucesso",
"Inclure le contenu du gestionnaire de fichiers": "Captura de tela gerada com sucesso",
"Si le contenu du gestionnaire de fichiers est très volumineux, mieux vaut une copie par FTP.": "Se o conteúdo do gerenciador de arquivos for muito grande, é melhor copiar por FTP.",
"Retour": "De volta",
"L'archive a été déposée dans le gestionnaire de fichiers. Les archives inférieures à la version 9 ne sont pas acceptées.": "O arquivo foi depositado no gerenciador de arquivos. Arquivos anteriores à versão 9 não são aceitos.",
"Préserver les comptes des utilisateurs déjà installés": "Preservar contas de usuário já instaladas",
"Éditeur de script dans Head": "Éditor do script no Head",
"Valider": "Validar",
"Éditeur de script dans Body": "Éditor do script no Body",
"FontId": "ID da fonte",
"Affectation": "Atribuição",
"Origine": "Fonte",
"Bouton Standard": "botão padrão",
"Configuration du module": "Configuração do módulo",
"Installation terminée": "instalação completa",
"Jeton invalide": "Símbolo inválido",
"Suppression interdite": "exclusão proibida",
"Page dupliquée": "Página duplicada",
"Page et module dupliqués": "Página y módulo duplicados",
"Nouvelle page créée": "Nova página criada",
"Suppression interdite, page active dans la configuration du site": "Exclusão proibida, página ativa nas configurações do site",
"Impossible de supprimer une page contenant des pages enfants": "Não é possível excluir uma página que contém páginas filhas",
"Page supprimée": "página excluída",
"La suppression a échoué": "exclusão malsucedida",
"Le module %s est désinstallé, il reste peut-être des données dans %s": "O módulo é desinstalado, os dados podem permanecer",
"Archive invalide, le descripteur est absent": "Arquivo inválido, descritor ausente",
"Archive invalide, les dossiers ne correspondent pas au descripteur": "Arquivo inválido, as pastas não correspondem ao descritor",
"Archive invalide, l'écriture dans le dossier core est interdite": "Arquivo inválido, é proibido gravar na pasta principal",
"Archive invalide, le fichier de classe est absent": "Arquivo inválido, arquivo de classe está faltando",
"La version installée est plus récente": "A versão instalada é mais recente.",
"actualisé": "Atualizada",
"installé": "Instalado",
"Erreur inconnue, le module n'est pas installé": "Erro desconhecido, o módulo não está instalado",
"Impossible d'ouvrir l'archive": "Não é possível abrir o arquivo",
"Archive copiée dans le dossier Modules du gestionnaire de fichier": "Arquivo copiado para a pasta do Módulos Gerenciador de arquivos",
"Erreur de copie": "Erro de cópia",
"Le module %s de la page %s a été supprimé": "Módulo de página removido",
"Le module %s a été %s": "O módulo foi",
"Données importées": "Dados importados",
"Sélectionnez au moins un contenu à afficher": "Selecione pelo menos um conteúdo para exibir",
"Fonte créée": "Fonte criada",
"Fonte non créée, ressource absente !": "Fonte não criada, por falta de recursos!",
"Fonte actualisée": "Fonte atualizada",
"Fonte supprimée": "fonte removida",
"Thème importé": "Tema importado",
"Erreur d'extraction, vérifiez les permissions": "Extrair erro, verificar permissões",
"Archive de thème invalide": "Arquivo de tema inválido",
"Archive non spécifiée ou introuvable": "Arquivo não especificado ou não encontrado",
"sauvegardé avec succès": "Salvo com sucesso",
"Données %s copiées vers %s": "Dados copiados para",
"Erreur de copie, vérifiez les permissions": "Erro de cópia, verifique as permissões",
"Les langues sélectionnées sont identiques": "Os idiomas selecionados são idênticos",
"Erreur d'URL": "Erro de URL",
"Traduction supprimée": "Tradução removida",
"Impossible de supprimer votre propre compte": "Você não pode excluir sua própria conta",
"Utilisateur supprimé": "Usuário excluído",
"Incorrect": "Incorreta",
"Un mail a été envoyé pour confirmer la réinitialisation": "Um e-mail foi enviado para confirmar a redefinição.",
"Utilisateur inexistant": "Usuário inexistente",
"Compte verrouillé": "Conta bloqueada",
"Captcha, identifiant ou mot de passe incorrects": "Captcha, nome de usuário ou senha incorretos",
"Seul un administrateur peut se connecter lors d'une maintenance": "Somente um administrador pode fazer login durante uma manutenção",
"Bienvenue %s %s": "Bem-vindo",
"Accès bloqué %d minutes": "Minutos de acesso bloqueado",
"Déconnexion !": "Fechar Sessão!",
"Nouveau mot de passe enregistré": "Nova senha salva",
"Importation effectuée": "Importação concluída",
"Erreur de lecture, vérifiez les permissions": "Erro de leitura, verifique as permissões"
}

View File

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

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-2024, 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,8 +6,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
$("#installId").on("change keydown keyup",(function(event){var userId=$(this).val();if(8!==event.keyCode&&37!==event.keyCode&&39!==event.keyCode&&46!==event.keyCode&&window.getSelection().toString()!==userId){var searchReplace={"á":"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","Á":"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","'":"-",'"':"-"," ":"-"};userId=(userId=userId.replace(/[áàâäãåçéèêëíìîïñóòôöõúùûüýÿ'" ]/gi,(function(match){return searchReplace[match]}))).replace(/[^a-z0-9-]/gi,""),$(this).val(userId)}})); $("#installId").on("change keydown keyup",(function(event){var userId=$(this).val();if(8!==event.keyCode&&37!==event.keyCode&&39!==event.keyCode&&46!==event.keyCode&&window.getSelection().toString()!==userId){var searchReplace={"á":"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","Á":"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","'":"-",'"':"-"," ":"-"};userId=(userId=userId.replace(/[áàâäãåçéèêëíìîïñóòôöõúùûüýÿ'" ]/gi,(function(match){return searchReplace[match]}))).replace(/[^a-z0-9-]/gi,""),$(this).val(userId)}}));

View File

@ -2,71 +2,77 @@
<?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'); ?> <div class="col12">
</h3> <details open>
<div> <summary>
<div class="row"> <span class="title">
<div class="col12"> <?php echo helper::translate('Compte administrateur'); ?>
<?php echo template::text('installId', [ </span>
'autocomplete' => 'off', </summary>
'label' => 'Identifiant'
]); ?>
</div>
</div>
<div class="row">
<div class="col6">
<?php echo template::password('installPassword', [
'autocomplete' => 'off',
'label' => 'Mot de passe'
]); ?>
</div>
<div class="col6">
<?php echo template::password('installConfirmPassword', [
'autocomplete' => 'off',
'label' => 'Confirmation'
]); ?>
</div>
</div>
<div class="row">
<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>
<ul class="accordion" data-speed="150">
<li class="accordion-item">
<h3 class="accordion-title">
<?php echo '&#9655; ' . helper::translate('Options avancées'); ?>
</h3>
<div class="accordion-content">
<?php if ($this->getUrl(2) === 'fr_FR'): ?>
<div class="row"> <div class="row">
<div class="col12"> <div class="col6">
<?php echo template::checkbox('installDefaultData', true, 'Ne pas charger l\'exemple de site (utilisateurs avancés)', [ <?php echo template::text('installFirstname', [
'checked' => false 'autocomplete' => 'off',
]); 'label' => 'Prénom'
?> ]); ?>
</div>
<div class="col6">
<?php echo template::text('installLastname', [
'autocomplete' => 'off',
'label' => 'Nom'
]); ?>
</div> </div>
</div> </div>
<?php endif;?> <div class="row">
<div class="col6">
<?php echo template::text('installId', [
'autocomplete' => 'off',
'label' => 'Identifiant'
]); ?>
</div>
<div class="col6">
<?php echo template::mail('installMail', [
'autocomplete' => 'off',
'label' => 'Adresse électronique'
]); ?>
</div>
</div>
<div class="row">
<div class="col6">
<?php echo template::password('installPassword', [
'autocomplete' => 'off',
'label' => 'Mot de passe'
]); ?>
</div>
<div class="col6">
<?php echo template::password('installConfirmPassword', [
'autocomplete' => 'off',
'label' => 'Confirmation'
]); ?>
</div>
</div>
</details>
</div>
</div>
<div class="row">
<div class="col12">
<details close>
<summary>
<span class="title">
<?php echo helper::translate('Options avancées'); ?>
</span>
</summary>
<?php if ($_SESSION['ZWII_UI'] === 'fr_FR'): ?>
<div class="row">
<div class="col12">
<?php echo template::checkbox('installDefaultData', true, 'Ne pas charger l\'exemple de site (utilisateurs avancés)', [
'checked' => false
]);
?>
</div>
</div>
<?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,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */

View File

@ -1,6 +1,10 @@
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 = ["<?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(), $.ajax({ $(".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: {
@ -9,12 +13,61 @@ function step(i, 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) {
$("#installUpdateSuccess").show();
$("body").css("cursor", "default");
$("#installUpdateEnd").removeClass("disabled");
$("#installUpdateProgress").hide();
} else {
step(i + 1, result.data);
}
}), 2e3) }), 2e3)
}, },
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, "")) // Balance tout dans la console
console.log(i);
console.log(xhr.responseText);
console.log(errors);
// 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('{');
// 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);
const jsonData = JSON.parse(jsonString);
// Afficher les résultats
if (jsonData) {
$("#installUpdateErrorMessage").html("<strong>Détails de l'erreur :</strong><br> " +
jsonData.data.replace(/^"(.*)"$/, '$1') +
"<br>" +
warningMessage.replace(/<[^p].*?>/g, ""));
}
} else {
// Vous pouvez également faire quelque chose d'autre ici, par exemple, afficher un message à l'utilisateur, etc.
$("#installUpdateErrorMessage").html(message);
}
}
$(window).on("load", function () {
step(1, null);
});

View File

@ -1,55 +1,56 @@
<p><strong> <div id="updateContainer">
<?php echo helper::translate('Mise à jour de ZwiiCMS'); ?> <p><strong>
&nbsp; <?php echo helper::translate('Version'); ?>
<?php echo self::ZWII_VERSION; ?> &nbsp;
<?php echo helper::translate('vers ZwiiCMS'); ?> <?php echo self::ZWII_VERSION; ?>
&nbsp; <?php echo helper::translate('vers'); ?>
<?php echo $module::$newVersion; ?>. &nbsp;
</strong></p> <?php echo $module::$newVersion; ?>
<p> </strong></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.'); ?> <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.'); ?>
<div class="row"> </p>
<div class="col9 verticalAlignMiddle"> <div class="row">
<div id="installUpdateProgress"> <div class="col9 verticalAlignMiddle">
<?php echo template::ico('spin', ['animate' => true]); ?> <div id="installUpdateProgress">
<span class="installUpdateProgressText" data-id="1"> <?php echo template::ico('spin', ['animate' => true]); ?>
<?php echo helper::translate('1/4 : Préparation...'); ?> <span class="installUpdateProgressText" data-id="1">
</span> <?php echo helper::translate('1/4 : Préparation...'); ?>
<span class="installUpdateProgressText displayNone" data-id="2"> </span>
<?php echo helper::translate('2/4 : Téléchargement...'); ?> <span class="installUpdateProgressText displayNone" data-id="2">
</span> <?php echo helper::translate('2/4 : Téléchargement...'); ?>
<span class="installUpdateProgressText displayNone" data-id="3"> </span>
<?php echo helper::translate('3/4 : Installation...'); ?> <span class="installUpdateProgressText displayNone" data-id="3">
</span> <?php echo helper::translate('3/4 : Installation...'); ?>
<span class="installUpdateProgressText displayNone" data-id="4"> </span>
<?php echo helper::translate('4/4 : Configuration...'); ?> <span class="installUpdateProgressText displayNone" data-id="4">
</span> <?php echo helper::translate('4/4 : Configuration...'); ?>
</span>
</div>
<div id="installUpdateError" class="message colorRed displayNone">
<?php echo template::ico('cancel'); ?>
<strong>
<?php echo helper::translate('Une erreur est survenue lors de l\'étape :') . '<br>'; ?>
<span id="installUpdateErrorStep"> </span>.
</strong>
</div>
<div id="installUpdateSuccess" class="message colorGreen displayNone">
<?php echo template::ico('check'); ?>
<?php echo helper::translate('Mise à jour terminée avec succès.'); ?>
</div>
</div> </div>
<div id="installUpdateError" class="colorRed displayNone"> <div class="col3 verticalAlignTop">
<?php echo template::ico('cancel'); ?> <?php echo template::button('installUpdateEnd', [
<strong> 'value' => 'Terminer',
<?php echo helper::translate('Une erreur est survenue lors de l\'étape :'); ?> 'href' => helper::baseUrl() . 'config',
&nbsp; 'ico' => 'check',
<span id="installUpdateErrorStep"> </span>. 'class' => 'disabled'
</strong> ]); ?>
</div>
<div id="installUpdateSuccess" class="colorGreen displayNone">
<?php echo template::ico('check'); ?>
<?php echo helper::translate('Mise à jour terminée avec succès.'); ?>
</div> </div>
</div> </div>
<div class="col3 verticalAlignTop"> <div class="row">
<?php echo template::button('installUpdateEnd', [ <div class="col12">
'value' => 'Terminer', <p><em><span class="colorRed" id="installUpdateErrorMessage"></span></em></p>
'href' => helper::baseUrl() . 'config', </div>
'ico' => 'check',
'class' => 'disabled'
]); ?>
</div> </div>
</div> </div>
<div class="row">
<div class="col12">
<p><em><span class="colorRed" id="installUpdateErrorMessage"></span></em></p>
</div>
</div

View File

@ -0,0 +1,712 @@
<?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-2024, Frédéric Tempez
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/
*/
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 = [
'index' => self::GROUP_ADMIN,
'copy' => self::GROUP_ADMIN,
'add' => self::GROUP_ADMIN,
// Ajouter une langue de contenu
'edit' => self::GROUP_ADMIN,
// Éditer une langue de l'UI
'locale' => self::GROUP_ADMIN,
// Éditer une langue de contenu
'delete' => self::GROUP_ADMIN,
// Effacer une langue de contenu ou de l'interface
'content' => self::GROUP_VISITOR,
'update' => self::GROUP_ADMIN,
'default' => self::GROUP_ADMIN
];
const PAGINATION = '20';
// Language contents
public static $translateOptions = [];
// Page pour la configuration dans la langue
public static $pagesList = [];
public static $orphansList = [];
public static $pages = '';
// Liste des langues installées
public static $languagesUiInstalled = [];
public static $languagesInstalled = [];
public static $languagesStore = [];
public static $dialogues = [];
// Liste des langues cibles
public static $languagesTarget = [];
// Activation du bouton de copie
public static $siteCopy = true;
// Localisation en cours d'édition
public static $locales = [];
//UI
// Fichiers des langues de l'interface
public static $i18nFiles = [];
/**
* Met à jour les traduction du site depuis le store
*/
public function update()
{
if (
$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
) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'language',
'state' => false,
'notification' => helper::translate('Action interdite')
]);
}
// Télécharger le descripteur en ligne
$languageData = json_decode(helper::getUrlContents(self::ZWII_UI_URL . $lang . '.json'), true);
$descripteur = json_decode(helper::getUrlContents(self::ZWII_UI_URL . 'language.json'), true);
$success = false;
if (
is_array($languageData) &&
is_array($descripteur['language'][$lang])
) {
if ($this->setData(['language', $lang, $descripteur['language'][$lang]])) {
$success = $this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', $languageData);
$success = is_int($success) ? true : false;
}
}
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'language',
'notification' => $success ? helper::translate('Copie terminée avec succès') : 'Copie terminée avec des erreurs',
'state' => $success
]);
}
}
/**
* Configuration avancée des langues
*/
public function copy()
{
// Soumission du formulaire
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Initialisation
$success = false;
$copyFrom = $this->getInput('translateFormCopySource');
$toCreate = $this->getInput('translateFormCopyTarget');
if ($copyFrom !== $toCreate) {
// Création du dossier
if (is_dir(self::DATA_DIR . $toCreate) === false) { // Si le dossier est déjà créé
$success = mkdir(self::DATA_DIR . $toCreate, 0755);
$success = mkdir(self::DATA_DIR . $toCreate . '/content', 0755);
} else {
$success = true;
}
// Copier les données par défaut
$success = (copy(self::DATA_DIR . $copyFrom . '/locale.json', self::DATA_DIR . $toCreate . '/locale.json') === true && $success === true) ? true : false;
$success = (copy(self::DATA_DIR . $copyFrom . '/module.json', self::DATA_DIR . $toCreate . '/module.json') === true && $success === true) ? true : false;
$success = (copy(self::DATA_DIR . $copyFrom . '/page.json', self::DATA_DIR . $toCreate . '/page.json') === true && $success === true) ? true : false;
$success = ($this->copyDir(self::DATA_DIR . $copyFrom . '/content', self::DATA_DIR . $toCreate . '/content') === true && $success === true) ? true : false;
// Enregistrer la langue
if ($success) {
$notification = sprintf(helper::translate('Données %s copiées vers %s'), self::$languages[$copyFrom], self::$languages[$toCreate]);
} else {
$notification = helper::translate('Erreur de copie, vérifiez les permissions');
}
} else {
$success = false;
$notification = helper::translate('Les langues sélectionnées sont identiques');
}
// Valeurs en sortie
$this->addOutput([
'notification' => $notification,
'title' => 'Utilitaire de copie',
'view' => 'index',
'state' => $success
]);
}
// Tableau des langues installées
foreach (self::$languages as $key => $value) {
// tableau des langues installées
if (is_dir(self::DATA_DIR . $key)) {
self::$languagesTarget[$key] = self::$languages[$key];
}
}
// Langues cibles fr en plus
self::$languagesInstalled = self::$languagesTarget;
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Copie de contenus localisés'),
'view' => 'copy'
]);
}
/**
* Configuration
*/
public function index()
{
// --------------------------------------------------------------------------------------------------
// Langues du site
// --------------------------------------------------------------------------------------------------
foreach (self::$languages as $key => $value) {
// tableau des langues installées
if (is_dir(self::DATA_DIR . $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');
} elseif (isset($_SESSION['ZWII_SITE_CONTENT']) && $_SESSION['ZWII_SITE_CONTENT'] === $key) {
$messageLocale = helper::translate('Langue du site sélectionnée');
} else {
$messageLocale = '';
}
self::$languagesInstalled[] = [
template::flag($key, '20 %') . '&nbsp;' . $value . ' (' . $key . ')',
$messageLocale,
template::button('translateContentLanguageLocaleEdit' . $key, [
'class' => file_exists(self::DATA_DIR . $key . '/locale.json') ? '' : ' disabled',
'href' => helper::baseUrl() . $this->getUrl(0) . '/locale/' . $key,
'value' => template::ico('pencil'),
'help' => 'Éditer'
]),
template::button('translateContentLanguageLocaleDelete' . $key, [
'class' => 'translateDelete buttonRed' . ($messageLocale ? ' disabled' : ''),
'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/locale/' . $key,
'value' => template::ico('trash'),
'help' => 'Supprimer',
])
];
}
}
}
// Activation du bouton de copie
self::$siteCopy = count(self::$languagesInstalled) > 1 ? false : true;
// --------------------------------------------------------------------------------------------------
// Langues de l'UI
// --------------------------------------------------------------------------------------------------
// Langues attachées à des utilisateurs non effaçables
$usersUI = [];
$users = $this->getData(['user']);
foreach ($users as $key => $value) {
array_push($usersUI, $this->getData(['user', $key, 'language']));
}
// Langues installées
$installedUI = $this->getData(['language']);
if (array_key_exists('language', $installedUI)) {
$installedUI = $installedUI['language'];
}
// Langues disponibles en ligne
$storeUI = json_decode(helper::getUrlContents(self::ZWII_UI_URL . 'language.json'), true);
$storeUI = $storeUI ? $storeUI['language'] : null;
// Construction du tableau à partir des langues disponibles dans le store
foreach ($installedUI as $file => $value) {
// La langue est-elle référencée ?
if (array_key_exists(basename($file, '.json'), $installedUI)) {
// La langue est déjà installée
self::$languagesUiInstalled[$file] = [
template::flag($file, '20 %') . '&nbsp;' . self::$languages[$file],
$value['version'],
helper::dateUTF8('%d/%m/%Y', $value['date'], self::$i18nUI),
//self::$i18nUI === $file ? helper::translate('Interface') : '',
'',
/*
template::button('translateContentLanguageUIEdit' . $file, [
'href' => helper::baseUrl() . $this->getUrl(0) . '/edit/' . $file,
'value' => template::ico('pencil'),
'help' => 'Éditer',
'disabled' => 'fr_FR' === $file
]),
*/
template::button('translateContentLanguageUIDownload' . $file, [
'class' => isset($storeUI[$file]['version']) && version_compare($installedUI[$file]['version'], $storeUI[$file]['version']) < 0 ? 'buttonGreen' : '',
'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file,
'value' => template::ico('update'),
'help' => 'Mise à jour',
]),
template::button('translateContentLanguageUIDelete' . $file, [
'class' => 'translateDelete buttonRed' . (in_array($file, $usersUI) ? ' disabled' : ''),
'href' => helper::baseUrl() . $this->getUrl(0) . '/delete/ui/' . $file,
'value' => template::ico('trash'),
'help' => 'Supprimer',
]),
];
}
}
// Construction du tableau à partir des langues disponibles dans le store
if ($storeUI) {
foreach ($storeUI as $file => $value) {
// La langue est-elle installée ?
if (array_key_exists($file, $installedUI) === false) {
self::$languagesStore[$file] = [
template::flag($file, '20 %') . '&nbsp;' . self::$languages[$file],
$value['version'],
helper::dateUTF8('%d/%m/%Y', $value['date'], self::$i18nUI),
'',
template::button('translateContentLanguageUIDownload' . $file, [
'class' => 'buttonGreen',
'href' => helper::baseUrl() . $this->getUrl(0) . '/update/' . $file,
'value' => template::ico('shopping-basket'),
'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
$this->addOutput([
'title' => helper::translate('Langues'),
'view' => 'index'
]);
}
/***
* Ajouter une langue de contenu
*/
public function add()
{
// Soumission du formulaire
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
$lang = $this->getInput('translateAddContent');
// Constructeur pour cette langue
$this->jsonDB($lang);
// Création du contenu
$this->initData('page', $lang);
$this->initData('module', $lang);
$this->initData('locale', $lang);
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'language',
'notification' => helper::translate('Modifications enregistrées'),
'state' => true
]);
}
// Préparation de l'affichage du formulaire
//-----------------------------------------
// Tableau des langues non installées
foreach (self::$languages as $key => $value) {
if (!is_dir(self::DATA_DIR . $key))
self::$i18nFiles[$key] = $value;
}
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Nouveau contenu localisé'),
'view' => 'add'
]);
}
/**
* Edition des paramètres de la langue de contenu
*/
public function locale()
{
// 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')
]);
}
// Soumission du formulaire
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Sauvegarder les locales
$data = [
'locale' => [
'homePageId' => $this->getInput('localeHomePageId', helper::FILTER_ID, true),
'page404' => $this->getInput('localePage404'),
'page403' => $this->getInput('localePage403'),
'page302' => $this->getInput('localePage302'),
'legalPageId' => $this->getInput('localeLegalPageId'),
'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),
'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),
'metaDescription' => $this->getInput('localeMetaDescription', helper::FILTER_STRING_LONG, true),
'title' => $this->getInput('localeTitle', helper::FILTER_STRING_SHORT, true),
'cookies' => [
// Les champs sont obligatoires si l'option consentement des cookies est active
'mainLabel' => $this->getInput('localeCookiesZwiiText', helper::FILTER_STRING_LONG, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
'titleLabel' => $this->getInput('localeCookiesTitleText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
'linkLegalLabel' => $this->getInput('localeCookiesLinkMlText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
'cookiesFooterText' => $this->getInput('localeCookiesFooterText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
'buttonValidLabel' => $this->getInput('localeCookiesButtonText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN))
]
]
];
// Sauvegarde hors méthodes si la langue n'est pas celle de l'UI
if ($lang === self::$siteContent) {
// Enregistrer les données par lecture directe du formulaire
$this->setData(['locale', $data['locale']]);
} else {
// Sauver sur le disque
$this->secure_file_put_contents(self::DATA_DIR . $lang . '/locale.json', $data);
}
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl(),
'notification' => helper::translate('Modifications enregistrées'),
'state' => true
]);
}
// Préparation de l'affichage du formulaire
//-----------------------------------------
// La locale est-elle celle de la langue de l'UI ?
if ($lang === self::$siteContent) {
self::$locales[$lang]['locale'] = $this->getData(['locale']);
} else {
// Lire les locales sans passer par les méthodes
self::$locales[$lang] = json_decode(file_get_contents(self::DATA_DIR . $lang . '/locale.json'), true);
}
// Générer la liste des pages disponibles
self::$pagesList = $this->getData(['page']);
foreach (self::$pagesList as $page => $pageId) {
if (
$this->getData(['page', $page, 'block']) === 'bar' ||
$this->getData(['page', $page, 'disable']) === true
) {
unset(self::$pagesList[$page]);
}
}
self::$orphansList = $this->getData(['page']);
foreach (self::$orphansList as $page => $pageId) {
if (
$this->getData(['page', $page, 'block']) === 'bar' ||
$this->getData(['page', $page, 'disable']) === true ||
$this->getdata(['page', $page, 'position']) !== 0
) {
unset(self::$orphansList[$page]);
}
}
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Paramètres de la localisation') . '&nbsp;' . template::flag($lang, '20 %'),
'view' => 'locale'
]);
}
/**
* Edition de la langue de l'interface
*/
public function edit()
{
$lang = $this->getUrl(2);
// Action interdite ou URl avec le code langue incorrecte
if (
array_key_exists($lang, self::$languages) === false
) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'language',
'state' => false,
'notification' => helper::translate('Action interdite')
]);
}
// Soumission du formulaire
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$this->isPost()
) {
// Sauvegarder les champs de la langue
$data = json_decode(file_get_contents(self::I18N_DIR . $lang . '.json'), true);
foreach ($data as $key => $value) {
$target = $this->getInput('translateString' . array_search($key, array_keys($data)));
if (empty($target) === false) {
$data[$key] = $target;
}
}
$this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', $data);
// Mettre à jour le descripteur
$this->setData([
'language',
$lang,
[
'version' => $this->getInput('translateEditVersion'),
'date' => $this->getInput('translateEditDate', helper::FILTER_DATETIME),
]
]);
// Valeurs en sortie
$this->addOutput([
'notification' => helper::translate('Modifications enregistrées'),
'redirect' => helper::baseUrl() . 'language',
'state' => true,
]);
}
// Construction du formulaire
// Chargement des dialogue de la langue cible
if (!isset($data)) {
$data = json_decode(file_get_contents(self::I18N_DIR . $this->getUrl(2) . '.json'), true);
}
// Ajout des champs absents selon la langue de référence
$dataFr = json_decode(file_get_contents(self::I18N_DIR . 'fr_FR.json'), true);
foreach ($dataFr as $key => $value) {
if (!array_key_exists($key, $data)) {
$data[$key] = '';
}
}
$this->secure_file_put_contents(self::I18N_DIR . $lang . '.json', $data);
// Tableau des chaines à traduire dans la langue sélectionnée
foreach ($data as $key => $value) {
$dialogues[] = ['source' => $key, 'target' => $value];
}
// Pagination
$pagination = helper::pagination($dialogues, $this->getUrl(), self::PAGINATION);
// Liste des pages
self::$pages = $pagination['pages'];
// Articles en fonction de la pagination
for ($i = $pagination['first']; $i < $pagination['last']; $i++) {
self::$dialogues[$i] = $dialogues[$i];
}
// Valeurs en sortie
$this->addOutput([
'title' => helper::translate('Éditer les dialogues') . '&nbsp;' . template::flag($lang, '20 %'),
'view' => 'edit',
'vendor' => [
'flatpickr',
],
]);
}
/***
* Effacer une langue de contenu
*/
public function delete()
{
if (
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
) {
// Valeurs en sortie
$this->addOutput([
'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,
'notification' => helper::translate('Action interdite')
]);
}
switch ($target) {
case 'locale':
$success = false;
// Effacement d'une site dans une langue
if (is_dir(self::DATA_DIR . $lang) === true) {
$success = $this->deleteDir(self::DATA_DIR . $lang);
}
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'language',
'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'),
'state' => $success
]);
break;
case 'ui':
$success = false;
// Effacement d'une langue de l'interface
if (file_exists(self::I18N_DIR . $lang . '.json') === true) {
$this->deleteData(['language', $lang]);
$success = unlink(self::I18N_DIR . $lang . '.json');
}
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'language',
'notification' => $success ? helper::translate('Traduction supprimée') : helper::translate('Erreur inconnue'),
'state' => $success
]);
break;
default:
# Do nothing
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
* Fonction utilisée par le noyau
*/
public function content()
{
// Langue sélectionnée
$lang = $this->getUrl(2);
/**
* Changement de la langue si
* différe de la langue active
* déjà initialisée
* fait partie des langues installées
*/
if (
is_dir(self::DATA_DIR . $lang) &&
array_key_exists($lang, self::$languages) === true
) {
// Stocker la sélection
$_SESSION['ZWII_SITE_CONTENT'] = $lang;
}
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl()
]);
}
}

View File

@ -7,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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>
@ -21,12 +21,12 @@
<div class="row"> <div class="row">
<div class="col6"> <div class="col6">
<?php echo template::select('translateFormCopySource', $module::$languagesInstalled, [ <?php echo template::select('translateFormCopySource', $module::$languagesInstalled, [
'label' => 'De' 'label' => 'Source'
]); ?> ]); ?>
</div> </div>
<div class="col6"> <div class="col6">
<?php echo template::select('translateFormCopyTarget', $module::$languagesTarget, [ <?php echo template::select('translateFormCopyTarget', $module::$languagesTarget, [
'label' => 'Vers' 'label' => 'Cible'
]); ?> ]); ?>
</div> </div>
</div> </div>

View File

@ -7,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */

View File

@ -0,0 +1,59 @@
<?php echo template::formOpen('translateUIForm'); ?>
<div class="row">
<div class="col1">
<?php echo template::button('translateUIFormBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl() . 'language',
'value' => template::ico('left')
]); ?>
</div>
<div class="col2 offset9">
<?php echo template::submit('translateUIFormSubmit'); ?>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>
<?php echo helper::translate('Paramètres'); ?>
</h4>
<div class="row">
<div class="col6">
<?php echo template::text('translateEditVersion', [
'label' => 'Version n°',
'value' => $this->getData(['language', $this->getUrl(2), 'version'])
]); ?>
</div>
<div class="col6">
<?php echo template::date('translateEditDate', [
'label' => 'Date de publication',
'type' => 'datetime-local',
'value' => $this->getData(['language', $this->getUrl(2), 'date'])
]); ?>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<div class="row">
<?php foreach ($module::$dialogues as $key => $value) : ?>
<div class="col6">
<?php echo sprintf('%g -', $key); ?>
<?php echo $value['source']; ?>
</div>
<div class="col6">
<?php echo template::text('translateString' . $key, [
'label' => '',
'value' => $value['target']
]); ?>
</div>
<?php endforeach; ?>
</div>
<?php echo $module::$pages; ?>
</div>
</div>
</div>
<?php echo template::formClose(); ?>

View File

@ -7,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -21,7 +21,6 @@
display: block; display: block;
} }
.buttonNotice { .buttonNotice {
border: 2px solid red !important; border: 2px solid red !important;
border-radius: 2px; border-radius: 2px;

View File

@ -6,8 +6,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -15,18 +15,15 @@
$(document).ready(function() { $(document).ready(function() {
var translateLayout = getCookie("translateLayout"); var translateLayout = getCookie("translateLayout");
if (translateLayout == null) { if (translateLayout == null) {
translateLayout = "ui"; translateLayout = "content";
setCookie("translateLayout", "ui"); setCookie("translateLayout", "content");
} }
$("#contentContainer").hide(); $("#contentContainer").hide();
$("#uiContainer").hide(); $("#uiContainer").hide();
$("#" + translateLayout + "Container").show(); $("#" + translateLayout + "Container").show();
$("#translate" + capitalizeFirstLetter(translateLayout) + "Button").addClass("activeButton"); $("#translate" + capitalizeFirstLetter(translateLayout) + "Button").addClass("activeButton");
// Afficher les boutons liés au contenu
$(".translateButtonAddContent").show();
$(".translateButtonCopyContent").show();
// Cacher le bouton de mise à jour
$(".translateButtonUpdateContent").hide();
}); });
@ -38,11 +35,6 @@ $("#translateUiButton").on("click", function() {
$(this).addClass("activeButton"); $(this).addClass("activeButton");
$("#translateContentButton").removeClass("activeButton"); $("#translateContentButton").removeClass("activeButton");
setCookie("translateLayout", "ui"); setCookie("translateLayout", "ui");
// Cacher les boutons liés au contenu
$(".translateButtonAddContent").hide();
$(".translateButtonCopyContent").hide();
// Afficher le bouton de mise à jour
$(".translateButtonUpdateContent").show();
}); });
$("#translateContentButton").on("click", function() { $("#translateContentButton").on("click", function() {
@ -52,10 +44,7 @@ $("#translateContentButton").on("click", function() {
$("#translateUiButton").removeClass("activeButton"); $("#translateUiButton").removeClass("activeButton");
setCookie("translateLayout", "content"); setCookie("translateLayout", "content");
// Afficher les boutons liés au contenu // Afficher les boutons liés au contenu
$(".translateButtonAddContent").show(); $(".contentButtonContainer").show();
$(".translateButtonCopyContent").show();
// Cacher le bouton de mise à jour
$(".translateButtonUpdateContent").hide();
}); });
/** /**
@ -63,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

@ -0,0 +1,98 @@
<?php echo template::formOpen('translateForm'); ?>
<div class="row">
<div class="col1">
<?php echo template::button('translateFormBack', [
'class' => 'buttonGrey',
'href' => helper::baseUrl(),
'value' => template::ico('home')
]); ?>
</div>
<div class="col1">
<?php /**echo template::button('translateHelp', [
'href' => 'https://doc.zwiicms.fr/prise-en-charge-des-langues-etrangeres',
'target' => '_blank',
'value' => template::ico('help'),
'class' => 'buttonHelp',
'help' => 'Consulter l\'aide en ligne'
]);*/?>
</div>
</div>
<div class="tab">
<?php echo template::button('translateUiButton', [
'value' => 'Interface',
'class' => 'buttonTab'
]); ?>
<?php echo template::button('translateContentButton', [
'value' => 'Site',
'class' => 'buttonTab'
]); ?>
</div>
<div id="uiContainer" class="tabContent">
<div class="row">
<div class="col12">
<div class="block">
<h4>
<?php echo helper::translate('Langues installées'); ?>
</h4>
<?php if ($module::$languagesUiInstalled): ?>
<?php echo template::table([2, 1, 1, 5, 1, 1], $module::$languagesUiInstalled, ['Langues', 'Version', 'Date', '', '', '']); ?>
<?php endif; ?>
</div>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>
<?php echo helper::translate('Catalogue'); ?>
</h4>
<?php if ($module::$languagesStore): ?>
<?php echo template::table([2, 1, 2, 6, 1], $module::$languagesStore, ['Langues', 'Version', 'Date', '', '']); ?>
<?php endif; ?>
</div>
</div>
</div>
</div>
<div id="contentContainer" class="tabContent">
<div class="row">
<div class="col12">
<div class="block">
<h4>
<?php echo helper::translate('Paramètres'); ?>
</h4>
<div class="col4 offset2">
<?php echo template::button('translateButtonCopyContent', [
'href' => helper::baseUrl() . 'language/copy',
'ico' => 'docs',
'disabled' => $module::$siteCopy,
'value' => 'Copie de contenus localisés'
]); ?>
</div>
<div class="col4">
<?php echo template::button('translateButtonAddContent', [
'href' => helper::baseUrl() . 'language/add',
'ico' => 'plus',
'class' => 'buttonGreen',
'value' => 'Nouveau contenu localisé'
]); ?>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col12">
<div class="block">
<h4>
<?php echo helper::translate('Langues installées'); ?>
</h4>
<?php if ($module::$languagesInstalled): ?>
<?php echo template::table([2, 6, 1, 1], $module::$languagesInstalled, ['Langues', '', '', '']); ?>
<?php endif; ?>
</div>
</div>
</div>
</div>
<?php echo template::formClose(); ?>

View File

@ -7,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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>
@ -24,7 +24,7 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<?php echo template::text('localeTitle', [ <?php echo template::text('localeTitle', [
'label' => 'Titre du site', 'label' => 'Titre',
'value' => $module::$locales[$this->getUrl(2)]['locale']['title'], 'value' => $module::$locales[$this->getUrl(2)]['locale']['title'],
'help' => 'Il apparaît dans la barre de titre et les partages sur les réseaux sociaux.' 'help' => 'Il apparaît dans la barre de titre et les partages sur les réseaux sociaux.'
]); ?> ]); ?>
@ -33,7 +33,7 @@
<div class="row"> <div class="row">
<div class="col12"> <div class="col12">
<?php echo template::textarea('localeMetaDescription', [ <?php echo template::textarea('localeMetaDescription', [
'label' => 'Description du site', 'label' => 'Description',
'value' => $module::$locales[$this->getUrl(2)]['locale']['metaDescription'], 'value' => $module::$locales[$this->getUrl(2)]['locale']['metaDescription'],
'help' => 'La description d\'une page participe à son référencement, chaque page doit disposer d\'une description différente.' 'help' => 'La description d\'une page participe à son référencement, chaque page doit disposer d\'une description différente.'
]); ?> ]); ?>
@ -55,7 +55,7 @@
<div class="row"> <div class="row">
<div class="col4"> <div class="col4">
<?php echo template::select('localeHomePageId', helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC'), [ <?php echo template::select('localeHomePageId', helper::arrayColumn($module::$pagesList, 'title', 'SORT_ASC'), [
'label' => 'Accueil du site', 'label' => 'Accueil',
'selected' => $module::$locales[$this->getUrl(2)]['locale']['homePageId'], 'selected' => $module::$locales[$this->getUrl(2)]['locale']['homePageId'],
'help' => 'La première page que vos visiteurs verront.' 'help' => 'La première page que vos visiteurs verront.'
]); ?> ]); ?>
@ -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'],
@ -160,8 +167,8 @@
<div class="row"> <div class="row">
<div class="col6"> <div class="col6">
<?php echo template::text('localeCookiesTitleText', [ <?php echo template::text('localeCookiesTitleText', [
'help' => 'Saisissez le titre de la fenêtre de gestion des cookies.', 'help' => 'Saisissez le Titre de gestion des cookies.',
'label' => 'Titre de la fenêtre', 'label' => 'Titre',
'value' => $module::$locales[$this->getUrl(2)]['locale']['cookies']['titleLabel'], 'value' => $module::$locales[$this->getUrl(2)]['locale']['cookies']['titleLabel'],
'placeHolder' => 'Cookies essentiels' 'placeHolder' => 'Cookies essentiels'
]); ?> ]); ?>

View File

@ -8,8 +8,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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,8 +9,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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'
@ -41,28 +42,42 @@ class page extends common
// Position du module // Position du module
public static $modulePosition = [ public static $modulePosition = [
'bottom' => 'Après le contenu de la page', 'bottom' => 'Après le contenu de la page',
'top' => 'Avant le contenu de la page', 'top' => 'Avant le contenu de la page',
'free' => 'À l\'emplacement du mot clé [MODULE] dans la page' 'free' => 'À l\'emplacement du mot clé [MODULE] dans la page'
]; ];
public static $pageBlocks = [ public static $pageBlocks = [
'12' => 'Page standard', '12' => 'Page standard',
'bar' => 'Barre latérale', 'bar' => 'Barre latérale',
'4-8' => 'Barre 1/3 - page 2/3', '4-8' => 'Barre 1/3 - page 2/3',
'8-4' => 'Page 2/3 - barre 1/3', '8-4' => 'Page 2/3 - barre 1/3',
'3-9' => 'Barre 1/4 - page 3/4', '3-9' => 'Barre 1/4 - page 3/4',
'9-3' => 'Page 3/4 - barre 1/4', '9-3' => 'Page 3/4 - barre 1/4',
'3-6-3' => 'Barre 1/4 - page 1/2 - barre 1/4', '3-6-3' => 'Barre 1/4 - page 1/2 - barre 1/4',
'2-7-3' => 'Barre 2/12 - page 7/12 - barre 3/12', '2-7-3' => 'Barre 2/12 - page 7/12 - barre 3/12',
'3-7-2' => 'Barre 3/12 - page 7/12 - barre 2/12', '3-7-2' => 'Barre 3/12 - page 7/12 - barre 2/12',
]; ];
public static $displayMenu = [ public static $displayMenu = [
'none' => 'Aucun menu', 'none' => 'Aucun menu',
'parents' => 'Le menu horizontal intégral', 'parents' => 'Le menu horizontal intégral',
'children' => 'Le sous-menu de la page parente' 'children' => 'Le sous-menu de la page parente'
]; ];
public static $extraPosition = [ public static $extraPosition = [
false => 'Menu standard', false => 'Menu standard',
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',
]; ];
@ -71,56 +86,55 @@ class page extends common
*/ */
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'])) { // Duplication de la page
// Valeurs en sortie $pageTitle = $this->getData(['page', $page, 'title']);
$this->addOutput([ $pageId = helper::increment(helper::filter($pageTitle, helper::FILTER_ID), $this->getData(['page']));
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0], $pageId = helper::increment($pageId, self::$coreModuleIds);
'notification' => helper::translate('Jeton invalide') $pageId = helper::increment($pageId, self::$moduleIds);
]);
} 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
$pageTitle = $this->getData(['page', $url[0], 'title']);
$pageId = helper::increment(helper::filter($pageTitle, helper::FILTER_ID), $this->getData(['page']));
$pageId = helper::increment($pageId, self::$coreModuleIds);
$pageId = helper::increment($pageId, self::$moduleIds);
$data = $this->getData([
'page',
$url[0]
]);
// Ecriture
$this->setData(['page', $pageId, $data]);
$notification = helper::translate('Page dupliquée');
// Duplication du module présent
if ($this->getData(['page', $url[0], 'moduleId'])) {
$data = $this->getData([ $data = $this->getData([
'module', 'page',
$url[0] $page
]); ]);
// Ecriture // Ecriture
$this->setData(['module', $pageId, $data]); $this->setData(['page', $pageId, $data]);
$notification = helper::translate('Page et module dupliqués'); $notification = helper::translate('Page dupliquée');
// Duplication du module présent
if ($this->getData(['page', $page, 'moduleId'])) {
$data = $this->getData(['module', $page]);
$this->setData(['module', $pageId, $data]);
$notification = helper::translate('Page et module dupliqués');
}
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $pageId . '/' . self::$siteContent,
'notification' => $notification,
'state' => true
]);
} }
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $pageId,
'notification' => $notification,
'state' => true
]);
} }
@ -129,55 +143,76 @@ class page extends common
*/ */
public function add() public function add()
{ {
$pageTitle = 'Nouvelle page'; // La session ne correspond pas au site ouvert dans cet onglet
$pageId = helper::increment(helper::filter($pageTitle, helper::FILTER_ID), $this->getData(['page'])); if (
$this->setData([ // 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
'page', $this->getUrl(3) && $this->getUrl(3) != self::$siteContent
$pageId, ) {
[ $_SESSION['ZWII_SITE_CONTENT'] = $this->getUrl(3);
'typeMenu' => 'text', header('Refresh:0; url=' . helper::baseUrl() . $this->getUrl());
'iconUrl' => '', exit();
'disable' => false,
'content' => $pageId . '.html',
'hideTitle' => false,
'breadCrumb' => false,
'metaDescription' => '',
'metaTitle' => '',
'moduleId' => '',
'parentPageId' => '',
'modulePosition' => 'bottom',
'position' => 0,
'group' => self::GROUP_VISITOR,
'targetBlank' => false,
'title' => $pageTitle,
'shortTitle' => $pageTitle,
'block' => '12',
'barLeft' => '',
'barRight' => '',
'displayMenu' => '0',
'hideMenuSide' => false,
'hideMenuHead' => false,
'hideMenuChildren' => false,
'js' => '',
'css' => ''
]
]);
// Creation du contenu de la page
if (!is_dir(self::DATA_DIR . self::$i18nContent . '/content')) {
mkdir(self::DATA_DIR . self::$i18nContent . '/content', 0755);
} }
//file_put_contents(self::DATA_DIR . self::$i18nContent . '/content/' . $pageId . '.html', '<p>Contenu de votre nouvelle page.</p>');
$this->setPage($pageId, '<p>Contenu de votre nouvelle page.</p>', self::$i18nContent); if ($this->getUser('permission', __CLASS__, __FUNCTION__) !== true) {
// Met à jour le site map // Valeurs en sortie
$this->createSitemap('all'); $this->addOutput([
// Mise à jour de la liste des pages pour TinyMCE 'access' => false
$this->listPages(); ]);
// Valeurs en sortie } else {
$this->addOutput([ $pageTitle = 'Nouvelle page';
'redirect' => helper::baseUrl() . $pageId, $pageId = helper::increment(helper::filter($pageTitle, helper::FILTER_ID), $this->getData(['page']));
'notification' => helper::translate('Nouvelle page créée'), $this->setData([
'state' => true 'page',
]); $pageId,
[
'typeMenu' => 'text',
'iconUrl' => '',
'disable' => false,
'content' => $pageId . '.html',
'hideTitle' => false,
'breadCrumb' => false,
'metaDescription' => '',
'metaTitle' => '',
'moduleId' => '',
'parentPageId' => '',
'modulePosition' => 'bottom',
'position' => 0,
'group' => self::GROUP_VISITOR,
'targetBlank' => false,
'title' => $pageTitle,
'shortTitle' => $pageTitle,
'block' => '12',
'barLeft' => '',
'barRight' => '',
'navLeft' => 'none',
'navRight' => 'none',
'navTemplate' => 'dir',
'displayMenu' => '0',
'hideMenuSide' => false,
'hideMenuHead' => false,
'hideMenuChildren' => false,
'js' => '',
'css' => ''
]
]);
// Creation du contenu de la page
if (!is_dir(self::DATA_DIR . self::$siteContent . '/content')) {
mkdir(self::DATA_DIR . self::$siteContent . '/content', 0755);
}
//$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::$siteContent);
// Ne met à jour le sitemap pour éviter un warning, de toute manière la nouvelle page doit être éditée.
// $this->updateSitemap();
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . $pageId,
'notification' => helper::translate('Nouvelle page créée'),
'state' => true
]);
}
} }
/** /**
@ -185,120 +220,105 @@ class page extends common
*/ */
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
$this->addOutput([
'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
]);
}
// Impossible de supprimer la page de recherche affectée
elseif ($url[0] === $this->getData(['locale', 'searchPageId'])) {
// Valeurs en sortie
$this->addOutput([
'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite, page active dans la configuration du site')
]);
}
// Impossible de supprimer la page des mentions légales affectée
elseif ($url[0] === $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', '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', 'page403'])) { 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', 'page302'])) { 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')
]); ]);
} }
// Jeton incorrect // Impossible de supprimer la page affectée
elseif (!isset($_GET['csrf'])) { elseif ($page === $this->getData(['locale', 'page403'])) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0], 'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Jeton invalide') 'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
]); ]);
} elseif ($_GET['csrf'] !== $_SESSION['csrf']) { }
// Impossible de supprimer la page affectée
elseif ($page === $this->getData(['locale', 'page302'])) {
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'page/edit/' . $url[0], 'redirect' => helper::baseUrl() . 'config',
'notification' => helper::translate('Suppression interdite') 'notification' => helper::translate('Suppression interdite, page active dans la configuration de la langue du site')
]); ]);
} }
// 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 +334,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 +358,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é
@ -358,7 +395,7 @@ 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]);
} }
@ -375,8 +412,8 @@ 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 :
@ -433,7 +470,7 @@ class page extends common
// Une page parent devient orpheline, les pages enfants le devienne pour éviter une incohérence // Une page parent devient orpheline, les pages enfants le devienne pour éviter une incohérence
if ( if (
$position === 0 && $position === 0 &&
$position !== $this->getData(['page', $this->getUrl(2), 'position']) && $position !== $this->getData(['page', $this->getUrl(2), 'position']) &&
$this->getinput('pageEditBlock') !== 'bar' $this->getinput('pageEditBlock') !== 'bar'
) { ) {
foreach ($this->getHierarchy($pageId) as $parentId => $childId) { foreach ($this->getHierarchy($pageId) as $parentId => $childId) {
@ -462,6 +499,18 @@ class page extends common
} }
} }
} }
// 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,34 +529,36 @@ 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),
'hideMenuChildren' => $this->getinput('pageEditHideMenuChildren', helper::FILTER_BOOLEAN), 'hideMenuChildren' => $this->getinput('pageEditHideMenuChildren', helper::FILTER_BOOLEAN),
'extraPosition' => $this->getinput('pageEditExtraPosition', helper::FILTER_BOOLEAN), 'extraPosition' => $this->getinput('pageEditExtraPosition', helper::FILTER_BOOLEAN),
'css' => $this->getData(['page', $this->getUrl(2), 'css']), 'css' => $this->getData(['page', $this->getUrl(2), 'css']) == null ? '' : $this->getData(['page', $this->getUrl(2), 'css']),
'js' => $this->getData(['page', $this->getUrl(2), 'js']), 'js' => $this->getData(['page', $this->getUrl(2), 'js']) == null ? '' : $this->getData(['page', $this->getUrl(2), 'js']),
] ]
]); ]);
// 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 (
@ -529,7 +580,19 @@ class page extends common
} }
} }
} }
self::$moduleIds = array_merge(['' => 'Aucun'], helper::arrayColumn(helper::getModules(), 'realName', 'SORT_ASC')); // Pages sans parent // Construction du formulaire
// Met à jour le sitemap
$this->updateSitemap();
// Création du sélecteur de modules
self::$moduleIds = [];
foreach (helper::getModules() as $key => $values) {
self::$moduleIds[$key] = $values['realName'] . ' (' . $key . ')';
}
self::$moduleIds = array_merge(['' => 'Aucun'], self::$moduleIds);
// Pages sans parent
foreach ($this->getHierarchy() as $parentPageId => $childrenPageIds) { foreach ($this->getHierarchy() as $parentPageId => $childrenPageIds) {
if ($parentPageId !== $this->getUrl(2)) { if ($parentPageId !== $this->getUrl(2)) {
self::$pagesNoParentId[$parentPageId] = $this->getData(['page', $parentPageId, 'title']); self::$pagesNoParentId[$parentPageId] = $this->getData(['page', $parentPageId, 'title']);
@ -544,6 +607,20 @@ class page extends common
self::$pagesBarId[$parentPageId] = $this->getData(['page', $parentPageId, 'title']); self::$pagesBarId[$parentPageId] = $this->getData(['page', $parentPageId, 'title']);
} }
} }
// Profils installés
// Profils disponibles
foreach ($this->getData(['profil']) as $profilId => $profilData) {
if ($profilId < self::GROUP_MEMBER) {
continue;
}
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']),
@ -561,20 +638,22 @@ class page extends common
public function cssEditor() public function cssEditor()
{ {
// Soumission du formulaire // Soumission du formulaire
if ($this->isPost()) { if (
// Supprime les balises styles si elles ont été saisies $this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$css = $this->getInput('pageCssEditorContent', null); $this->isPost()
$css = str_replace('<style>', '', $css); ) {
$css = str_replace('</style>', '', $css); $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), 'css', 'page',
$this->getUrl(2),
'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
]); ]);
} }
@ -594,20 +673,22 @@ class page extends common
public function jsEditor() public function jsEditor()
{ {
// Soumission du formulaire // Soumission du formulaire
// Supprime les balises scripts si elles ont été saisies if (
$js = $this->getInput('pageJsEditorContent', null); $this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
$js = str_replace('<script>', '', $js); $this->isPost()
$js = str_replace('<script>', '', $js); ) {
if ($this->isPost()) { $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), 'js', 'page',
$this->getUrl(2),
'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
]); ]);
} }
@ -620,4 +701,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,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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>
@ -12,12 +12,9 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col12">
<?php echo helper::translate('Ne pas saisir les balises') . htmlentities(' <style></style>'); ?>
</div>
<div class="col12"> <div class="col12">
<?php echo template::textarea('pageCssEditorContent', [ <?php echo template::textarea('pageCssEditorContent', [
'value' => empty($this->getData(['page', $this->getUrl(2), 'css'])) ? '' : $this->getData(['page', $this->getUrl(2), 'css']), 'value' => is_null($this->getData(['page', $this->getUrl(2), 'css'])) ? '' : $this->getData(['page', $this->getUrl(2), 'css']),
'class' => 'editor' 'class' => 'editor'
]); ?> ]); ?>
</div> </div>

View File

@ -7,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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,15 +7,15 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
/** /**
* 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() {
@ -23,7 +23,7 @@
}); });
}); });
$("#pageEditModuleId").on("click", function() { $("#pageEditModuleId").on("change", function() {
protectModule(); protectModule();
}); });
@ -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) { console.log(pageLayout);
// 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'])
@ -148,7 +133,7 @@
</div> </div>
<div class="col4"> <div class="col4">
<?php echo template::select('pageEditExtraPosition', $module::$extraPosition, [ <?php echo template::select('pageEditExtraPosition', $module::$extraPosition, [
'label' => 'Emplacement :', 'label' => 'Emplacement',
'selected' => $this->getData(['page', $this->getUrl(2), 'extraPosition']), 'selected' => $this->getData(['page', $this->getUrl(2), 'extraPosition']),
'help' => 'Le menu accessoire est aligné à droite de la barre de menu, c\'est un emplacement réservé aux drapeaux et au bouton de connexion.' 'help' => 'Le menu accessoire est aligné à droite de la barre de menu, c\'est un emplacement réservé aux drapeaux et au bouton de connexion.'
]); ?> ]); ?>
@ -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,8 +7,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @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>
@ -12,12 +12,9 @@
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col12">
<?php echo helper::translate('Ne pas saisir les balises') . htmlentities(' <script></script>'); ?>
</div>
<div class="col12"> <div class="col12">
<?php echo template::textarea('pageJsEditorContent', [ <?php echo template::textarea('pageJsEditorContent', [
'value' => empty($this->getData(['page', $this->getUrl(2), 'js'])) ? '' : $this->getData(['page', $this->getUrl(2), 'js']), 'value' => is_null($this->getData(['page', $this->getUrl(2), 'js'])) ? '' : $this->getData(['page', $this->getUrl(2), 'js']),
'class' => 'editor' 'class' => 'editor'
]); ?> ]); ?>
</div> </div>

View File

@ -9,8 +9,8 @@
* @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-2022, Frédéric Tempez * @copyright Copyright (C) 2018-2024, Frédéric Tempez
* @license GNU General Public License, version 3 * @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
* @link http://zwiicms.fr/ * @link http://zwiicms.fr/
*/ */
@ -20,19 +20,19 @@ class plugin extends common
public static $actions = [ public static $actions = [
'index' => self::GROUP_ADMIN, 'index' => self::GROUP_ADMIN,
'delete' => self::GROUP_ADMIN, 'delete' => self::GROUP_ADMIN,
'save' => self::GROUP_ADMIN, // Sauvegarde le module dans un fichier ZIP ou dans le gestionnaire 'save' => self::GROUP_ADMIN,
'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, // détail d'un objet //'item' => self::GROUP_ADMIN,
'upload' => self::GROUP_ADMIN, // Téléverser catalogue // détail d'un objet
'upload' => self::GROUP_ADMIN,
// Téléverser catalogue
'uploadItem' => self::GROUP_ADMIN // Téléverser par archive 'uploadItem' => self::GROUP_ADMIN // Téléverser par archive
]; ];
// URL des modules // URL des modules
const BASEURL_STORE = 'https://store.zwiicms.fr/'; const BASEURL_STORE = 'https://store.zwiicms.fr/';
const MODULE_STORE = 'modules/'; const MODULE_STORE = '?modules/';
// Gestion des modules // Gestion des modules
public static $modulesData = []; public static $modulesData = [];
@ -51,33 +51,34 @@ class plugin extends common
/* /*
* Effacement d'un module installé et non utilisé * Effacement d'un module installé et non utilisé
*/ */
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 {
@ -130,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,
@ -145,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,
@ -155,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,
@ -170,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,
@ -183,7 +184,7 @@ class plugin extends common
* Le module est-il déjà installé ? * Le module est-il déjà installé ?
* Si oui lire le numéro de version et le stocker dans $versionInstalled * Si oui lire le numéro de version et le stocker dans $versionInstalled
*/ */
if (is_file(self::MODULE_DIR . $module['name'] . '/' . $module['name'] . '.php')) { if (is_file(self::MODULE_DIR . $module['name'] . '/' . $module['name'] . '.php')) {
$c = helper::getModules(); $c = helper::getModules();
if (array_key_exists($module['name'], $c)) { if (array_key_exists($module['name'], $c)) {
$versionInstalled = $c[$module['name']]['version']; $versionInstalled = $c[$module['name']]['version'];
@ -203,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,
@ -218,29 +219,33 @@ class plugin extends common
// Copie du module // Copie du module
$success = $this->copyDir(self::TEMP_DIR . $tempFolder, self::MODULE_DIR . $module['name']); $success = $this->copyDir(self::TEMP_DIR . $tempFolder, self::MODULE_DIR . $module['name']);
// Copie récursive des dossiers externes // Copie récursive des dossiers externes
foreach ($module['dirs'] as $src => $dest) { if (is_array($module['dataDirectory'])) {
if (!is_dir(self::TEMP_DIR . $tempFolder . $src)) { foreach ($module['dataDirectory'] as $src => $dest) {
mkdir(self::TEMP_DIR . $tempFolder . $src); if (!is_dir(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,
'notification' => $success ? sprintf(helper::translate('Le module %s a été %s'), $module['name'], $t) 'notification' => $success
: helper::translate('Erreur inconnue, le module n\'est pas installé') ? sprintf(helper::translate('Le module %s a été %s'), $module['name'], $t)
: 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
@ -257,10 +262,14 @@ 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);
if ($zipFilename !== '') { if ($zipFilename !== '') {
$state = $this->install(self::FILE_DIR . 'source/' . $zipFilename, $checkValidMaj); $state = $this->install(self::FILE_DIR . 'source/' . $zipFilename, $checkValidMaj);
} }
@ -282,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
@ -307,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)) {
@ -318,11 +325,12 @@ class plugin extends common
} }
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . 'plugin/store', 'redirect' => helper::baseUrl() . 'plugin/store',
'notification' => $r['notification'], 'notification' => $r['notification'],
'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'),
@ -336,16 +344,20 @@ class plugin extends common
public function store() public function store()
{ {
$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);
if ($store) { if ($store) {
// Modules installés // Modules installés
$infoModules = helper::getModules(); $infoModules = helper::getModules();
// Clés moduleIds dans les pages // Clés moduleIds dans les pages
$inPages = helper::arrayColumn($this->getData(['page']), 'moduleId', 'SORT_DESC'); $inPages = helper::arrayColumn($this->getData(['page']), 'moduleId', 'SORT_DESC');
foreach ($inPages as $key => $value) {
$pagesInfos[$this->getData(['page', $key, 'title'])] = $value;
}
// Parcourir les données des modules // Parcourir les données des modules
foreach ($store as $key => $value) { foreach ($store as $key => $value) {
if (empty($key)) {
continue;
}
$pageInfos = array_keys($inPages, $key);
// Module non installé // Module non installé
$ico = template::ico('download'); $ico = template::ico('download');
$class = ''; $class = '';
@ -357,20 +369,20 @@ class plugin extends common
$help = 'Mettre à jour le module orphelin'; $help = 'Mettre à jour le module orphelin';
} }
// Le module est installé et utilisé // Le module est installé et utilisé
if (array_key_exists($key, $inPages) === true) { if (in_array($key, $inPages) === true) {
$class = 'buttonRed'; $class = 'buttonRed';
$ico = template::ico('update'); $ico = template::ico('update');
$help = 'Mettre à jour le module attaché, une sauvegarde des données de module est recommandée !'; $help = 'Mettre à jour le module attaché, une sauvegarde des données de module est recommandée !';
} }
self::$storeList[] = [ self::$storeList[] = [
$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(', ', array_keys($pagesInfos, $key)), implode(' - ', $pageInfos),
template::button('moduleExport' . $key, [ template::button('moduleExport' . $key, [
'class' => $class, 'class' => $class,
'href' => helper::baseUrl() . $this->getUrl(0) . '/uploadItem/' . $key . '/' . $_SESSION['csrf'], // appel de fonction vaut exécution, utiliser un paramètre 'href' => helper::baseUrl() . $this->getUrl(0) . '/uploadItem/' . $key,
'value' => $ico, 'value' => $ico,
'help' => $help 'help' => $help
]) ])
@ -392,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']),
@ -400,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;
} }
} }
@ -419,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');
@ -430,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;
@ -461,13 +487,13 @@ class plugin extends common
$infoModules[$key]['version'], $infoModules[$key]['version'],
'', '',
$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'
]) ])
: '', : '',
]; ];
} }
@ -484,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'
]) ])
@ -513,19 +539,22 @@ class plugin extends common
self::$modulesData[] = [ self::$modulesData[] = [
$infoModules[$pagesInfos[$keyi18n][$keyPage]['moduleId']]['realName'] . '&nbsp(' . $pagesInfos[$keyi18n][$keyPage]['moduleId'] . ')', $infoModules[$pagesInfos[$keyi18n][$keyPage]['moduleId']]['realName'] . '&nbsp(' . $pagesInfos[$keyi18n][$keyPage]['moduleId'] . ')',
$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'], // appel de fonction vaut exécution, utiliser un paramètre '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
'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'], // appel de fonction vaut exécution, utiliser un paramètre '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
'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'], // appel de fonction vaut exécution, utiliser un paramètre 'href' => helper::baseUrl() . $this->getUrl(0) . '/dataDelete/' . self::$siteContent . '/' . $pagesInfos[$keyi18n][$keyPage]['moduleId'] . '/' . $keyPage,
// appel de fonction vaut exécution, utiliser un paramètre
'value' => template::ico('trash'), 'value' => template::ico('trash'),
'class' => 'buttonRed dataDelete', 'class' => 'buttonRed dataDelete',
'help' => 'Détacher le module de la page', 'help' => 'Détacher le module de la page',
@ -537,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'),
@ -550,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);
} }
@ -571,272 +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])); $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
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream'); header('Content-Type: application/octet-stream');
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));
ob_clean(); readfile($tmpFolder . $fileName);
ob_end_flush();
readfile(self::TEMP_DIR . $fileName);
// Nettoyage
unlink(self::TEMP_DIR . $fileName);
$this->removeDir($tmpFolder);
exit(); exit();
} }
// Nettoyage
unlink(self::TEMP_DIR . $fileName);
$this->deleteDir($tmpFolder);
} }
} }
/*
* 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 sléectionné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)) === false ? false : true;
$success = $success && is_int(file_put_contents($tmpFolder . '/enum.json', json_encode([$moduleId => $infoModule])));
// 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);
// Gestin 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
unlink(self::TEMP_DIR . $fileName);
$this->removeDir($tmpFolder);
}
break;
case 'download':
default:
if (file_exists(self::TEMP_DIR . $fileName)) {
ob_start();
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . self::TEMP_DIR . $fileName . '"');
header('Content-Length: ' . filesize(self::TEMP_DIR . $fileName));
ob_clean();
ob_end_flush();
readfile(self::TEMP_DIR . $fileName);
unlink(self::TEMP_DIR . $fileName);
$this->removeDir($tmpFolder);
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>

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