summaryrefslogtreecommitdiff
path: root/src/service/ckeditor5/CKEditor.php
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/ckeditor5/CKEditor.php')
-rw-r--r--src/service/ckeditor5/CKEditor.php204
1 files changed, 204 insertions, 0 deletions
diff --git a/src/service/ckeditor5/CKEditor.php b/src/service/ckeditor5/CKEditor.php
new file mode 100644
index 0000000..3adf223
--- /dev/null
+++ b/src/service/ckeditor5/CKEditor.php
@@ -0,0 +1,204 @@
1<?php
2// src/integration/ckeditor5/CKEditor.php
3
4declare(strict_types=1);
5
6class CKEditor
7{
8 public const string INTEGRATION_PATH = '../src/service/ckeditor5/';
9 public const string DATA_PATH = '../data/page';
10 //public const string SERVER_PATH = '/';
11 private const string SERVER_PATH = '/ckeditor5/';
12
13 private string $server_root; // pour les "imports" en javascript
14 // pour l'importmap: j'ai modifié la version "installation avec CDN de la doc pour utiliser les fichiers locaux
15 // l'"importmap" permet d'utiliser "import" (ça ressemble pas mal au python) dans le navigateur comme n'importe quel langage de programmation normal
16
17 private string $storage_mode = 'files';
18 private string $page = 'accueil';
19 private string $from = '';
20
21 private int $php_ini_max_size;
22 private string $css_editor_tag = '';
23 private string $css_outside_editor_tag = '';
24 private string $toolbar_language = 'en';
25
26
27 public function __construct()
28 {
29 $this->php_ini_max_size = $this->returnBytes(ini_get('upload_max_filesize')); // = 2M par défaut dans le php.ini
30 $this->css_outside_editor_tag = '<link rel="stylesheet" href="css/article_hors_editeur.css" />';
31 $this->server_root = $_SERVER['SERVER_NAME'] . self::SERVER_PATH;
32 }
33
34 // getters
35 public function getPage(): string
36 {
37 return $this->page;
38 }
39 public function getFrom(): string
40 {
41 return $this->from;
42 }
43 public function getCSSOutsideEditorTag(): string
44 {
45 return $this->css_outside_editor_tag;
46 }
47 public function getCSSEditorTag(): string
48 {
49 return $this->css_editor_tag;
50 }
51 public function getStorageMode(): string
52 {
53 return $this->storage_mode;
54 }
55
56 // setters
57 public function setPage(string $page): void
58 {
59 $this->page = $page;
60 }
61 public function setFrom(string $from): void
62 {
63 $this->from = $from;
64 }
65 public function setStorageMode($mode): void
66 {
67 $this->storage_mode = $mode;
68 }
69
70 public function setLanguage(string $language): void
71 {
72 $this->toolbar_language = $language;
73 $this->makeTranslationSymLink();
74 }
75
76 public function checkAjaxRequest(): void
77 {
78 // dans un fichier à part parce que trop de lignes
79 require self::INTEGRATION_PATH . 'image_upload.php';
80 die;
81 }
82
83 public function displayNewArticleButton(): string
84 {
85 $html = '<article>
86 <a href="index.php?page=' . $this->page . '&action=open_editor"><button>Nouvel article</button></a>
87 </article>';
88 return $html;
89 }
90 public function displayArticle(string $id, string $texte): string
91 {
92 $html = '<article>' . $texte . '</article>
93 <a href="index.php?page=' . $this->page . '&action=open_editor&id=' . $id . '"><button>Modifier</button></a>
94 <a href="index.php?page=' . $this->page . '&action=delete_article&id=' . $id . '"><button>Supprimer</button></a>';
95 return $html;
96 }
97
98 public function openEditor(string $id = '', string $texte = ''): string
99 {
100 // version "minifiée"
101 $this->css_editor_tag = '<link rel="stylesheet" href="../node_modules/ckeditor5/dist/browser/ckeditor5.css" />';
102 // version normale aérée et commentée"
103 $this->css_editor_tag = '<link rel="stylesheet" href="../node_modules/ckeditor5/dist/ckeditor5.css" />';
104
105 require self::INTEGRATION_PATH . 'view.php'; // html + JS
106 return $editeurHTML;
107 }
108
109 //public function deleteSideEffects(string $id){}
110
111 public function checkSubmitPOST(): string
112 {
113 return $this->getAndCleanEditorOutput($_POST["contenu"]); // manipule $_POST['contenu'];
114
115 // enregistrement des données
116 //var_dump($html_from_editor); // debug
117 //echo "ce programme n'enregistre rien, faîtes-le dans votre application et supprimer cette ligne dans index.php"; die;
118
119 /*header('Location: ' . $this->from);
120 die;*/
121 }
122
123 /* lien symbolique des traductions
124 l'éditeur recherche un dans module/ckeditor5/dist/browser/translations
125 un fichier se trouvant dans module/ckeditor5/dist/translations
126 c'est le meilleur moyen que j'ai trouvé de gérer ça (il y a surement mieux) */
127 private function makeTranslationSymLink(): void
128 {
129 $target = '../translations';
130 $link = '../node_modules/ckeditor5/dist/browser/translations';
131
132 if(!file_exists($link))
133 {
134 if(PHP_OS_FAMILY === 'Linux')
135 {
136 symlink($target, $link);
137 }
138 elseif(PHP_OS_FAMILY === 'Windows') // note: PHP_OS = WINNT
139 {
140 // on peut créer une jointure sans droit d'admin
141 $target = '..\node_modules\ckeditor5\dist\translations';
142 exec('mklink /J ' . str_replace('/', '\\', $link) . ' ' . $target);
143 }
144 else
145 {
146 echo "erreur dans " . self::INTEGRATION_PATH . "CKEditor.php: système d'exploitation n'a pas été reconnu";
147 }
148 // autres valeurs possibles pour PHP_OS_FAMILY: 'BSD', 'Darwin', 'Solaris', 'Unknown'
149 }
150 }
151
152 // conversion des 2M du php.ini en 2000000
153 // note: les kibi, mébi et gibi sont inutiles ici
154 private function returnBytes(string $size_str): int // chaine du style '2M'
155 {
156 switch(substr($size_str, -1))
157 {
158 case 'Ki': case 'ki': return (int)$size_str * 1024;
159 case 'Mi': case 'mi': return (int)$size_str * 1048576;
160 case 'Gi': case 'gi': return (int)$size_str * 1073741824;
161 case 'K': case 'k': return (int)$size_str * 1000;
162 case 'M': case 'm': return (int)$size_str * 1000000;
163 case 'G': case 'g': return (int)$size_str * 1000000000;
164 default: return (int)$size_str;
165 }
166 }
167
168 private function getAndCleanEditorOutput(string $html): string
169 {
170 // bugs possibles sans trim() lorsqu'on insère le HTML dans l'éditeur
171 $html = trim($html);
172
173 //$this->checkContentInFile($html, 'avant');
174
175 // sécurisation du HTML (faille XSS)
176 require '../vendor/htmlawed/htmlawed/htmLawed.php';
177 $configHtmLawed = array(
178 'safe'=>1, // protection contre les élements et attributs dangereux
179
180 // balises autorisées
181 'elements'=>'h2, h3, h4, p, span, i, strong, u, s, mark, blockquote, li, ol, ul, a, figure, hr, img, figcaption, table, tbody, tr, td',
182 // note: change <s></s> en <span style="text-decoration: line-through;"></span>
183
184 // attributs interdits
185 'deny_attribute'=>'id', // 'class' et 'style' sont conservés pour le ckeditor
186 );
187 $specHtmLawed = ''; // optionnel: faire qu'un certain élément puisse n'avoir que certains attributs
188 $html = htmLawed($html, $configHtmLawed, $specHtmLawed);
189
190 //$this->checkContentInFile($html, 'après');
191
192 return $html;
193 }
194
195
196 private function checkContentInFile($html, $file_name): void
197 {
198 $nom_fichier = $file_name . ".html";
199 $fichier = fopen(self::DATA_PATH . '/' . $nom_fichier, 'w'); // w peut créer un fichier, si il existe déjà, il est effacé par le nouveau contenu
200 fputs($fichier, $html);
201 fclose($fichier);
202 chmod(self::DATA_PATH . '/' . $nom_fichier, 0666);
203 }
204}