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