diff options
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 | ||
