backdrop-issues icon indicating copy to clipboard operation
backdrop-issues copied to clipboard

Invalid markup if field prefix or suffix contain html tags

Open indigoxela opened this issue 3 years ago β€’ 20 comments

Description of the bug

In an otherwise unrelated issue we discovered a flaw with field prefix and suffix ending up with invalid markup.

Steps To Reproduce

Just as an example: the image field settings form:

  1. Go to admin/structure/types/manage/card/fields/field_image
  2. Switch to source display
  3. Check for the markup around id edit-instance-settings-max-dimensions

Actual behavior

HTML tags span / div nested in an invalid way.

broken-markup

Expected behavior

Valid markup.

Additional information

  • Backdrop CMS version: latest dev

This must be around for quite some time, but we didn't realize so far.

Another example is the Field UI global settings (cardinality). I'm pretty sure that there are even more.

indigoxela avatar Aug 21 '22 11:08 indigoxela

@indigoxela rehashing here what I said in https://github.com/backdrop/backdrop-issues/issues/1349#issuecomment-1221609901

...the issue with the invalid markup could be just a matter of using #prefix vs. #field_prefix and #suffix vs. #field_suffix properly. I often forget that #field_prefix/#field_suffix things even exist and use#prefix/#suffix most of the time (if not always). So chances are that others make the same mistake + then people that review code also miss it.

Perhaps we need a best-practice policy, where we discourage using markup in #prefix/#suffix and use the respective #field_* variants for that instead(?) ...or the other way around 🀷🏼

klonos avatar Aug 21 '22 19:08 klonos

...added the "documentation" label here, so that we may update https://docs.backdropcms.org/form_api with some notes.

klonos avatar Aug 21 '22 19:08 klonos

...as it turns out, #field_prefix and #field_suffix are already (always) wrapped in <span> tags. See theme_form_element():

  $prefix = isset($element['#field_prefix']) ? '<span class="field-prefix">' . $element['#field_prefix'] . '</span> ' : '';
  $suffix = isset($element['#field_suffix']) ? ' <span class="field-suffix">' . $element['#field_suffix'] . '</span>' : '';

This is definitely something worth mentioning in the Form API documentation!

Another thing worth documenting is that there apparently is no easy way to add classes/attributes to the <span> tags of #field_prefix and #field_suffix πŸ€”

klonos avatar Aug 21 '22 20:08 klonos

...as it turns out, #field_prefix and #field_suffix are already (always) wrapped in tags

Right, I wasn't completely aware of that, too. And probably did it also wrong (in contrib or custom code).

So IMO the first step is to fix how core uses the field prefix and suffix. My suspicion: there's a reason why some core fields do it that way. Probably there was no other solution for the problem to solve?

And of course, the documentation should be clearer about what prefix or suffix are supposed to contain (and what not).

indigoxela avatar Aug 22 '22 06:08 indigoxela

...documentation should be clearer about what prefix or suffix are supposed to contain (and what not).

Agreed πŸ‘πŸΌ ...actually, there are some hints currently. In the Form API documentation #prefix/#suffix are described as:

Text or markup to include before/after the form element.

...whereas for #field_prefix/#field_suffix the respective description doesn't mention markup:

Text or code that is placed directly in front of/after a field.

It seems that markup is not explicitly mentioned for the #field_* properties.

klonos avatar Aug 22 '22 11:08 klonos

...odd how #prefix/#suffix are listed in https://www.drupal.org/docs/drupal-apis/form-api/form-render-elements, but #field_prefix/#field_suffix aren't. Were these introduced later in D8 (and Backdrop) but not in D7 or something?

Anyway, here's some further descriptions for those that we should add in our documentation:

(string) Prefix/Suffix to display before/after the HTML input element. Should be translated, normally. If it is not already wrapped in a safe markup object, will be filtered for XSS safety.

klonos avatar Aug 22 '22 14:08 klonos

I added some commentary to https://docs.backdropcms.org/form_api#field_prefix, also https://docs.backdropcms.org/form_api#prefix. Further suggestions/requests solicited, of course.

bugfolder avatar Aug 22 '22 15:08 bugfolder

Thanks @bugfoder. The text seems very clear to me. Check a typo - "$suffix" instead of "#suffix".

argiepiano avatar Aug 22 '22 17:08 argiepiano

Typo fixed.

bugfolder avatar Aug 22 '22 17:08 bugfolder

I did a quick check: we inherited this markup mess from Drupal, which has the same problem.

Markup as wrapper for items using field_prefix and field_suffix is used in several places in core:

  • core/modules/field_ui/field_ui.admin.inc
  • core/modules/image/image.field.inc
  • core/modules/locale/locale.admin.inc
  • core/modules/views/plugins/views_plugin_display_page.inc
  • core/modules/filter/filter.admin.inc
  • core/modules/layout/layout.flexible.inc

