1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
|
<?php
// view/template-formulaire.php
// voici la partie HTML et javascript du ckeditor:
// on crée un formulaire <form> avec zones de saisie et boutons
// l'éditeur est inséré par lib/ckeditor5/build/ckeditor.js
// en remplaçant les balises <textarea>
// il est en version "Classic" customizée pour pouvoir ressembler à la version "DecoupledEditor", on peut le créer ici:
// https://ckeditor.com/ckeditor-5/online-builder/
// la version DecoupledEditor ne peut remplacer une <textarea>, il faut une <div>, ce qui interdit la méthode 1) ci-dessous
// pour envoyer les données au serveur, on a trois méthodes:
// 1) facile: le JS de la bibliothèque remplace la <textarea> par l'éditeur, noter que c'est impossible avec la version DecoupledEditor du ckeditor5, d'ou le choix la "custom"
// 2) moins facile; technique du formulaire caché (l'éditeur remplace une <div>), à la validation, du JS (appelé avec onload="") place les données dans l'<input> caché duquel part le POST
// 3) méthode AJAX (compliquée): le formulaire ni le bouton "valider" ne sont plus nécessaires et l'enregistrement des données est immédiat
// falsification de requête inter-site - CSRF
// à faire plus tard
// variable $inputsAlbum (page discographie uniquement)
// attention: on ne peut préremplir le champ input file
// solution: on affiche le nom du fichier, si l'utilisateur en télécharge un autre, on le remplace;
// il devient donc impossible de n'avoir aucun fichier
ob_start();
?>
<?= $imageFormulaire ?>
<p><i>Infos qui seront affichées sur cette page:</i></p>
<label for="titre" >Titre</label>
<input type="text" name="titre" value="<?= $vignette[0] ?>" required ><br />
<label for="annee" >Année</label>
<input type="text" name="annee" value="<?= $vignette[1] ?>" required ><br />
<label for="pochette" >Pochette du disque (jpg ou png) : <?= $vignette[2] ?></label><br/>
<input type="file" name="upload" ><br /><br /><br />
<?php
$inputsAlbum = ob_get_clean();
// variable $editeurHTML
ob_start();
?>
<div class="conteneur_article" >
<form action="index.php?page=<?= $page ?><?= $fileCodeArgument ?>&action=submit" method="post" enctype="multipart/form-data" >
<?php
if($page == 'discographie')
{
echo($inputsAlbum . "<p><i>Infos qui seront affichées dans la page spécifique à cet album:</i></p>");
}
?>
<textarea id="editor" name="contenu" ></textarea>
<input class="boutonSubmitEditeur" type="submit" value="Valider" />
<a class="boutonAnnuler" href="index.php?page=<?= $page ?>" >
<input type="button" value="Annuler" />
</a>
<script>
let editor; // variable utilisable depuis une fonction
// ATTENTION: si l'éditeur ne fonctionne pas, empêcher qu'on puisse cliquer sur Valider!
// Il y a aussi des paramètres dans le fichier de config: ckeditor/webpack.config.js
ClassicEditor
.create( document.querySelector( '#editor' ),{
language: 'fr',
// barre d'outils à adapter au "custom build"
// la liste ici: lib/ckeditor5/src/ckeditor.js
toolbar: {
items: [ 'undo', 'redo', 'selectAll', '|', 'heading', '|', 'alignment', 'bulletedList', 'numberedList',
//'todoList',
'blockQuote', 'horizontalLine', '-', 'bold', 'italic', 'underline',
//'strikethrough',
'|',
//'fontFamily',
'fontColor', 'fontSize', 'highlight', '|', 'imageInsert', 'link',
//'htmlEmbed',
//'mediaEmbed',
'insertTable'
//'|', 'textPartLanguage'
],
// multiligne automatique (le '-' dans la liste permet de choisir l'endroit où couper)
shouldNotGroupWhenFull: true
// noter que 'fontFamily' ne comporte que des polices microsoft => problèmes de droits?
// de plus, il faut que le navigateur connaisse toutes les polices
},
// barre d'outils dans une image
image: {
toolbar: [
//'imageStyle:full', //inutile?
'imageStyle:block',
//'imageStyle:inline', // complexe, on peut aussi placer l'image à la souris
'imageStyle:side',
/*'imageStyle:align-left',
'imageStyle:align-right',*/
//'imageResize', // optionnel, on a les poignées dans les coins de l'image
'linkImage',
'toggleImageCaption',
'imageTextAlternative'
]
},
// barre d'outils dans un tableau
table: {
contentToolbar: [
'tableColumn',
'tableRow',
'mergeTableCells',
//'tableCellProperties',
'tableProperties'
]
},
// plugin code HTML
// pour coller le code HTML "embed" proposé par certains sites
// media embarqué (audio, vidéo, carte)
//mediaEmbed: {
//previewsInData: true,
// vaut "false" par defaut, on crée la balise non standard <oembed url="" > // https://oembed.com/
// qui nécessite un traitement (en JS ou côté serveur) en utilisant le lien à l'intérieur
// avec "true", on crée la balise <iframe> qui sert à insérer une page HTML dans une autre,
// notre "embarquement de média" devrit donc réussir quelque soit le site
// c'est plus simple, il ne reste plus qu'à ajuster le contenu avec du CSS (important)
// 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
// en outre, le plugin mediaEmbed (dans l'éditeur), tout comme la balise "iframe" (hors éditeur),
// permettent d'afficher un aperçu (preview): une image avec un bouton lecture dessus
// cette image est envoyée imédiatement par le serveur, et le contenu après un clic dessus
//
//},
// images
// https://ckeditor.com/docs/ckeditor5/latest/features/image-upload/simple-upload-adapter.html
// le plugin "image upload" s'occupe est la partie graphique, il crée un objet "createLoader",
// le plugin "simple upload adapter" est la classe qui communique avec le serveur au moyen de requêtes AJAX
// il attend du serveur une réponse au format .json contenant l'adresse où est stockée l'image:
//{
// "url": "https://example.com/images/foo.jpg"
//}
// cette url sert à deux choses:
// - à télécharger immédiatement l'image envoyée pour la placer dans l'éditeur
// - à inclure l'adresse de l'image dans le HTML produit par l'éditeur
simpleUpload: {
uploadUrl: 'index.php?action=upload_image&page=<?= $page ?>',
// Headers supplémentaires envoyés avec la requête
// c'est ici qu'on installe les mécanismes de sécurités comme l'authentification et la protection au CSRF
headers: {
//'X-CSRF-TOKEN': 'CSRF-Token',
//Authorization: 'Bearer <JSON Web Token>'
}
},
// formats acceptés par défaut: jpeg, png, gif, bmp, webp, tiff
// 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
// ce plugin est simple (JS pur) et n'oblige pas le serveur à disposer de l'extension GD
// niveau perfs, on garde le choix d'utiler GD ou imagemagick ou un système d'onglets
// plugin autosave
} )
.then( newEditor => {
editor = newEditor;
// obtenir la liste des éléments disponibles pour la barre d'outils
//alert(Array.from( editor.ui.componentFactory.names() ));
// obtenir la liste des plugins disponibles:
//alert(ClassicEditor.builtinPlugins.map( plugin => plugin.pluginName ));
var initial = '<?= $texte ?>';
editor.setData(initial);
} )
.catch( error => {
console.error( error );
} );
</script>
</form>
</div>
<?php
$editeurHTML = ob_get_clean();
|