Callback et manipulation du buffer de sortie
Bonjour,
Je suis en train de traiter le problème suivant :
Un document est généré dans le buffer de sortie et je veux le modifier, en l'occurence transformer les titres <Hn>... </Hn> pour générer un sommaire et associer des ancres.
Aucun problème particulier, preg_match_all avec captures puis remplacements avec précautions (voir remarques en notes).
Mais le problème se gâte quand le document est la publication d'un extrait d'un document plus grand (chapitre d'un livre par exemple). Dans ce cas il va falloir rapprocher du document de sortie, la source (HTML en format interne et partiellement encodé de caractères spéciaux) :
J'ai pour l'instant échoué sur le problème suivant : comment fabriquer à partir des tags Hn source non encodés la chaîne qui pourra être recherchée dans le buffer de sortie ?
On pourrait penser que une routine (simplifiée) comme :
Code:
1 2 3 4 5
| function ob_sencode ($input) {
ob_start();
echo $input;
return ob_get_clean();
} |
pourrait faire l'affaire en ignorant toutes les définitions d'encodage du contexte.
Mais cela ne marche pas, et je ne vois vraiment pas pourquoi :
Le titre brut :
Code:
<h2>L'impact des nouveaux moyens de communication et de traitement de l'information</h2>
revient tel quel de la fonction ob_sencode()
alors que dans le buffer il est encodé :
Code:
<h2>Limpact des nouveaux moyens de communication et de traitement de linformation</h2>
Note : C'est évidemment l'exemple élémentaire, dans la pratique c'est tout de suite un peu plus compliqué, mais pouvant être traité, avec les apostrophes, différents guillemets etc. et les fonction spéciales de remplacement du type "texturize" de WordPress
Je n'ai rien trouvé sur la question.
Il y a plusieurs autres solutions plus ou moins complexes pour faire le rapprochement (ré-associer de manière fiable un titre avec son image dans le buffer pour effectuer le remplacement adapté) mais pouvoir générer le code identique parait la plus simple, mais je sèche.
Cordialement
Trebly
Si vous avez une idée, merci d'avance
Notes : Je compléterai au fur et à mesure de la discussion ou à la fin.
Contexte et éléments de solution au problème de callback "manuel" du buffer, pas si évident que cela
Bonsoir,
Désolé de cette réaction tardive à ta réponse à ma question, j'avais loupé l'activation de notification... et je ne suis pas revenu jusqu'à aujourd'hui faire un contrôle systématique des sujets lancés.
En fait il y avait deux problèmes importants et je les ai confondus en répondant, tardivement
A- Traiter de texte brut, puis le buffer de sortie comme avec une fonction de type callback mais par soft complexe
l'explication du traitement est donnée en (B), en résumé, pour un article on a le HTML intégral complété de commandes de traitement les [shortcodes], à ce stade on va analyser le sommaire et pré-traiter des shortcodes spécifiques. Le texte en entrée est intégral alors que des commandes comme "<!--nextpage-->" vont permettre un découpage en sections affichées à la fin (buffer) comme des documents séparés. Par conséquent si l'on veut avoir un sommaire général il faut faire un prétraitement.
On va ensuite rendre (confier) ce document prétraité au traitement principal de mise en page WordPress.
Après traitement on va récupérer le buffer de sortie qui ne comprendra, si le texte est découpé, qu'une seule partie du document complet (j'ai pas exemple un ouvrage de 80 pages découpé en 12 sections).
Par ailleurs comme il s'agit d'un buffer il est encodé triplement (UTF8+full_HTML+altération et compléments de styles et ajout de tags internes générés par Wordpress), la question est donc de retrouver les bons entêtes pour les compléter : en particulier écrire les liens permettent d'y accéder depuis le sommaire.
La seule solution qui me semble viable, et que je fais fonctionner sans problème depuis cet été, comporte un double traitement sachant que :
- Je n'ai pas pu trouver de moyen de repasser du texte encodé à l'original source.
- Je n'ai pas pu trouver de moyen de repasser du texte source à l'output (nombreuses raisons : impossible malgré les outils d'encodage décodage et les traitement wordpress).
Je vais, en fait, créer un identifiant unique en string ascii des headers (Hn) qui pourra être obtenu à partir des deux formes. Le traitement n'est que deux "simples" (pas si simples) preg_replace après avoir isolé les tags (<Hn>...</Hn>) et filtré.
Dans les deux cas, après avoir isolé le contenu textuel, on remplace le chaines de caractères spéciaux (qui auront été modifiés par un identifiant unique de même longueur en octets et l'on complète d'infos permettant d'interdire tout doublon (les doublons s'ils existent - i.e. "introduction" sont nécessairement dans le même ordre...).
Le rapprochement des listes marche à 100%
Ensuite il ne s'agit plus que de remplacer les blocs pour reconstituer le nouvel élément valide DOM Hn souhaité (ajout de <span> permettant l'identification, les liens, associer les data utiles etc...) remplaçant après un parse partiel les éléments Hn du DOM de sortie.
J'ai aussi appliqué ce traitement à des documents construits (listes divers avec objets multiples) pour retrouver et modifier des identifiants et libellés d'éléments et introduire notamment des liens et des marques.
B- Difficultés de récupération du buffer : anomalies -> échec de recherches = buffer tronqué
Le problème est résolu, mais je laisse ouvert parce je pense intéressant le résultat de l'analyse que j'ai ménée qui m'a d'ailleurs conduit à faire une note sur php.net à propos de ob_start (l'analyse a été faite en utilisant les fonction d'analyse de la pile de bufferisation et les contenus).
Pourquoi lire le buffer :
- Dans le cas d'articles parce que Wordpress modifie les "source" html des articles avec les "shortcodes", il est utile d'analyser (recherche d'éléments utiles) et d'effectuer les remplacements dans le buffer d'éléments repérés en première analyse (difficile à cause de l'encodage full html du buffer).
- Il existe le cas de documents générés (listes d'articles ou autres objets mixtes - articles par auteur) et dans ce cas seul l'analyse du buffer en callback permet les traitements utiles (extension des fonctionalités prévues à l'origine qui j'ai implémentée et qui permet de construire le sommaire (avec lien) de tout document y compris ceux générés par une méthode quelconque : plugins)
Le traitement principal que j'effectue : encadrement de "span" permettant l'identification d'éléments et la création de liens (avec beaucoup de précautions à cause des mécanismes d'héritage et leur prise en compte dans les css).
D'où venait le problème de traitement rencontré :
Le buffer était tronqué dans certains cas (articles suffisamment longs... en fait supérieurs à 4096 c.).
Lorsque wordpress (le thème utilisé puis mes traitements) utilise ob_start(); pour ouvrir un niveau de buffer à traiter, l'ouverture du nouveau niveau de buffer se fait avec la bufferisation de sortie par défaut (ou le set effectué... quelque part de "chunk_size" qui en l'occurrence était réglé à 4096c. cf. remarque de la doc php :
Citation:
Avant la version PHP 5.4.0, la valeur 1 était une valeur spéciale qui définissait la taille du morceau à 4096 octets.
ce qui était le cas).
Par conséquent si l'on écrit plus que la taille de buffer, on ne retrouvera avec ob_get*() que au plus la taille max de buffer définie par chunk_size.
Pour effectuer le traitement que je voulais faire (un callback en utilisant ob_get*() et la réécriture complète par un traitement complexe qui implique tout un document) il faut donc :
- Forcer l'écriture de la partie "article" (je crée une div spécifique) sans limite de vidage en exécutant un ob_start(,0); (0 = buffer illimité) qui n'est pas du tout équivalent de ob_start(); pour cette question.
- Après la fin d'écriture récupérer ce buffer (en totalité) et le remplacer.
Ca marche très bien et en encadrant avec une div je peux tester la validité du buffer récupéré (et d'ailleurs le découper proprement).
Donc le traitement n'est possible qu'en modifiant les sources du (ou des) thème(s) utilisé(s) (ce qui nécessite pour le plugin que je développe un processus d'installation assez lourd impliquant des patch de thèmes).
Merci.
Cordialement
Trebly