Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
If a (non-active) local task contains a "&" character, and the item is NOT marked as html, this character will be filtered twice in bootstrap_menu_local_task():
- filter_xss_admin()
- the usual check_plain() as part of l().
This causes the tab (local task) to have a visible "&" in its title. Sad!
Note: This does not happen for active local tasks, because.. well, look into the code.
Also this comment is wrong:
// Filter the title if the "html" is not set, otherwise l() will automatically
// sanitize using check_plain(), so no need to call that here.
It is the other way round: l() will automatically sanitize if html is NOT set. If html = TRUE, then l() will NOT sanitize.
Comment | File | Size | Author |
---|---|---|---|
#5 | 2866798-4.patch | 1.36 KB | markhalliwell |
Comments
Comment #2
donquixote CreditAttribution: donquixote as a volunteer commentedMaybe whenever stuff like this happens, it is time to replace the ternary ?: with if / else :)
Comment #3
donquixote CreditAttribution: donquixote as a volunteer commentedgit blame pointed me to commit e165225ed5 and issue #2827761: Menu HTML breaks.
Comment #4
donquixote CreditAttribution: donquixote as a volunteer commentedAnd commit b8be0646716d9bd6066128e403fcc9b8e22cefbd with message "Fix bugs".
Comment #5
markhalliwellAh, good catch. It needs to set
$options['html'] = TRUE
if it usesfilter_xss_admin()
; which inadvertently requires an if/else block instead of a ternary operator.Try this patch.
Comment #6
donquixote CreditAttribution: donquixote as a volunteer commented(I wrote this before your comment, I think it applies anyway)
The implementation in Drupal core seems fine,
https://api.drupal.org/api/drupal/includes%21menu.inc/function/theme_men...
The $link_text is left untouched for non-active local tasks.
Only for the active local task, the link text is checkplained before going into t().
The smelly thing about this core code is how it writes to array values instead of using local variables. But this should not have visible effects, it is just bad practice.
So why the different logic in Bootstrap?
Comment #7
donquixote CreditAttribution: donquixote as a volunteer commentedAbout your patch..
Core theme_menu_local_task(), via l(), would have applied check_plain() in this case. In your patched code you apply filter_xss_admin() instead of check_plain(). I'd say this is probably wrong..
This comment is still wrong..
In this case the thing will *not* be filtered by l() because
$options['html'] === TRUE
.Comment #8
donquixote CreditAttribution: donquixote as a volunteer commentedOtherwise the code looks like it is mostly equivalent with core.. no additional classes added.
Maybe we could drop this theme implementation altogether!
If we do this, I think it might still be wise to have
- one commit to fix the theme implementation (possibly replacing it with a copy from core)
- another commit to drop the theme implementation.
This gives a more useful git history, and allows to revert to a non-broken state.
Comment #9
donquixote CreditAttribution: donquixote as a volunteer commentedAnother difference I notice to core is the use of drupal_attributes()..
The only two possible values of $attributes are
array()
andarray('class' => array('active'))
.So it would be faster to just do
(!empty($variables['element']['#active']) ? ' class="active"' : '')
like core.Comment #10
markhalliwellShort version: it's not.
Long version:
I've just spent some time tracing back where this override was initially added.
Turns out it was actually added in the https://www.drupal.org/project/twitter_bootstrap project, commit aaec518 (well before I took over this project).
It seems they had originally added dropdowns to these for sub-tasks.
This file then became inherited by this project. It made its way through out the years getting whittled down.
Currently, these subtasks are now just rendered as pagination pills below the main tabs.
Thus, this has effectively made this override completely unnecessary.
Kind of funny how a bug actually determines that some inherited legacy code is irrelevant :D
---
So, I'm ok with your proposal and will commit both shortly:
- one commit to fix the theme implementation (possibly replacing it with a copy from core)
- another commit to drop the theme implementation.
Comment #11
markhalliwellComment #13
markhalliwellComment #14
donquixote CreditAttribution: donquixote as a volunteer commentedThanks!
Or it means that noone likes to review existing code unless there is a bug..
(no blame or guilt implied)
Comment #15
donquixote CreditAttribution: donquixote as a volunteer commentedMy idea was to insert a copy of core implementation instead of this call.. this would allow to see the diff between the different implementations.
Then the second commit message would say "drop custom implementation, because it is identical with core".
But I don't care, main thing is it is fixed :)