diff --git a/ecrire/inc/filtres.php b/ecrire/inc/filtres.php index 1c7136cfc3804c1a73826c1aa748c680bb641939..c054fb5f3958452c1edf6610583c5cd015b05e8e 100644 --- a/ecrire/inc/filtres.php +++ b/ecrire/inc/filtres.php @@ -2427,8 +2427,8 @@ function tags2dcsubject($tags) { /** * Retourne la premiere balise html du type demandé * - * Retourne le contenu d'une balise jusqu'à la première fermeture rencontrée - * du même type. + * Retourne dans un tableau le contenu de chaque balise jusqu'à sa + * fermeture correspondante. * Si on a passe un tableau de textes, retourne un tableau de resultats. * * @example `[(#DESCRIPTIF|extraire_balise{img})]` @@ -2445,12 +2445,12 @@ function tags2dcsubject($tags) { * texte(s) dont on souhaite extraire une balise html * @param string $tag * Nom de la balise html à extraire - * @return void|string|array - * - Code html de la balise, sinon rien + * @return string|array + * - Code html de la première occurence de la balise trouvée, sinon chaine vide * - Tableau de résultats, si tableau en entrée. **/ -function extraire_balise($texte, $tag = 'a') { - $balises = extraire_balises($texte, $tag, ['nb_max' => 1]); +function extraire_balise($texte, $tag = 'a', $profondeur = 1) { + $balises = extraire_balises($texte, $tag, ['nb_max' => 1, 'profondeur' => $profondeur]); if (is_array($texte)) { return array_map(function(array $a) {return (empty($a) ? '' : reset($a));}, $balises); } @@ -2461,8 +2461,8 @@ function extraire_balise($texte, $tag = 'a') { /** * Extrait toutes les balises html du type demandé * - * Retourne dans un tableau le contenu de chaque balise jusqu'à la première - * fermeture rencontrée du même type. + * Retourne dans un tableau le contenu de chaque balise jusqu'à sa + * fermeture correspondante. * Si on a passe un tableau de textes, retourne un tableau de resultats. * * @example `[(#TEXTE|extraire_balises{img}|implode{" - "})]` @@ -2470,16 +2470,14 @@ function extraire_balise($texte, $tag = 'a') { * @filtre * @link https://www.spip.net/5618 * @see extraire_balise() - * @note - * Attention : les résultats peuvent être incohérents sur des balises imbricables, - * tel que demander à extraire `div` dans un texte. * * @param string|array $texte * texte(s) dont on souhaite extraire une balise html * @param string $tag * Nom de la balise html à extraire * @param array $options - * int @nb_max : nombre d'occurence maxi à extraire + * int nb_max : nombre d'occurence maxi à extraire + * int profondeur : niveau de profondeur d'extraction en cas d'intrication de balises identiques * @return array * - Liste des codes html des occurrences de la balise, sinon tableau vide * - Tableau de résultats, si tableau en entrée. diff --git a/ecrire/src/Texte/Collecteur/HtmlTag.php b/ecrire/src/Texte/Collecteur/HtmlTag.php index 8d8206a103c66215bdf399f8cf7e50b76e8d62b9..873451ad9370c31713f5fd3e6e4ff4dc5e11e6d9 100644 --- a/ecrire/src/Texte/Collecteur/HtmlTag.php +++ b/ecrire/src/Texte/Collecteur/HtmlTag.php @@ -80,6 +80,7 @@ class HtmlTag extends AbstractCollecteur { array_shift($closing); } + $profondeur = ($options['profondeur'] ?? 1); $tags = []; while (!empty($opening)) { $first_opening = array_shift($opening); @@ -131,12 +132,33 @@ class HtmlTag extends AbstractCollecteur { $tags[] = $tag; } } - if ( - (!empty($options['detecter_presence']) and count($tags)) - or (!empty($options['nb_max']) and count($tags) >= $options['nb_max']) - ) { + if ((!empty($options['detecter_presence']) and count($tags))) { return $tags; } + if (($profondeur == 1 and !empty($options['nb_max']) and count($tags) >= $options['nb_max'])) { + break; + } + } + + while (--$profondeur > 0) { + $outerTags = $tags; + $tags = []; + $options['profondeur'] = 1; + foreach ($outerTags as $outerTag) { + if (!empty($outerTag['innerHtml'])) { + $offsetPos = $outerTag['pos'] + strlen($outerTag['opening']); + $innerTags = $this->collecter($outerTag['innerHtml'], $options); + if (!empty($innerTags)) { + foreach ($innerTags as $tag) { + $tag['pos'] += $offsetPos; + $tags[] = $tag; + } + if (($profondeur == 1 and !empty($options['nb_max']) and count($tags) >= $options['nb_max'])) { + return $tags; + } + } + } + } }