PluginProbe
AI Builder – Generate pages, blocks, images & translate with AI / 2.7.6
AI Builder – Generate pages, blocks, images & translate with AI v2.7.6
2.7.8 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.3.10 2.3.11 2.3.12 All 120 releases
ai-builder / test-blocks.php

test-blocks.php in AI Builder – Generate pages, blocks, images & translate with AI 2.7.6, at test-blocks.php

512 lines 19.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Script de test pour valider le format HTML sérialisé des blocs WordPress
4 *
5 * Usage:
6 * 1. Placez ce fichier à la racine de votre plugin
7 * 2. Collez votre contenu HTML dans la variable $test_content ci-dessous
8 * 3. Accédez au fichier via votre navigateur ou exécutez-le en ligne de commande
9 *
10 * Ou utilisez-le comme page admin WordPress:
11 * ?page=test-blocks&content=[VOTRE_CONTENU_ENCODED]
12 */
13
14 // Charger WordPress si nécessaire (si exécuté en standalone)
15 if (!function_exists('parse_blocks')) {
16 // Ajustez ce chemin selon votre installation
17 require_once(__DIR__ . '/../../../wp-load.php');
18 }
19
20 // Fonction pour tester un contenu de bloc
21 function test_block_content($html_content) {
22 $results = [
23 'valid' => true,
24 'errors' => [],
25 'warnings' => [],
26 'blocks' => [],
27 'total_blocks' => 0
28 ];
29
30 if (empty($html_content)) {
31 $results['valid'] = false;
32 $results['errors'][] = 'Le contenu est vide';
33 return $results;
34 }
35
36 // Vérifier que ça commence par un commentaire de bloc WordPress
37 $trimmed = trim($html_content);
38 if (strpos($trimmed, '<!-- wp:') !== 0) {
39 $results['warnings'][] = 'Le contenu ne commence pas par un commentaire de bloc WordPress';
40 }
41
42 // Parser les blocs
43 $parsed_blocks = parse_blocks($html_content);
44
45 if (empty($parsed_blocks)) {
46 $results['valid'] = false;
47 $results['errors'][] = 'Aucun bloc n\'a pu être parsé. Le format est peut-être invalide.';
48 return $results;
49 }
50
51 $results['total_blocks'] = count($parsed_blocks);
52
53 // Analyser chaque bloc
54 foreach ($parsed_blocks as $index => $block) {
55 $block_info = [
56 'index' => $index,
57 'blockName' => $block['blockName'] ?? 'INCONNU',
58 'valid' => true,
59 'errors' => [],
60 'warnings' => [],
61 'attrs' => $block['attrs'] ?? [],
62 'innerBlocks_count' => isset($block['innerBlocks']) ? count($block['innerBlocks']) : 0,
63 'innerContent_count' => isset($block['innerContent']) ? count($block['innerContent']) : 0
64 ];
65
66 // Vérifier que le bloc a un nom
67 if (empty($block['blockName'])) {
68 $block_info['valid'] = false;
69 $block_info['errors'][] = 'Le bloc n\'a pas de nom (blockName)';
70 $results['valid'] = false;
71 }
72
73 // Tester la sérialisation/désérialisation
74 try {
75 $serialized = serialize_block($block);
76 if (empty($serialized)) {
77 $block_info['valid'] = false;
78 $block_info['errors'][] = 'La sérialisation du bloc échoue (retour vide)';
79 $results['valid'] = false;
80 } else {
81 // Vérifier qu'on peut le reparser
82 $reparsed = parse_blocks($serialized);
83 if (empty($reparsed)) {
84 $block_info['valid'] = false;
85 $block_info['errors'][] = 'Le bloc sérialisé ne peut pas être re-parsé';
86 $results['valid'] = false;
87 } elseif ($reparsed[0]['blockName'] !== $block['blockName']) {
88 $block_info['warnings'][] = 'Le blocName change après sérialisation/parsing';
89 }
90 }
91 } catch (Exception $e) {
92 $block_info['valid'] = false;
93 $block_info['errors'][] = 'Erreur lors de la sérialisation: ' . $e->getMessage();
94 $results['valid'] = false;
95 }
96
97 // Vérifier les attributs JSON (s'ils existent dans le commentaire)
98 if (!empty($block['attrs'])) {
99 $attrs_json = json_encode($block['attrs']);
100 if ($attrs_json === false) {
101 $block_info['warnings'][] = 'Les attributs ne peuvent pas être encodés en JSON valide';
102 }
103 }
104
105 // Vérifier la structure innerContent vs innerBlocks pour les blocs conteneurs
106 if (!empty($block['innerBlocks'])) {
107 if (empty($block['innerContent']) || !is_array($block['innerContent'])) {
108 $block_info['warnings'][] = 'Le bloc a des innerBlocks mais pas de innerContent défini';
109 } else {
110 // innerContent devrait avoir des null là où sont les innerBlocks
111 $null_count = count(array_filter($block['innerContent'], function($item) {
112 return $item === null;
113 }));
114 if ($null_count !== count($block['innerBlocks'])) {
115 $block_info['warnings'][] = "Le nombre de null dans innerContent ({$null_count}) ne correspond pas au nombre d'innerBlocks (" . count($block['innerBlocks']) . ")";
116 }
117 }
118 }
119
120 $results['blocks'][] = $block_info;
121 if (!$block_info['valid']) {
122 $results['errors'][] = "Bloc #{$index} ({$block_info['blockName']}): " . implode(', ', $block_info['errors']);
123 }
124 if (!empty($block_info['warnings'])) {
125 $results['warnings'][] = "Bloc #{$index} ({$block_info['blockName']}): " . implode(', ', $block_info['warnings']);
126 }
127 }
128
129 return $results;
130 }
131
132 // Fonction pour extraire et valider les JSON dans les commentaires
133 function validate_block_comments($html_content) {
134 $errors = [];
135 $fixes = [];
136 preg_match_all('/<!-- wp:([^\s]+)\s+(\{.*?\})\s*-->/', $html_content, $matches, PREG_SET_ORDER);
137
138 foreach ($matches as $index => $match) {
139 $block_name = $match[1];
140 $json_str = $match[2];
141
142 // Décoder le JSON
143 $decoded = json_decode($json_str, true);
144 if ($decoded === null && json_last_error() !== JSON_ERROR_NONE) {
145 // Essayer de corriger le JSON échappé
146 $fixed_json = stripslashes($json_str);
147 $decoded_fixed = json_decode($fixed_json, true);
148
149 $error_info = [
150 'block' => $block_name,
151 'position' => strpos($html_content, $match[0]),
152 'error' => 'JSON invalide: ' . json_last_error_msg(),
153 'json' => $json_str,
154 'is_escaped' => false,
155 'can_be_fixed' => false,
156 'fixed_json' => null
157 ];
158
159 // Vérifier si le JSON contient des guillemets échappés
160 if (strpos($json_str, '\\"') !== false || strpos($json_str, '\\\'') !== false) {
161 $error_info['is_escaped'] = true;
162
163 if ($decoded_fixed !== null && json_last_error() === JSON_ERROR_NONE) {
164 $error_info['can_be_fixed'] = true;
165 $error_info['fixed_json'] = $fixed_json;
166 $fixes[] = [
167 'block' => $block_name,
168 'original' => $json_str,
169 'fixed' => $fixed_json
170 ];
171 }
172 }
173
174 $errors[] = $error_info;
175 }
176 }
177
178 return ['errors' => $errors, 'fixes' => $fixes];
179 }
180
181 // Fonction pour corriger automatiquement le HTML échappé
182 function fix_escaped_html($html_content) {
183 // Retirer les backslashes des guillemets dans les JSON des commentaires
184 $fixed = preg_replace_callback(
185 '/<!-- wp:([^\s]+)\s+(\{.*?\})\s*-->/',
186 function($matches) {
187 $block_name = $matches[1];
188 $json_str = $matches[2];
189 $fixed_json = stripslashes($json_str);
190 return "<!-- wp:{$block_name} {$fixed_json} -->";
191 },
192 $html_content
193 );
194
195 return $fixed;
196 }
197
198 // ============================================
199 // ZONE DE TEST - Collez votre contenu ici
200 // ============================================
201
202 $test_content = '';
203 // Collez votre HTML sérialisé ici, ou laissez vide pour utiliser le paramètre GET
204
205 // Si exécuté dans WordPress, vérifier les paramètres GET
206 if (isset($_GET['content']) && !empty($_GET['content'])) {
207 $test_content = urldecode($_GET['content']);
208 } elseif (!empty($test_content)) {
209 // Utiliser le contenu défini ci-dessus
210 } else {
211 // Exemple de contenu pour test
212 $test_content = '<!-- wp:paragraph -->
213 <p>Test paragraph</p>
214 <!-- /wp:paragraph -->';
215 }
216
217 ?>
218 <!DOCTYPE html>
219 <html lang="fr">
220 <head>
221 <meta charset="UTF-8">
222 <meta name="viewport" content="width=device-width, initial-scale=1.0">
223 <title>Testeur de Blocs WordPress</title>
224 <style>
225 body {
226 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
227 max-width: 1200px;
228 margin: 0 auto;
229 padding: 20px;
230 background: #f5f5f5;
231 }
232 .container {
233 background: white;
234 padding: 30px;
235 border-radius: 8px;
236 box-shadow: 0 2px 4px rgba(0,0,0,0.1);
237 margin-bottom: 20px;
238 }
239 h1 {
240 color: #23282d;
241 border-bottom: 2px solid #0073aa;
242 padding-bottom: 10px;
243 }
244 h2 {
245 color: #0073aa;
246 margin-top: 30px;
247 }
248 .status {
249 padding: 15px;
250 border-radius: 4px;
251 margin: 15px 0;
252 font-weight: bold;
253 }
254 .status.valid {
255 background: #d4edda;
256 color: #155724;
257 border: 1px solid #c3e6cb;
258 }
259 .status.invalid {
260 background: #f8d7da;
261 color: #721c24;
262 border: 1px solid #f5c6cb;
263 }
264 .errors, .warnings {
265 margin: 15px 0;
266 padding: 15px;
267 border-radius: 4px;
268 }
269 .errors {
270 background: #fff3cd;
271 border: 1px solid #ffeaa7;
272 }
273 .warnings {
274 background: #e7f3ff;
275 border: 1px solid #b3d9ff;
276 }
277 .error-item, .warning-item {
278 margin: 8px 0;
279 padding: 8px;
280 background: white;
281 border-left: 3px solid;
282 }
283 .error-item {
284 border-color: #ff6b6b;
285 }
286 .warning-item {
287 border-color: #4dabf7;
288 }
289 .block-info {
290 margin: 15px 0;
291 padding: 15px;
292 background: #f8f9fa;
293 border-radius: 4px;
294 border-left: 4px solid #0073aa;
295 }
296 .block-info.invalid {
297 border-left-color: #dc3545;
298 }
299 .block-name {
300 font-weight: bold;
301 color: #0073aa;
302 margin-bottom: 10px;
303 }
304 code {
305 background: #f4f4f4;
306 padding: 2px 6px;
307 border-radius: 3px;
308 font-family: 'Courier New', monospace;
309 font-size: 0.9em;
310 }
311 textarea {
312 width: 100%;
313 min-height: 300px;
314 padding: 10px;
315 font-family: 'Courier New', monospace;
316 font-size: 12px;
317 border: 2px solid #ddd;
318 border-radius: 4px;
319 }
320 button {
321 background: #0073aa;
322 color: white;
323 border: none;
324 padding: 10px 20px;
325 border-radius: 4px;
326 cursor: pointer;
327 font-size: 16px;
328 margin-top: 10px;
329 }
330 button:hover {
331 background: #005177;
332 }
333 .json-errors {
334 margin-top: 20px;
335 }
336 .json-error-item {
337 background: #fff3cd;
338 padding: 10px;
339 margin: 10px 0;
340 border-radius: 4px;
341 border-left: 3px solid #ff9800;
342 }
343 </style>
344 </head>
345 <body>
346 <div class="container">
347 <h1>🔍 Testeur de Blocs WordPress</h1>
348
349 <form method="GET">
350 <h2>Collez votre contenu HTML sérialisé ici:</h2>
351 <textarea name="content" placeholder="<!-- wp:paragraph -->..."><?php echo htmlspecialchars($test_content); ?></textarea>
352 <button type="submit">Tester le contenu</button>
353 </form>
354 </div>
355
356 <?php if (!empty($test_content)): ?>
357 <?php
358 // Détecter et corriger si nécessaire
359 $original_content = $test_content;
360 $json_validation = validate_block_comments($test_content);
361 $json_errors = $json_validation['errors'];
362 $json_fixes = $json_validation['fixes'];
363
364 // Si des corrections sont possibles, les appliquer
365 $has_escaped_json = false;
366 foreach ($json_errors as $error) {
367 if ($error['is_escaped'] && $error['can_be_fixed']) {
368 $has_escaped_json = true;
369 break;
370 }
371 }
372
373 if ($has_escaped_json && !empty($json_fixes)) {
374 $test_content = fix_escaped_html($test_content);
375 }
376
377 $results = test_block_content($test_content);
378 ?>
379
380 <div class="container">
381 <h2>📊 Résultats du Test</h2>
382
383 <?php if ($has_escaped_json && !empty($json_fixes)): ?>
384 <div class="status valid" style="background: #fff3cd; color: #856404; border-color: #ffeaa7;">
385 ⚠️ Correction automatique appliquée : Les guillemets échappés (`\"`) ont été corrigés dans les commentaires JSON
386 <br>
387 <small><?php echo count($json_fixes); ?> bloc(s) corrigé(s)</small>
388 </div>
389 <?php endif; ?>
390
391 <div class="status <?php echo $results['valid'] ? 'valid' : 'invalid'; ?>">
392 <?php if ($results['valid']): ?>
393
394 Le contenu est valide <?php echo $has_escaped_json ? '(après correction)' : ''; ?>!
395 <?php else: ?>
396 Le contenu contient des erreurs
397 <?php endif; ?>
398 <br>
399 <small>Nombre total de blocs: <?php echo $results['total_blocks']; ?></small>
400 </div>
401
402 <?php if (!empty($results['errors'])): ?>
403 <div class="errors">
404 <h3> Erreurs détectées:</h3>
405 <?php foreach ($results['errors'] as $error): ?>
406 <div class="error-item"><?php echo htmlspecialchars($error); ?></div>
407 <?php endforeach; ?>
408 </div>
409 <?php endif; ?>
410
411 <?php if (!empty($results['warnings'])): ?>
412 <div class="warnings">
413 <h3>⚠️ Avertissements:</h3>
414 <?php foreach ($results['warnings'] as $warning): ?>
415 <div class="warning-item"><?php echo htmlspecialchars($warning); ?></div>
416 <?php endforeach; ?>
417 </div>
418 <?php endif; ?>
419
420 <?php if (!empty($json_errors)): ?>
421 <div class="json-errors">
422 <h3>📝 Erreurs JSON dans les commentaires:</h3>
423 <?php foreach ($json_errors as $json_error): ?>
424 <div class="json-error-item">
425 <strong>Bloc:</strong> <code><?php echo htmlspecialchars($json_error['block']); ?></code><br>
426 <strong>Erreur:</strong> <?php echo htmlspecialchars($json_error['error']); ?><br>
427 <?php if ($json_error['is_escaped']): ?>
428 <strong style="color: #856404;">⚠️ JSON échappé détecté (guillemets avec backslashes)</strong><br>
429 <?php if ($json_error['can_be_fixed']): ?>
430 <strong style="color: #28a745;">�
431 Correction automatique possible</strong><br>
432 <strong>JSON original (échappé):</strong><br>
433 <code style="display:block;margin-top:5px;max-height:100px;overflow:auto;background:#ffeaa7;"><?php echo htmlspecialchars($json_error['json']); ?></code>
434 <strong>JSON corrigé:</strong><br>
435 <code style="display:block;margin-top:5px;max-height:100px;overflow:auto;background:#d4edda;"><?php echo htmlspecialchars($json_error['fixed_json']); ?></code>
436 <?php else: ?>
437 <strong>JSON problématique:</strong><br>
438 <code style="display:block;margin-top:5px;max-height:100px;overflow:auto;"><?php echo htmlspecialchars($json_error['json']); ?></code>
439 <?php endif; ?>
440 <?php else: ?>
441 <strong>JSON problématique:</strong><br>
442 <code style="display:block;margin-top:5px;max-height:100px;overflow:auto;"><?php echo htmlspecialchars($json_error['json']); ?></code>
443 <?php endif; ?>
444 </div>
445 <?php endforeach; ?>
446 </div>
447 <?php endif; ?>
448
449 <?php if ($has_escaped_json && !empty($json_fixes)): ?>
450 <div class="container" style="margin-top: 20px; background: #d4edda; border: 1px solid #c3e6cb;">
451 <h3>�
452 Contenu corrigé (à utiliser):</h3>
453 <textarea readonly style="min-height: 200px; font-size: 11px;"><?php echo htmlspecialchars($test_content); ?></textarea>
454 <p><small>📋 Copiez ce contenu corrigé et utilisez-le à la place de l'original</small></p>
455 </div>
456 <?php endif; ?>
457
458 <h2>📦 Détails des Blocs</h2>
459 <?php foreach ($results['blocks'] as $block): ?>
460 <div class="block-info <?php echo $block['valid'] ? '' : 'invalid'; ?>">
461 <div class="block-name">
462 Bloc #<?php echo $block['index']; ?>:
463 <code><?php echo htmlspecialchars($block['blockName']); ?></code>
464 <?php if (!$block['valid']): ?>
465 <span style="color: #dc3545;">❌</span>
466 <?php else: ?>
467 <span style="color: #28a745;">�
468 </span>
469 <?php endif; ?>
470 </div>
471
472 <div style="margin-top: 10px; font-size: 0.9em; color: #666;">
473 <strong>Inner Blocks:</strong> <?php echo $block['innerBlocks_count']; ?><br>
474 <strong>Inner Content items:</strong> <?php echo $block['innerContent_count']; ?>
475 </div>
476
477 <?php if (!empty($block['errors'])): ?>
478 <div style="margin-top: 10px;">
479 <strong style="color: #dc3545;">Erreurs:</strong>
480 <ul>
481 <?php foreach ($block['errors'] as $error): ?>
482 <li><?php echo htmlspecialchars($error); ?></li>
483 <?php endforeach; ?>
484 </ul>
485 </div>
486 <?php endif; ?>
487
488 <?php if (!empty($block['warnings'])): ?>
489 <div style="margin-top: 10px;">
490 <strong style="color: #ff9800;">Avertissements:</strong>
491 <ul>
492 <?php foreach ($block['warnings'] as $warning): ?>
493 <li><?php echo htmlspecialchars($warning); ?></li>
494 <?php endforeach; ?>
495 </ul>
496 </div>
497 <?php endif; ?>
498
499 <?php if (!empty($block['attrs'])): ?>
500 <details style="margin-top: 10px;">
501 <summary style="cursor: pointer; color: #0073aa;">Attributs (cliquez pour voir)</summary>
502 <pre style="background: #f4f4f4; padding: 10px; margin-top: 5px; border-radius: 4px; overflow: auto; max-height: 200px;"><?php echo htmlspecialchars(json_encode($block['attrs'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); ?></pre>
503 </details>
504 <?php endif; ?>
505 </div>
506 <?php endforeach; ?>
507 </div>
508 <?php endif; ?>
509
510 </body>
511 </html>
512