My suspicion: it's done that way because there's no other way to achieve the desired result.

So IMO we should:

  1. Verify if there are alternative for field_prefix/field_suffix for these cases
  2. If so, implement these alternatives in core
  3. If not, figure out what's missing in core to achieve these results
  4. If there's no alternative yet, either provide one or drop the automatic span around prefix/suffix entirely

Feedback is welcome!

indigoxela avatar Aug 25 '22 09:08 indigoxela

...we inherited this markup mess from Drupal, which has the same problem.

Did you find any d.o issues while looking into this @indigoxela? Curious to see what possible solutions our Drupal brethren might have thought of.

...or drop the automatic span around prefix/suffix entirely

I was thinking that we could perhaps introduce a hook that would provide the defaults, but also allow affecting the markup used. I haven't fully fleshed out how/if that can happen.

klonos avatar Aug 25 '22 11:08 klonos

I added some commentary to https://docs.backdropcms.org/form_api#field_prefix, also https://docs.backdropcms.org/form_api#prefix. Further suggestions/requests solicited, of course.

Thank you @bugfolder πŸ™πŸΌ

I've asked this question in our internal developers Slack channel:

I have searched in Drupal documentation and in articles/posts around the internet, yet it is still unclear to me in which cases you'd use #prefix/#suffix vs #field_prefix/#field_suffix ...does anyone know? For context + some relevant findings/documentation, see: Invalid markup if field prefix or suffix contain html tags #5735

I got the following replies:

Been a while but from what I remember #prefix is a more general theme render array property, FAPI inherits the render array so the theme system renders it as normal. #field_prefix is a themed implementation of a property specifically for FAPI, so it’s scope is more limited to just visible fields generally.

prefix/suffix add markups outside of the element template. field_prefix adds the markup inside the element template, usually right before the element tag.

We should validate these (they may only apply to D8/9), and if helpful add them to our documentation as well.

klonos avatar Aug 25 '22 11:08 klonos

prefix/suffix add markups outside of the element template. field_prefix adds the markup inside the element template, usually right before the element tag.

This is also correct for Backdrop, but I don't think this solves anything per se. :wink:

indigoxela avatar Aug 25 '22 12:08 indigoxela

Verify if there are alternative for field_prefix/field_suffix for these cases

Coming to this late and have not done my "homework", but how about just replacing those faulty #field_prefix and #field_suffix with #prefix and #suffix? Wouldn't that solve the faulty markup? Personally I've always used #prefix and #suffix for markup. I wasn't even aware of the other ones.

argiepiano avatar Aug 25 '22 12:08 argiepiano

To verify if there are alternatives in core, I played with function image_field_instance_settings_form.

  • Form type "item" ignores '#attributes' for class
  • Form type "container" can't have a title (title is needed here)
  • Even if type "item" could have classes it wouldn't work, as the .container-inline CSS expects an inner <div>
  • Switching to prefix/suffix doesn't work, either (completely messes form display)
  • Giving the two inner elements the .container-inline class doesn't work, either (messes display)

My conclusion: this abuse of field_prefix/field_suffix happened because currently there's no easy way to get nested inline elements as this item would need.

indigoxela avatar Aug 25 '22 12:08 indigoxela

^^ Wow, simultaneously. :laughing:

indigoxela avatar Aug 25 '22 12:08 indigoxela

Switching to prefix/suffix doesn't work, either (completely messes form display)

haha ok this answers it. Thanks @indigoxela

argiepiano avatar Aug 25 '22 12:08 argiepiano

Probably the easiest solution would be to add a new CSS class like "item-inline-block", which allows individual form items inside a container to be displayed - inline-block.

Another solution would be to style these items, that currently abuse field_prefix/field_suffix, specifically. (Not my favorite, as several form items seem to need that sort of styling.)

indigoxela avatar Aug 25 '22 13:08 indigoxela

Here we go, a PR based on the idea from my previous comment.

See it in action on:

  • admin/structure/types/manage/card/fields/field_image (Max/Min image dimensions, and Global / Number of values)
  • /admin/config/content/formats/filtered_html (Maximum dimensions)

There's some more questionable usage with wrapper markup, but these are span and don't seem to cause invalid markup.

Another documentation issue: #wrapper_attributes are used by all form items, not only the ones listed there. (See here).

indigoxela avatar Aug 25 '22 14:08 indigoxela

Lack of interest for years now (it seems) and a merge conflict, that would need resolving... A good opportunity to close the PR. The bug report still seems valid to me, though, so not closing the issue.

indigoxela avatar Jun 22 '24 10:06 indigoxela