[wp-meta] [Making WordPress.org] #5746: wporg-glossary plugin doesn't correctly handle being run twice over the same content
Making WordPress.org
noreply at wordpress.org
Tue May 25 00:10:22 UTC 2021
#5746: wporg-glossary plugin doesn't correctly handle being run twice over the
same content
--------------------------------------+--------------------
Reporter: pbiron | Owner: (none)
Type: defect | Status: new
Priority: normal | Milestone:
Component: Make (Get Involved) / P2 | Keywords:
--------------------------------------+--------------------
In `Glossary_Handler::glossary_links()`, there is logic that tries to skip
adding links in content...but that logic is incorrect.
In particular,
{{{#!php
// Skip the Glossary item container span, for when the_content is run over
the_content.
if ( $matches && 'span' == $matches[0] && false !== strpos( $element,
"class='glossary-item-container'" ) ) {
if ( ! $is_end_tag ) {
array_unshift( $inside_block, $matches[0] );
} elseif ( $inside_block && $matches[0] === $inside_block[0] ) {
array_shift( $inside_block );
}
continue;
}
}}}
Unfortunately, the `false !== strpos( $element, "class='glossary-item-
container'" )` clause in the conditional will only ever be true on the
opening tag. Because of that, the `span` that gets pushed onto
`$inside_block` will never get popped.
The result is that once it sees an opening span with that class,
`$inside_block` will never be empty again (unless there is some seriously
unbalanced markup involving any of the `$ignore_elements`) and from that
point on no other occurrences of glossary terms will get the hovercard
markup added to them.
I discovered this while investigating possibly using this plugin on a
client site. It's unclear how likely this issue is to surface on .org
content.
Here's a simple example to illustrate the bug (abstracted from that client
site). Suppose the glossary contains `term1` and `term2`, and a post with
the following content:
{{{
[some_shortcode]this is term1[/some_shortcode]
<p>a paragraph with term2</p>
}}}
Further suppose the plugin that registers [some_shortcode], does something
like:
{{{#!php
add_shortcode( 'some_shortcode', function( $atts, $content ) {
return apply_filters( 'the_content', $content );
} );
}}}
So, what `Glossary_Handler::glossary_links()` sees the 2nd time is:
{{{
<span tabindex="0" class="glossary-item-container">some term<span class
="glossary-item-hidden-content"><span class="glossary-item-
header">Administrator</span> <span class="glossary-item-description">some
definition</span></span></span></span>
<p>a paragraph with term2</p>
}}}
The result is that `term2` does **not** end up with a hovercard.
I'm not sure what the easiest/best way to fix this is. Conceptually, what
needs to happen is once a `<span class='glossary-item-container'>` is
found, it needs to start pushing/popping tags onto **another** stack so
that it can detect when it's seen the associated closing `</span>`, in
which case it should pop the span off of `$inside_block`. But that can
get messy real quick, especially if it needs to account for unbalanced
tags in the glossary item description.
--
Ticket URL: <https://meta.trac.wordpress.org/ticket/5746>
Making WordPress.org <https://meta.trac.wordpress.org/>
Making WordPress.org
More information about the wp-meta
mailing list