summaryrefslogtreecommitdiff
path: root/view/template-ckeditor.php
diff options
context:
space:
mode:
authorpolo <ordipolo@gmx.fr>2021-04-20 21:46:33 +0200
committerpolo <ordipolo@gmx.fr>2021-04-20 21:46:33 +0200
commit87798e5554eb0330cd2de255e5034f0472d410a4 (patch)
treeacd9e26a7d912c7575cb6dd1c7b42cc3e9f52993 /view/template-ckeditor.php
downloadmelaine-87798e5554eb0330cd2de255e5034f0472d410a4.zip
mot de passe
Diffstat (limited to 'view/template-ckeditor.php')
-rw-r--r--view/template-ckeditor.php189
1 files changed, 189 insertions, 0 deletions
diff --git a/view/template-ckeditor.php b/view/template-ckeditor.php
new file mode 100644
index 0000000..48b673a
--- /dev/null
+++ b/view/template-ckeditor.php
@@ -0,0 +1,189 @@
1<?php
2// view/template-ckeditor.php
3
4// voici la partie HTML et javascript du ckeditor,
5// elle permette d'insérer l'éditeur dans la page avec un formulaire qui comporte 4 éléments:
6// barre d'outils, zone de saisie, formulaire caché, bouton "valider"
7
8// le formulaire est presque classique, en effet on utilise le ckeditor 5 dans sa version "Document" (ou DecoupledEditor):
9// - avantage: plus de possibilité dans la barre d'outils (se rapproche d'un traitement de texte)
10// - inconvénient: on ne peut utiliser la balise <textarea> qu'on remplace par une <div>
11
12// pour pouvoir envoyer le contenu dans le POST, on a deux possibilité:
13// - savoir coder en javascript ! et donc faire de l'AJAX, dans ce cas on n'a même plus besoin de formulaire, le contenu est envoyé au serveur au fur et à mesure! ce sera l'objet d'une future amélioration
14// - utiliser l'astuce du formulaire caché !
15
16// le javascript place les données dans le formulaire caché
17// avec la fonction envoiDonnees(), les données se retrouvent dans une <input> et sont donc envoyées avec par la POST (haha)
18
19// l'envoi d'image en revanche utilise nécessairement de l'AJAX et
20// la bibliothèque "ckfinder" (en JS + PHP) me permet de ne pas coder moi-même un "upload adapter", ce sera l'objet d'une autre amélioration, et en plus certaines fonctionnalités sont payantes
21// https://ckeditor.com/docs/ckeditor5/latest/framework/guides/deep-dive/upload-adapter.html
22// le ckfinder communique avec le serveur au moyen de requêtes AJAX,
23// le fichier est ainsi téléchargé sur le serveur avant même d'apparaître dans l'éditeur
24// attention, le ckfinder nécessite php7.3, les extensions GD et FileInfo et le support du type MIME JSON sur le serveur (retenir php7.3 et GD)
25// https://ckeditor.com/ckfinder/download/
26
27// variable $editeurHTML
28ob_start();
29?>
30
31 <div class="conteneur_article" >
32 <form action="index.php?page=<?= $page_actuelle ?>&article=<?= $numArticle ?>&action=submit" method="post" >
33 <textarea id="editor" name="contenu" ></textarea>
34
35<?php
36// falsification de requête inter-site
37// on ajoute un formulaire caché avec une valeur aléatoire cryptée utilisable une seule fois (=jeton)
38
39// "Vous pouvez rendre chaque jeton utilisable une seule fois et ainsi éviter de rejouer plusieurs fois la même requête.
40// Les jetons sont stockés dans le back-office.
41// Une rotation des jetons est effectuée quand le nombre maximum a été atteint, les plus vieux en premier.
42// Chaque jeton peut être lié à une URL spécifique.
43// Si un jeton est intercepté, il ne peut pas être utilisé dans un autre contexte.
44// Si besoin, les jetons peuvent être attachés à une adresse IP spécifique.
45// Depuis la version v2.1, les jetons peuvent être réutilisés (par exemple pour les requêtes AJAX).
46// Si vous n’utilisez pas un framework qui gère la protection CSRF pour vous, jetez un oeil à Anti-CSRF."
47
48// une bibli qui fait ça: https://github.com/paragonie/anti-csrf
49?>
50
51 <input class="boutonSubmitEditeur" type="submit" value="Valider" onclick="envoiDonnees();" />
52
53 <script>
54 let editor; // variable utilisable depuis une fonction
55
56 // code exécuté à la validation du formulaire
57 function envoiDonnees()
58 {
59 // supprimer le positionnement absolu de l'iframe
60 //~ let balisesIframe = document.getElementsByTagName("iframe");
61 //~ for(var i = 0; i < balisesIframe.length; i++)
62 //~ {
63 //~ alert(balisesIframe[i].getAttribute("style")); // affiche le CSS
64 //~ balisesIframe[i].removeAttribute("style");
65 //~ alert(balisesIframe[i].getAttribute("style")); // affiche null
66 //~ }
67 }
68
69 // ATTENTION: si l'éditeur ne fonctionne pas, empêcher qu'on puisse cliquer sur Valider!
70 // Il y a aussi des paramètres dans le fichier de config: ckeditor/webpack.config.js
71 ClassicEditor
72 .create( document.querySelector( '#editor' ),{
73 language: 'fr',
74
75 // barre d'outils à adapter au build
76 toolbar: {
77 items: [ 'undo', 'redo', 'selectAll', '|', 'heading', '|', 'alignment', 'bulletedList', 'numberedList', 'todoList', 'blockQuote', 'horizontalLine', '-', 'bold', 'italic', 'underline',
78 //'strikethrough',
79 '|',
80 //'fontFamily',
81 'fontColor', 'fontSize', 'highlight', '|', 'imageInsert', 'link',
82 //'htmlEmbed',
83 //'mediaEmbed',
84 'insertTable'
85 //'|', 'textPartLanguage'
86 ],
87 // multiligne automatique (le '-' dans la liste permet de choisir l'endroit où couper)
88 shouldNotGroupWhenFull: true
89
90 // noter que 'fontFamily' ne comporte que des polices microsoft => problèmes de droits?
91 // de plus, il faut que le navigateur connaisse toutes les polices
92 },
93
94 // barre d'outils dans une image
95 image: {
96 toolbar: [
97 'imageTextAlternative',
98 'imageStyle:full',
99 'imageStyle:side',
100 'linkImage'
101 ]
102 },
103
104 // barre d'outils dans un tableau
105 table: {
106 contentToolbar: [
107 'tableColumn',
108 'tableRow',
109 'mergeTableCells',
110 //'tableCellProperties',
111 'tableProperties'
112 ]
113 },
114
115 // plugin code HTML
116 // pour coller le code HTML "embed" proposé par certains sites
117 //
118
119 // media embarqué (audio, vidéo, carte)
120 mediaEmbed: {
121 //previewsInData: true,
122 // vaut "false" par defaut, on crée la balise non standard <oembed url="" > // https://oembed.com/
123 // qui nécessite un traitement (en JS ou côté serveur) en utilisant le lien à l'intérieur
124 // avec "true", on crée la balise <iframe> qui sert à insérer une page HTML dans une autre,
125 // notre "embarquement de média" devrit donc réussir quelque soit le site
126 // c'est plus simple, il ne reste plus qu'à ajuster le contenu avec du CSS (important)
127 // on doit supprimer le positionnement absolu qui fait que l'iframe se place par dessus le reste et adapter la taille de l'élément
128
129 // en outre, le plugin mediaEmbed (dans l'éditeur), tout comme la balise "iframe" (hors éditeur),
130 // permettent d'afficher un aperçu (preview): une image avec un bouton lecture dessus
131 // cette image est envoyée imédiatement par le serveur, et le contenu après un clic dessus
132 //
133 },
134
135 // images
136 // https://ckeditor.com/docs/ckeditor5/latest/features/image-upload/simple-upload-adapter.html
137 // le plugin "image upload" s'occupe est la partie graphique, il crée un objet "createLoader",
138 // le plugin "simple upload adapter" est la classe qui communique avec le serveur au moyen de requêtes AJAX
139 // il attend du serveur une réponse au format .json contenant l'adresse où est stockée l'image:
140 //{
141 // "url": "https://example.com/images/foo.jpg"
142 //}
143 // cette url sert à deux choses:
144 // - à télécharger l'image avant de la placer dans l'éditeur
145 // - écrire le HTML qu'on enregistrera ensuite
146 // en effet, le fichier est téléchargé sur le serveur avant de revenir dans l'éditeur comme un téléchargement classique
147
148 simpleUpload: {
149 uploadUrl: 'imageAJAX.php?page=<?= $page_actuelle ?>',
150 // noter qu'il est possible (parce que souhaitable je ne pense pas) d'envoyer une requête AJAX
151 // en indiquant une adresse "statique" du type: fichier.txt ou .xml, jpg, png, etc
152
153 // Headers supplémentaires envoyés avec la requête
154 // c'est ici qu'on installe les mécanismes de sécurités comme l'authentification et la protection au CSRF
155 headers: {
156 'X-CSRF-TOKEN': 'CSRF-Token',
157 Authorization: 'Bearer <JSON Web Token>'
158 }
159 },
160 // formats acceptés par défaut: jpeg, png, gif, bmp, webp, tiff
161 // le svg n'est pas dans la liste, pour raison de sécurité il me semble, apparemment on peut mettre du javascript à l'intérieur
162
163 // ce plugin a l'intérêt de ne pas imposer l'utilisation de l'extension GD de PHP,
164 // Reste qu'il sera quand même intéressant de l'ajouter pour le redimensionnement des images trop lourdes,
165 // quoi que le système d'onglets (limiter l'affichge à 5 ou 10 articles par page) règle aussi le problème d'une autre manière
166
167
168 // plugin autosave
169 } )
170
171 .then( newEditor => {
172 editor = newEditor;
173
174 // obtenir la liste des éléments disponibles pour la barre d'outils
175 //alert(Array.from( editor.ui.componentFactory.names() ));
176 // obtenir la liste des plugins disponibles:
177 //alert(ClassicEditor.builtinPlugins.map( plugin => plugin.pluginName ));
178
179 var initial = '<?= $initial ?>';
180 editor.setData(initial);
181 } )
182 .catch( error => {
183 console.error( error );
184 } );
185 </script>
186 </form>
187 </div>
188<?php
189$editeurHTML = ob_get_clean(); \ No newline at end of file