Problem/Motivation

Currently text fields can either be restricted to plain text, or the user may select between all accessible text formats independently of the context. This means that a privileged user who needs access to a permissive text formats (for example, to put tables or embedded remote content in basic pages) will get access to that format on every formatted text field (for example on a comment field).

There are three problems with this approach, and most experience Drupal developers have faced at least one of those in the past:

Consistency
At the moment you have to count on competence, good will and diligence of privileged users not to put certain markup in certain places. It would be convenient if a text field could be forced to use a specific text format (other than plain text). For example, you may want to make sure that comments only allow a very limited set of HTML tags ("filtertered HTML" for example) independently of the user's role, even if the same user has access to less restrictive formats in other places.
Usability
The ability to select text formats is a common source of confusion. By limiting the available text formats we also remove confusing user interface elements.
Security
If a privileged user account is taken over (for example, through social engineering), the attack surface is large due to the fact that every single text field can be used for XSS injections. By limiting where a dangerous text format can be used, we restrict the possibilities to inject malicious content.

Proposed resolution

Add an optional setting to the text field types that lets the site-builder determine if the text formats should be restricted. This setting is then used in the default textfield and textarea widgets to remove any non-allowed text formats. If nothing is set, the current behavior is unchanged.

Note that as it uses the underlying '#allowed_formats' form API property, the settings can't be used to give access to text formats that the user wouldn't have access to otherwise.

Remaining tasks

1) Review and commit 🤞

User interface changes

Checkboxes on list of available formats on text field configuration. Reduced set of allowed formats on content edit forms, where used. No fields use the new setting by default, so the patch doesn't affect the user interface for those who don't do anything with this functionality.

API changes

None

Data model changes

One setting is added to the field settings. The structure of the field data is unchanged.

Release notes snippet

Site builders can now limit which input formats are available on a per-field basis.

CommentFileSizeAuthor
#305 784672-drupal-10.0.x-305.patch42.37 KBa.dmitriiev
#302 784672-302.patch39.45 KBs_leu
#287 784672-287.patch39.92 KBsmustgrave
#287 interdiff-280-287.txt10.39 KBsmustgrave
#280 784672-280.patch42.98 KBsmustgrave
#280 interidff-278-280.txt744 bytessmustgrave
#278 784672-278.patch43.01 KBsmustgrave
#278 interdiff-271-278.txt1.6 KBsmustgrave
#271 784672-271-D10.patch43.01 KBdarvanen
#271 784672-266-271-interdiff.txt1.11 KBdarvanen
#271 784672-271.patch44.57 KBdarvanen
#266 784672-266-D10.patch38.98 KBsmustgrave
#266 784672-266.patch40.54 KBsmustgrave
#266 interdiff-263-266.txt3.6 KBsmustgrave
#264 784672-264-D10.patch39.25 KBsmustgrave
#263 784672-263.patch40.7 KBsmustgrave
#263 interdiff-256-263.txt4.75 KBsmustgrave
#256 784672-256.patch40.89 KBsmustgrave
#256 interdiff-253-256.txt4.1 KBsmustgrave
#253 784672-253.patch41.61 KBsmustgrave
#253 interdiff-251-253.txt3.92 KBsmustgrave
#251 784672-251.patch40.24 KBsmustgrave
#251 interdiff-250-251.txt1.15 KBsmustgrave
#250 784672-250.patch40.25 KBsmustgrave
#250 interdiff-244-250.txt1.63 KBsmustgrave
#244 interdiff-242-244.txt724 bytessmustgrave
#244 784672-244.patch38.83 KBsmustgrave
#242 784672-242.patch39.37 KBsmustgrave
#237 784672-237.patch36.92 KBsmustgrave
#236 interdiff-234-236.txt4.14 KBsmustgrave
#236 784672-236.patch36.98 KBsmustgrave
#234 784672-234.patch38.91 KBlarowlan
#231 interdiff-227-231.txt1.64 KBsmustgrave
#231 784672-231.patch38.3 KBsmustgrave
#227 interdiff_225-227.txt678 bytesravi.shankar
#227 784672-227.patch38.94 KBravi.shankar
#226 interdiff_219-225.txt1.12 KBravi.shankar
#225 784672-225.patch38.94 KBsmustgrave
#219 interdiff.txt9.47 KBDanielVeza
#219 784672-219.patch39.01 KBDanielVeza
#218 core-784672-restrict_text_format-217.patch36.16 KBvdsh
#213 patch-error-3.png184.34 KBvikashsoni
#213 patch-error-2.png139.09 KBvikashsoni
#213 patch-error-1.png201.82 KBvikashsoni
#201 interdiff_193-201.txt2.49 KBvsujeetkumar
#201 784672-201.patch36.28 KBvsujeetkumar
#197 Screenshot from 2021-06-09 11-34-34 (1).png410.19 KBRinku Jacob 13
#193 interdiff_189-193.txt850 bytesMeenakshi_j
#193 784672-193.patch36.23 KBMeenakshi_j
#189 interdiff-784672-187-189.txt863 bytesjoegraduate
#189 784672-189.patch36.23 KBjoegraduate
#187 interdiff-784672-186-187.txt1.74 KBjoegraduate
#187 784672-187.patch35.54 KBjoegraduate
#186 interdiff-784672-182-186.txt4.8 KBjoegraduate
#186 784672-186.patch35.5 KBjoegraduate
#184 interdiff-784672-182-184.txt2.1 KBvakulrai
#184 allowed_text_formats-784672-184.patch32.93 KBvakulrai
#182 interdiff_180-182.txt932 bytesjoegraduate
#182 784672-182.patch31.72 KBjoegraduate
#180 784672-180.patch31.01 KBminorOffense
#178 interdiff_176-178.txt2.18 KBraman.b
#178 784672-178.patch31.05 KBraman.b
#176 784672-176.patch31.19 KBviappidu
#175 784672-175.patch31.18 KBviappidu
#163 784672-163.patch31.44 KBAndyF
#163 interdiff_161-163.txt1.08 KBAndyF
text-field-format-1.patch17.21 KBc960657
#2 text-field-format-2.patch23.32 KBc960657
#16 drupal-enforce-specific-text-formats-784672-16.patch2.21 KBwjaspers
#34 limit_text_formats-784672-34.patch3.64 KBfloretan
#36 limit_text_formats-784672-36.patch11.89 KBfloretan
#38 limit_text_formats-784672-38.patch12.71 KBfloretan
#40 limit_text_formats-784672-40.patch12.71 KBfloretan
#43 limit_text_formats-784672-43.patch12.67 KBfloretan
#45 limit_text_formats-784672-45.patch12.79 KBfloretan
#53 allow_text_field_to-784672-53.patch12.79 KBvpeltot
#54 forced-text-formats.png31.39 KBmgifford
#56 allow_text_field_to-784672-56.patch14.4 KBfloretan
#59 allow_text_field_to-784672-58.patch15.56 KBfloretan
#62 784672-62.patch16.67 KBlokapujya
#62 784672-62-interdiff.txt3.83 KBlokapujya
#63 allow_text_field_to-784672-63.patch16.67 KBjcnventura
#65 allow_text_field_to-784672-65.patch16.82 KBjcnventura
#65 interdiff.txt1.94 KBjcnventura
#71 Screen Shot 2015-08-02 at 12.29.05.jpg391.93 KBLewisNyman
#71 Screen Shot 2015-08-02 at 12.34.03.jpg358.09 KBLewisNyman
#75 allow_text_field_to-784672-75.patch17.34 KBbruvers
#75 interdiff-65-75.txt3.92 KBbruvers
#78 interdiff-75-78.txt7.79 KBjcnventura
#78 allow_text_field_to-784672-78.patch18.72 KBjcnventura
#82 interdiff-78-82.txt776 bytesjcnventura
#82 allow_text_field_to-784672-82.patch18.72 KBjcnventura
#93 784672-reroll-93.patch17.46 KBlokapujya
#95 784672-reroll-95.patch17.33 KBlokapujya
#97 784672-reroll-97.patch583 byteslokapujya
#99 784672-99.patch17.27 KBlokapujya
#101 784672-101.patch17.83 KBfloretan
#101 interdiff-784672-99-101.txt386 bytesfloretan
#102 784672-102.patch17.7 KBfloretan
#102 interdiff-784672-99-102.txt1.29 KBfloretan
#105 784672-105.patch17.7 KBSonal.Sangale
#107 allow_text_field_to-784672-107.patch17.71 KBeiriksm
#108 allow_text_field_to-784672-108.patch17.86 KBeiriksm
#111 allow_text_field_to-784672-111.patch17.9 KBmohit_aghera
#111 interdiff.txt2.17 KBmohit_aghera
#123 allow_text_field_to-784672-123.patch17.96 KBjofitz
#131 allow_text_field_to-784672-131-8.5.x.patch19.28 KBgordon
#131 allow_text_field_to-784672-123-131.txt1.41 KBgordon
#134 784672-133-allow_text_format.patch20.6 KBjoelpittet
#134 interdiff.txt2.71 KBjoelpittet
#138 784672-138-allow_text_format.patch21.67 KBjoelpittet
#138 interdiff.txt2.42 KBjoelpittet
#145 784672-145-allow_text_format.patch21.92 KBjan.stoeckler
#152 784672-152.patch21.79 KBaleevas
#152 reroll_diff_145-152.txt18.51 KBaleevas
#159 interdiff_152-159.txt5.91 KBAndyF
#159 784672-159.patch22.74 KBAndyF
#161 interdiff_159-161.txt8.75 KBAndyF
#161 784672-161.patch30.86 KBAndyF
#164 784672-164.patch31.27 KBjungle
#164 interdiff-163-164.txt532 bytesjungle
#165 text-field-types.png191.08 KBjungle
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

c960657’s picture

Status: Needs review » Needs work
c960657’s picture

Status: Needs work » Needs review
FileSize
23.32 KB

Slightly new approach: '#type' => 'text_format' now has a new property, #formats, if only a subset of the format accessible to the user should be available in this field instance.

What do you think of this?

bjaspan’s picture

I don't see how this can go into D7 at this point.

webchick’s picture

Version: 7.x-dev » 8.x-dev

Agreed. Sorry.

c960657’s picture

Title: Allow text field to enfore a specific text format » Allow text field to enforce a specific text format
David_Rothstein’s picture

Something similar to the filter.module part of this issue was discussed at length in #414424: Introduce Form API #type 'text_format' but ultimately did not make it into the final patch. See for example:
http://drupal.org/node/414424#comment-1617600
http://drupal.org/node/414424#comment-2177612
(and many subsequent comments)

The argument I tried to make there was that since we were already doing a massive API change in that issue (completely reworking how #text_format works), it would make sense to slip in both something like the #formats option described here, as well as a #default_format option, since it would require almost no extra work to do so. I was overruled though...

So personally, if limited to the filter.module at least (the field module changes do seem like they might be too much for now) I'd be very in favor of still trying to do this in D7 :) It's possible to do this kind of thing in a contrib module - and people will undoubtedly try to do it - but it's tricky to do correctly (involves somewhat complex form API stuff that most people don't know about), and if you do it wrong, you are very likely to introduce a security issue. Plus, the filter.module changes here wouldn't break any existing code, just introduce a new optional property to the form element. I think adding this API functionality to the Filter module in a way that we know will be easy for contrib modules to use securely is definitely still worth doing. Anyone else agree? And would doing that help allow a contrib module to make the changes to the field UI/functionality that are contained in the rest of this patch?

ogi’s picture

It's sad that such essential ability for user-friendly forms is not in Drupal 7. Please reconsider :-)

ogi’s picture

Looking at the patch in #2, it doesn't provide what I want - ability to hide format fieldset altogether and wysiwyg+tinymce to do its job.

mightyiam’s picture

+1 for Drupal 7!

Hanno’s picture

Issue tags: +Accessibility

subscribe, a default text format for textfields might be also relevant to allow adding html tags for accessiblity.

Everett Zufelt’s picture

Issue tags: -Accessibility

This may help accessibility in some situations, but definitely isn't an accessibility issue. Removing tag, thanks for bringing it to my attention.

Hanno’s picture

Issue tags: +atag, +wcag2, +language of parts

OK. Tagging this as WCAG/ATAG and 'language of parts' as this feature request would help create accessible content, especially language tagging (WCAG2.0 3.1.2)

mgifford’s picture

#2: text-field-format-2.patch queued for re-testing.

mgifford’s picture

Issue tags: +Accessibility

Tagging for accessibility.

Status: Needs review » Needs work

The last submitted patch, text-field-format-2.patch, failed testing.

wjaspers’s picture

Drupal 7.x patch on-the-way.

I didn't change how the filter formats permissions are checked against the field, since this will require additional community feedback.
I.E. Should the user's permission to use the format supercede their ability to use a format specifically defined on a text field?

This probably isn't the most efficient patch in the world, but I have tested it locally against 7.x-dev and it works!

EDIT: Opened #1419016: Allow text fields to enforce a specific format so it could be tested against D7.

wjaspers’s picture

Status: Needs work » Needs review

Oops, forgot to set needs review.

Status: Needs review » Needs work

The last submitted patch, drupal-enforce-specific-text-formats-784672-16.patch, failed testing.

David_Rothstein’s picture

I think the strategy we need to take to implement this is:

1. Create an API in the filter system for any module which provides text format elements to specify which formats they want to allow in that instance.
2. Have the Text module implement that API.

We should really avoid hardcoding any special behavior for text fields inside the filter system itself, because that will limit how this can be used.

See also the related issue at #1423244: #allowed_formats property for #type 'text_format' to filter available formats. It almost would make sense to postpone this issue on that one (because that's basically #1 above), except that there's lots of code here already...

Note that there are also a lot of potential security issues that need to be dealt with in implementing this (see #1295248: Allow per-field-instance configuration of allowed formats for discussion and code), and that's one of the reasons why it would be good to at least have the API for this in core regardless of whether or not the code that implements it lives in core too.

mgifford’s picture

Issue tags: -Accessibility, -atag, -wcag2, -language of parts

We need clarification on why this is an accessibility issue. Sorry.

Hanno’s picture

Some while ago I tagged this issue as helping accessibility. For accessibility (or markup) in single line textfields we need sometimes additional HTML inline tags (span (for 'lang'), dfn and abbr). At the other hand, we don't want to allow HTML block level tags (h1, h2, h3, p) in single line fields, only in textareas.

So, in a website there are possibly two separate filter formats needed: one for single line textfields and one for textareas (where HTML block level tags are allowed). The end-user shouldn't be allowed to mix these sets, because we will end up with content that doesn't validate (ATAG2.0 issue (http://www.w3.org/TR/ATAG20/#principle_b2))
As abbr and dfn is needed on level AAA, it is mostly needed for language of parts (level AA), when someone wants to add text in another language (for example <span lang="fr">Tour de France</span>).

mgifford’s picture

Wished you'd been able to come over for A11ySprint by-the-way. You'd have had a great time with us I'm sure.

I think we just need a bit more of a use case where it's clear that this additional functionality meets the needs of the 80%.

How would this practically be used? I do think that there are a lot of instances where Languages of Parts really isn't dealt with all that well as you know.

What are the options for implementing this now in D7?

Hanno’s picture

@mgifford yes, it would have been nice to help during the sprint.

This issue is at the moment not relevant for most of the users. It becomes more relevant as soon as the node title becomes a text field (#1188394: Make title behave as a configurable, translatable field (again)). At the moment it is not possible to produce titles with language information nor semantic markup (part of WCAG 1.3.1 Info and Relationships: Information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text. (Level A)).

A technique for this is using semantic markup to mark emphasized or special text. For this certain - inline level - HTML tags are needed. Here are some examples taken from WCAG H49:

An excerpt from the <cite>The Story of my Life</cite> by Helen Keller
What she <em>really</em> meant to say was, "This is not ok,  it is <strong>excellent</strong>"!
Helen Keller said, "<q>Self-pity is our worst enemy and if we yield to it, we can never do anything good in the world.</q>"
Beth received 1<sup>st</sup> place in the 9<sup>th</sup> grade science competition.
The chemical notation for water is H<sub>2</sub>O.

Note: Instead of having two filter formats (one for text fields, one for text areas), an alternative could be to automatically disable the block level html tags in filter formats applied to text fields and only allowing them on text areas.

mgifford’s picture

Sadly this issue has been left behind. @Hanno are you in a place where you can try to update the patch?

sun’s picture

Component: field system » text.module
floretan’s picture

#1423244: #allowed_formats property for #type 'text_format' to filter available formats has a patch ready to be reviewed which adds some missing functionality in the text_format form element provided by the filter module. Once it's ready we can use it to make it possible to set the format for a specific field.

BrianLewisDesign’s picture

Issue summary: View changes

This feature is key. Please don't leave it behind. You should be able to select available formats per field. Some fields require a specific one or things break. (I guess if a user didn't have permissions for the available format it should make the field un-editable for them).

mgifford’s picture

Issue tags: +Needs reroll

Agreed. I'm wondering about tagging it for security. It's come up a few times thus far in this thread.

dsoini’s picture

This is very desirable to me. I have had to go about it with an ugly hack:

1. Created a custom module that searches the edit/add form for any field that has text_formats applied to it (sometimes there are many).
2. Hide the drop-down list but keep the guidelines for the default format displayed.
3. I set a default format by entering default text into the content-type field definition. The default text is

.

.
4. My modules looks for that default value and unsets it. I don't want the field polluted with this ugly data.

I like this functionality because sometimes I want a field that is just a simple 3 line box for entering a short amount of minimally-styled text. Perhaps I only want people to be able to use HTML to link some words in the text, but nothing else. I don't want them to have to switch between all the available content types, I don't want them to use a wysiwyg editor and be able to insert tables and headings and videos. I only want them to be presented with a simple box with guidelines on the limited allowed html they can use that is appropriate for that particular field.

The last submitted patch, text-field-format-1.patch, failed testing.

jenlampton’s picture

Issue tags: +Needs backport to D7
mgifford’s picture

Looks like #1423244-68: #allowed_formats property for #type 'text_format' to filter available formats was committed 10 months ago. @floretan suggested in #26 above that it "adds some missing functionality in the text_format form element provided by the filter module. Once it's ready we can use it to make it possible to set the format for a specific field."

Thanks for the link @jenlampton and yes, hopefully it gets backported.

floretan’s picture

Status: Needs work » Needs review
Issue tags: +drupaldevdays
FileSize
3.64 KB

The last patch didn't apply at all anymore, but the changes to the typed data API from the past two years have made it quite easy to rebuild this functionality.

Here's what this patch does:

  1. Make an additional setting available on the field editing form for all formatted text fields, like the body field of nodes for example. The checkboxes let you select what text formats should be available for that field.
  2. Use that setting on the widgets for fields of this type to determine what formats are available using the new #available_formats attribute from #1423244: #allowed_formats property for #type 'text_format' to filter available formats. Note that this only restricts what formats are available, it doesn't make formats available that the user doesn't have access to.

Open questions:

  1. Do we want to make the fallback format an option?
  2. The current patch adds the settings on the field level, based on the fact that it really affects what kind of data gets stored in the field, not only how it's entered. However, the validation is only done at the widget level. We should probably add some validation at the field level as well.

Once this gets in, we can have a follow-up issue where we check all fields in the default installation profile that should have limited text formats. For example, comments should probably be limited to "Restricted Html".

Status: Needs review » Needs work

The last submitted patch, 34: limit_text_formats-784672-34.patch, failed testing.

floretan’s picture

Status: Needs work » Needs review
FileSize
11.89 KB

Adding default configurations to fix most of the exceptions seen in the test results.

Status: Needs review » Needs work

The last submitted patch, 36: limit_text_formats-784672-36.patch, failed testing.

floretan’s picture

Status: Needs work » Needs review
FileSize
12.71 KB

Fixing two more failures. The remaining failures are related to FieldUiTestTrait and I'm not sure how to fix them yet. Any help on that would be appreciated.

Status: Needs review » Needs work

The last submitted patch, 38: limit_text_formats-784672-38.patch, failed testing.

floretan’s picture

Status: Needs work » Needs review
FileSize
12.71 KB

Oh, the ordering of items in an array matters for comparison.

yannickoo’s picture

  1. +++ b/core/modules/block_content/block_content.module
    @@ -83,7 +83,10 @@ function block_content_add_body_field($block_type_id, $label = 'Body') {
    +        'available_formats' => array(),
    
    +++ b/core/modules/config_translation/src/Tests/ConfigTranslationListUiTest.php
    @@ -401,7 +401,10 @@ public function doFieldListTest() {
    +        'available_formats' => array(),
    
    +++ b/core/modules/migrate_drupal/src/Tests/d6/MigrateFieldInstanceTest.php
    @@ -90,7 +90,10 @@ public function testFieldInstanceSettings() {
    +      'allowed_formats' => array(),
    
    +++ b/core/modules/node/node.module
    @@ -328,7 +328,10 @@ function node_add_body_field(NodeTypeInterface $type, $label = 'Body') {
    +        'available_formats' => array(),
    

    Just a minor thing: We should use the new syntax here, just [] instead of array().

  2. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -12,12 +12,37 @@
    +    $element['available_formats'] =  array(
    

    Another minor thing: We should remove that " " two spaces there.

Status: Needs review » Needs work

The last submitted patch, 40: limit_text_formats-784672-40.patch, failed testing.

floretan’s picture

Fix the confusion between "available" and "allowed".

@yannickoo: I also fixed the double spacing in TextItemBase.php. Regarding the array notation, all of the modified files use the old array() notation, so I left it as is to not add unrelated changes with the patch.

floretan’s picture

Status: Needs work » Needs review
floretan’s picture

This new patch fixes the schema definition for the individual formats in allowed_formats fields in text.schema.yml, which should fix the remaining failures.

The last submitted patch, 43: limit_text_formats-784672-43.patch, failed testing.

yannickoo’s picture

Status: Needs review » Reviewed & tested by the community

Ah sequence property did the trick ;)

Patch works fine, code looks good and no more failing tests!

floretan’s picture

Status: Reviewed & tested by the community » Needs work

Actually, there are few more things that need to happen.

At the moment, the allowed formats get exported like this (because that's the way checkbox values are submitted):

  allowed_formats:
    basic_html: basic_html
    restricted_html: restricted_html
    full_html: 0
    plain_text: 0

What we want is something like

  allowed_formats:
    - basic_html
    - restricted_html

Once we have this, we can update the configuration schema in text.schema.yml. The allowed formats are a sequence, but their values are not just any strings. So we should replace

    allowed_formats:
      type: sequence
      label: 'Allowed text formats'
      sequence:
        type: string

with something like

    allowed_formats:
      type: sequence
      label: 'Allowed text formats'
      sequence:
        type: filter.format.[%value]

One final but important addition we would need is some test coverage. The #allowed_formats form API property is already covered, but we probably need to extend some more textfield-related tests.

One issue pointed out by @maijs is that when applying this patch and there are already existing fields without the allowed_formats setting we get "undefined index" notices. We don't do something similar for other settings that have always been there, so I'm not sure if this is needed since it's one case of beta-to-beta upgrade. Saving the field settings form would get rid of those notices.

rpayanm’s picture

Issue tags: -Needs reroll

Status: Needs work » Needs review
vpeltot’s picture

Status: Needs review » Needs work
woprrr’s picture

This patch work fine in my case !! Thanks @floretan

ps : It would just be more optimized to put as select.

vpeltot’s picture

Status: Needs work » Needs review
FileSize
12.79 KB

Reroll.

Migrate installation confiuration files (core/modules/migrate_drupal/config/install) was moved to core/modules/migrate_drupal/config/optionnal.

mgifford’s picture

Issue summary: View changes
FileSize
31.39 KB

You can see this here /admin/structure/types/manage/page/fields/node.page.body

shot of admin page

Looks good to me. What else, if anything, is needed before this is marked RTBC?

floretan’s picture

The schema change I mentioned in #48 is not necessarily needed, but a test should be included.

floretan’s picture

While working on more real Drupal 8 projects, this functionality seems to be needed everywhere.

Here's the patch re-rolled, with some tests added. This should be good now.

Status: Needs review » Needs work

The last submitted patch, 56: allow_text_field_to-784672-56.patch, failed testing.

lokapujya’s picture

+++ b/core/modules/text/src/Tests/TextFieldTest.php
@@ -182,6 +182,31 @@ function _testTextfieldWidgetsFormatted($field_type, $widget_type) {
+    // Limit our field to only allow the newly created format.
+    $field_storage->set('settings', array('allowed_formats' => array($format_id)));

The set() is not working. I tried setSetting() and even calling save() after. The allowed_formats doesn't get saved to field storage.

floretan’s picture

Status: Needs work » Needs review
FileSize
15.56 KB

Thanks @lokapujya. The format ID should be in the key of the settings array, not in the value.

I also realised that the patch I uploaded somehow had an older version of the test. Here is the correct one (no functional change, only the test is different).

rcross’s picture

is there a d7 version of this patch (or one in the works)?

floretan’s picture

@rcross: it could be done, but #1423244: #allowed_formats property for #type 'text_format' to filter available formats would need to be committed first.

lokapujya’s picture

Changed the test so that it first has 2 formats. Verify that the format select shows up. Change the field to only have 1 format. Then, verify that the format selector doesn't show up.

Also, made the following changes:

  1. +++ b/core/modules/text/src/Tests/TextFieldTest.php
    @@ -84,6 +84,69 @@ function testTextfieldWidgetsFormatted() {
    +    // Create a second text formats.
    

    format (singular.)

  2. +++ b/core/modules/text/src/Tests/TextFieldTest.php
    @@ -84,6 +84,69 @@ function testTextfieldWidgetsFormatted() {
    +      'settings' => array('allowed_formats' => array($format1->id() => TRUE)),
    

    This still wasn't working. The format selector was not showing up, but only because no formats were allowed.

  3. +++ b/core/modules/text/src/Tests/TextFieldTest.php
    @@ -84,6 +84,69 @@ function testTextfieldWidgetsFormatted() {
    +    $this->assertFieldByName("{$field_name}[0][value]", '', 'Widget is displayed');
    

    '' should be NULL.

Status: Needs review » Needs work

The last submitted patch, 63: allow_text_field_to-784672-63.patch, failed testing.

jcnventura’s picture

Status: Needs work » Needs review
FileSize
16.82 KB
1.94 KB

Prior to the use of array_filter, check if the value to be filtered is an array.

lauriii’s picture

jcnventura’s picture

Issue summary: View changes
jcnventura’s picture

Issue summary: View changes
floretan’s picture

Issue summary: View changes

Updating the summary.

lauriii’s picture

Category: Feature request » Task

It seems more like a task than a complete new feature. Beta evaluation needs update too.

LewisNyman’s picture

Issue summary: View changes
Status: Needs review » Needs work
FileSize
391.93 KB
358.09 KB

Nice, this is a really cool feature. I reviewed the usability of the new UI. Only minor comments:

Can we move these options so they are above the default value display? It is quite big and has shown a tendency to be distracting in usability tests. If we move the options above the default value they have a better chance of being noticed.

Here's a screenshot displaying the changes to the content creation screen. When there are multiple choices it's the same UI. When there is only one choice the UI looks like this:

Can we remove the text formats help link if there are no options? It doesn't seem to provide any value.

floretan’s picture

Status: Needs work » Needs review

Thanks @LewisNyman for the review.

I agree that placing these options above the default value would make sense, but that would be different from what every other field configuration form does (the default value always comes first), so I'm not sure we want to do that.

I also agree that the link "About text formats" doesn't make sense if there is only one text format available. The changes in this issue make that problem apparent, but the problem is independent. I created #2544188: Change the label "About text formats" if only one format is available to address that issue, it probably shouldn't be combined with this one.

jcnventura’s picture

fgm’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/text/src/Plugin/Field/FieldWidget/TextareaWidget.php
    @@ -35,6 +35,14 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
    +      if (!empty($allowed_formats) && !$this->isDefaultValueWidget($form_state)) {
    

    Probably want to avoid two function calls by refactoring to a temporary variable.

  2. +++ b/core/modules/text/src/Plugin/Field/FieldWidget/TextfieldWidget.php
    @@ -35,6 +35,14 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
    +      $allowed_formats = array_filter($this->getFieldSetting('allowed_formats'));
    

    Probably want to avoid two function calls by refactoring to a temporary variable, here too.

EDIT because DrEditor doesn't make it really clear, this is about the repeated calls to $this->getFieldSetting('allowed_formats')); in both cases.

bruvers’s picture

Status: Needs work » Needs review
FileSize
17.34 KB
3.92 KB

The latest patch from #65 did not apply correctly anymore because 2 files were moved by recently commited issues #2415335 and #2534010. The files that have been moved and/or renamed are

  • core/modules/block_content/migration_templates/d6_block_content_body_field.yml and
  • core/modules/migrate_drupal/src/Tests/d6/MigrateFieldInstanceTest.php .

The attached patch fixes that and implements the suggestions from #74.

yannickoo’s picture

+++ b/core/modules/field/src/Tests/Migrate/d6/MigrateFieldInstanceTest.php
@@ -78,7 +78,10 @@ public function testFieldInstanceSettings() {
-    $expected = array('max_length' => 255);
+    $expected = array(
+      'allowed_formats' => array(),
+      'max_length' => 255,
+    );

What do you think about using $expected = ['max_length' => 255] instead of array() syntax?

lokapujya’s picture

Does #71 & #72 qualify as the usability review?

jcnventura’s picture

Status: Needs review » Needs work

The last submitted patch, 78: allow_text_field_to-784672-78.patch, failed testing.

lokapujya’s picture

What happens if the field allows only one format, but the user doesn't have access to that format?

The last submitted patch, 78: allow_text_field_to-784672-78.patch, failed testing.

jcnventura’s picture

Status: Needs work » Needs review
FileSize
776 bytes
18.72 KB

Stupid array comparison.

jcnventura’s picture

@lokapujya: Not sure how to reproduce that.. The plain text format is always available. If you find a way to disable or delete it, I can then answer your question. My guess is that the correct reply to your question is that, by design, Drupal will always allow you to use the plain text format.

The last submitted patch, 78: allow_text_field_to-784672-78.patch, failed testing.

lokapujya’s picture

My guess is that the correct reply to your question is that, by design, Drupal will always allow you to use the plain text format.

That's true, but, now with this patch, it can be configured that "plain text" is not allowed for the field.

What happens if the field allows only one format, but the user doesn't have access to that format?

The content editor will get this message in the input box when adding a new node, "This field has been disabled because you do not have sufficient permissions to edit it." That is the same message the content editor would get if he edited a piece of content and doesn't have access to the format.

Bojhan’s picture

Issue tags: -Needs usability review

Looks good!

Status: Needs review » Needs work

The last submitted patch, 82: allow_text_field_to-784672-82.patch, failed testing.

floretan’s picture

Version: 8.0.x-dev » 8.1.x-dev
Status: Needs work » Postponed

After discussing this with various people at the code sprint, it became clear that the best way to approach this issue is to implement it as a contrib module for now and eventually integrate it in Drupal 8.1. At this point the somewhat unclear logic for all fallback cases will be battle-tested.

I created a module here https://www.drupal.org/project/allowed_formats, we are working on converting the latest patch from this issue to a contrib module. Please join that module's issue queue if you want to contribute.

floretan’s picture

The Allowed Formats module (https://www.drupal.org/project/allowed_formats) is now functional.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

mlncn’s picture

Status: Postponed » Needs work

Nice that there's a contrib module, but can we go back to getting this into core, now targeting 8.2?

lokapujya’s picture

Status: Needs work » Needs review
FileSize
17.46 KB

not tested.

Status: Needs review » Needs work

The last submitted patch, 93: 784672-reroll-93.patch, failed testing.

lokapujya’s picture

Status: Needs work » Needs review
FileSize
17.33 KB

Status: Needs review » Needs work

The last submitted patch, 95: 784672-reroll-95.patch, failed testing.

lokapujya’s picture

Status: Needs work » Needs review
FileSize
583 bytes

this is the interdiff.

Status: Needs review » Needs work

The last submitted patch, 97: 784672-reroll-97.patch, failed testing.

lokapujya’s picture

Status: Needs work » Needs review
FileSize
17.27 KB

Status: Needs review » Needs work

The last submitted patch, 99: 784672-99.patch, failed testing.

floretan’s picture

FileSize
17.83 KB
386 bytes

Updated patch that addresses the DefaultConfigTest failures.

floretan’s picture

Also fix MigrateFieldInstanceTest failure.

colan’s picture

Anyone have thoughts on whether #1278886: Default text formats are not saved properly without accompanying values should be postponed until we get this one done? This might affect how that one is solved.

lokapujya’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

The last retest failed to apply.

Sonal.Sangale’s picture

Assigned: Unassigned » Sonal.Sangale
Status: Needs work » Needs review
FileSize
17.7 KB

Relolling the patch.

Sonal.Sangale’s picture

Assigned: Sonal.Sangale » Unassigned
eiriksm’s picture

Patch does not apply anymore (because forum config was renamed).

Code looks ok though.

Re-roll patch.

eiriksm’s picture

Hm, maybe we should add a description to the field. For example. it is not immediately obvious what happens if you select no allowed formats.

Here is a patch with only that added.

eiriksm’s picture

Issue tags: +DevDaysMilan
hchonov’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -7,12 +7,36 @@
    +  public function fieldSettingsForm(array $form, FormStateInterface $form_state) {
    

    inheritdoc missing.

  2. +++ b/core/modules/text/src/Plugin/Field/FieldWidget/TextfieldWidget.php
    @@ -25,11 +25,20 @@ class TextfieldWidget extends StringTextfieldWidget {
    +    if (is_array($allowed_formats_setting)) {
    

    The is_array check is not needed as it impossible to get anything different than an array there.

  3. +++ b/core/modules/text/src/Plugin/Field/FieldWidget/TextfieldWidget.php
    @@ -25,11 +25,20 @@ class TextfieldWidget extends StringTextfieldWidget {
    +      $allowed_formats = array_filter($allowed_formats_setting);
    

    Why do we need to filter the array here?

mohit_aghera’s picture

Status: Needs work » Needs review
FileSize
17.9 KB
2.17 KB

@hchonov
I have fixed 1 and 2

I tested by removing point 3 $allowed_formats = array_filter($allowed_formats_setting);
and tested manually. It seems worked fine for me.
still we can get some inputs from @eiriksm

eiriksm’s picture

Feedback totally makes sense. As I said it was more or less a re-roll.

Nice points!

Status: Needs review » Needs work

The last submitted patch, 111: allow_text_field_to-784672-111.patch, failed testing.

hchonov’s picture

@mohit_aghera when you are posting an interdiff please make it so that it indicates all the changes that are included, in your case the third change is to see in the interdiff, but not in the posted patch.

  1. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -16,6 +17,31 @@
    +      '#title' => t('Allowed text formats'),
    ...
    +      '#description' => t('Select the allowed text formats. If no formats are selected, all available text formats will be displayed to the user.'),
    

    Use $this->t() instead of t() whenever possible.

  2. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -16,6 +17,31 @@
    +      '#options' => $this->getProperties()['format']->getPossibleOptions(),
    

    The property should be retrieved with $this->get('format').

  3. +++ b/core/modules/text/src/Tests/TextFieldTest.php
    @@ -142,6 +142,77 @@ function testTextfieldWidgetsFormatted() {
    +
    ...
    @@ -182,8 +253,8 @@ function _testTextfieldWidgetsFormatted($field_type, $widget_type) {
    

    An empty line is not needed here.

tstoeckler’s picture

Some high-level remarks on the current approach:

We need to implement calculateDependencies() to declare a dependency on the text formats that we are limiting the text field to. Then we also need to implement onDependencyRemoval() to remove a text format from the list of allowed formats in case it is removed. This then becomes problematic if we are removing the single text format that was allowed for a field. In that case the allowed_formats array is empty which means that all formats are allowed which would be a security problem.

I think that problem hints to the fact that the "no values means all values" pattern employed here - while being used elsewhere in Drupal as well - really is problematic and I think we would be wise to avoid it in this case. I would suggest to add a separate restrict_formats boolean setting that activates this behavior. Then the allowed_formats setting really is just that: the list of allowed formats. And if it is empty (and restrict_formats is TRUE) then it simply means that no text formats are allowed and thus text cannot be submitted until this issue is resolved either by allowing one or more formats or by deactivating restrict_formats altogether.

I by no means think that we always need to have a 1-1 relationship between our UI elements and our storage but in this particular case I think the separate setting would make the UI less confusing as well. We could have a simple Restrict text formats checkbox and only when it is checked does the list of text formats to allow appear.

Would love to hear your thoughts on this, but marking needs work because - as explained in the first paragraph - the current patch is not sufficient, even if we pursue a different approach than outlined here.

hchonov’s picture

@tstoeckler what about if we just name it restricted_formats or enforced_formats and in this case only use what is set there without the boolean flag.

tstoeckler’s picture

Issue tags: -Needs reroll

i.e. always restrict the list of text formats, and just have it default to all formats by default? I am not sure about that. Given the properly implemented dependencies, it would mean that every textfield has a dependency on every text format or a subset of them but at the very least on one. That could be seen as a benefit if you see it as already existing dependencies becoming more explicit or you could see it as a a problem if you argue that it increases coupling of different systems (text storage vs. text processing). Not sure where I stand on that myself.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

nerdstein’s picture

I am curious if this should be closed since the Allowed Formats module is offering this functionality (per: https://www.drupal.org/node/784672#comment-10373375)

Berdir’s picture

I think the point of that issue is to bring that functionality into core which would IMHO make sense as it is a very useful feature. We only started that contrib module because we didn't manage to get it into core for 8.0.

lokapujya’s picture

Issue tags: +Needs reroll

Doesn't apply to 8.4

jofitz’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
FileSize
17.96 KB

Re-rolled.

Status: Needs review » Needs work

The last submitted patch, 123: allow_text_field_to-784672-123.patch, failed testing.

tstoeckler’s picture

Having thought about this for a while and having watched a bunch of other bugs being fixed with config dependencies in the meantime, I am convinced that we need to restructure the configuration that is currently being pursued by this patch. Feel free to disagree, of course, but this is what I think what we should do:

* Have a separate "restrict_formats" boolean flag, that defaults to FALSE.
* Have a "allowed_formats" array (just like now), that defaults to an empty array.

Then if "restrict_formats" is FALSE, then we do nothing. As soon as it is used then we use the "allowed_formats" array.
This is for the following reason:

We will have to add a config dependency on any text format that is being used. Then if a format is being deleted we will need to remove that format from the list of allowed formats. If that format happened to be the *last* format, then it must not be possible to use any format at all until the field is re-configured explicitly. Anything else would be a security problem. Currently if we remove the last format, the field is interpreted as not restricting formats as all.

I hope that was clear, this is kind of hard to explain... What do you think?

Berdir’s picture

Unexpected behavior, yes, security issue, no, IMHO. This is not a security feature, it's a user experience improvement. Security is handled through permissions and you'd still only have access to formats that you are allowed to use.

I think showing all would be OK, we don't really have an API/UI to handle having no allowed format, it would likely just fall back to the fallback format, which is most likely not what you want.

We could also force you to fix your configuration first by letting the field be deleted, but we all know that users don't really read those warnings (e.g. the related views deletion issue), at least not with the current UI.

mofdi’s picture

to resolve this problem, i used allowed_formats module

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Joao Sausen’s picture

A must have for sure. +1 to this feature

gordon’s picture

+++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
@@ -7,12 +7,38 @@
+      '#title' => t('Allowed text formats'),
...
+      '#description' => t('Select the allowed text formats. If no formats are selected, all available text formats will be displayed to the user.'),

Should not use t() inside an object. Use $this->t() instead.

joelpittet’s picture

Status: Needs work » Needs review
Issue tags: +Usability

Rerunning a test against 8.6.x

joelpittet’s picture

Addressing a couple of the errors

joelpittet’s picture

@tstoeckler re #125 Can we address the config dependency in a follow-up and does @Berdir's comments help alleviate your security concern?

Status: Needs review » Needs work

The last submitted patch, 134: 784672-133-allow_text_format.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Status: Needs review » Needs work

The last submitted patch, 134: 784672-133-allow_text_format.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

joelpittet’s picture

Status: Needs work » Needs review
FileSize
21.67 KB
2.42 KB

Missing use statement in test and umami default config for copyright field.

Status: Needs review » Needs work

The last submitted patch, 138: 784672-138-allow_text_format.patch, failed testing. View results

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

tstoeckler’s picture

Re #135: Yes #126 is correct that it would be not be a security issue, unlike I claimed. However, not cleaning up the configuration would be a bug that we would be introducing here, so I don't think we can punt that to a follow-up. Also, since my proposal would change the configuration structure relative to what the patch contains now, I think - if people agree with my proposal - we should just do it "correctly" now instead of changing it again in a follow-up.

joelpittet’s picture

@tstoeckler thanks for the quick reply, regarding your proposal of the extra field. What do we gain from the extra field? Can't we let none or explicit all checked for showing all? I believe that's how other things have worked in the past.

tstoeckler’s picture

It's true that this has been used before, but it has also lead to problems.

In this particular case the problem would be the following:

  • Say you have a field that is limited to only allow text format basic_html
  • The administrator then removes the basic_html text format
  • Since we have added the restricted filter as a config dependency, it is cleaned up when the format is deleted and the format is removed from the list of allowed formats
  • Since the list is now empty, the text filter now allows all formats. Since access to text formats is checked independently of this configuration n one will be able to use a format they don't have access to, but still this behavior violates the principle of least surprise

If we agree that this is not a big issue, I don't feel super strongly about this, but on the other hand I don't see much reason not to do it this way.

Berdir’s picture

We actually have this pattern already with allowed bundles in entity reference fields. We handle it there by treating NULL and [] differently. NULL means all filter formats are allowed that the user has access to, [] means none are allowed.

We could specifically test for that and disable the text field completely, similar to how we now handle existing data in a format that the user is not allowed to use, disabling the form element, possibly failing validation, forcing the admin to fix it.

Then again, this is actually rather theoretical, because officially, there is no way to delete a text format, you can only disable it (in which case you can't restore it, but that's another story).

So the only way to delete one would be through the API/deleting config files.

jan.stoeckler’s picture

Reroll attempt against 8.6.

AdamPS’s picture

Good points from @Berdir in #144.

  • It seems to make a lot of sense to copy the existing model of entity reference fields.
  • Deleting text formats is theoretical - at least at the moment.

Also sticking to a single field has the advantage of simplicity. Do we have a consensus for @Berdir suggestion? OK with you @tstoeckler?

In terms of "[] means none are allowed", if someone is keen they could add it to this patch. Or we could defer it to a follow-up issue on the basis that there is currently no UI to delete text formats.

GDrupal’s picture

The patch seems to be working from the functional point of view but it seems that we need to accommodate some of the core tests.
I tested on 8.7 and then re-rolled back to 8.5.8 that is the stable for our platform. All is working fine so far, documented the re-roll here:
https://www.drupal.org/project/drupal/issues/3008020
I will try to fix the failing tests if none-one is working on that already.
Thanks for this!

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

iyyappan.govind’s picture

Hi All,

Having this feature in field settings will be applicable for all the form modes. So we can't restrict it to particular form mode. So Can we implement this feature based on form display?

Hope makes sense.Thanks

tstoeckler’s picture

Re #149 I think that is a separate feature request, to make this available as a widget setting for the formatted textarea widget.

mpp’s picture

Thanks for the patch, very useful!

Some really small remarks:

  1. +++ b/core/modules/text/config/schema/text.schema.yml
    @@ -38,6 +44,12 @@ field.storage_settings.text_long:
    +        type: string
    

    I'm fine with using string here but it implies that the same format is valid for all languages (which makes sense imo).

  2. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -7,12 +7,38 @@ use Drupal\Core\Field\FieldDefinitionInterface;
    +      '#title' => t('Allowed text formats'),
    

    use $this->t()

  3. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -7,12 +7,38 @@ use Drupal\Core\Field\FieldDefinitionInterface;
    +      '#description' => t('Select the allowed text formats. If no formats are selected, all available text formats will be displayed to the user.'),
    

    use $this->t()

aleevas’s picture

The last patch from #145 was rerolled

Status: Needs review » Needs work

The last submitted patch, 152: 784672-152.patch, failed testing. View results

Deno’s picture

This is an excellent idea IMO. On a related note: once this is done, could we "kill" the formatted/unformatted text fields differentiation?

Instead of two field types, we could just have "text" with a list of allowed formatting types. And one of them being the "unformatted".

In that case, it would be possible to change the type of a field from "formatted" to "unformatted" and back easily. Moreover, it would be possible to apply *some* filters even to unformatted text if necessary. "Onomasticon" filter comes to mind. Or the one that recognises URLs in the text and adds links automatically.

hexabinaer’s picture

+1 for Deno's idea. In new projects we are using formatted text fields in most instance where you'd expect a plain text field - mainly (but strongly) for the reason that editors should be able to add language attributes (German has a lot of loan words). The text format selectors cause a lot of clutter.

After all if would be awesome if we could enhance the accessibility on existing sites by allowing language attributes in plain text fields that would never be replaced.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

PhilippVerpoort’s picture

+1 for #154.

And thanks to all for working on this, I'm finding this a really annoying issue.

renguer0’s picture

+1 to #154. I hope that could be merged soon because it's really annoying (I'm using Allowed formats module in order to hide that selector).

AndyF’s picture

Status: Needs work » Needs review
FileSize
22.74 KB
5.91 KB

Thanks all, would be great to get this in! The old patch is directly storing the checkboxes value for allowed formats in the config, eg:

settings:
  allowed_formats:
    basic_html: basic_html
    restricted_html: '0'
    full_html: '0'
    plain_text: '0'

This causes problems with the textfield widget: the allowed format doesn't exist so you get the This field has been disabled because you do not have sufficient permissions to edit it message as a non-admin user. (The textarea widget has an explicit array_filter() which makes it work as expected.)

I've updated the patch to save the allowed formats as an indexed array of selected formats, eg.

settings:
  allowed_formats:
    - basic_html

When I originally saw the symptoms of the problem (but didn't know what was happening under the covers) I tried to update \Drupal\Tests\text\Functional\TextFieldTest::testTextfieldWidgetsAllowedFormats() to get a fail before fixing it. The change didn't detect the problem however because we don't use the UI to create the text field, but I've left it in nonetheless as I think it's still probably useful. Do folk think it's worth updating the test to actually use the UI to create the fields themselves? Thanks!

Status: Needs review » Needs work

The last submitted patch, 159: 784672-159.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

AndyF’s picture

Status: Needs work » Needs review
FileSize
30.86 KB
8.75 KB
  • Address phpcs feedback.
  • Remove use of deprecated functionality in new test.
  • Address some failing tests.
  • I think I found some extra text field config that hadn't been updated to the new schema.

Still todo: fix remaining tests, implement calculateDependencies(), thanks!

The last submitted patch, 159: 784672-159.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

AndyF’s picture

FileSize
31.44 KB
1.08 KB

Guess there's no remaining tests to fix (: I've added the text formats as config dependencies, tho that's not tested. Thanks!

jungle’s picture

jungle’s picture

Issue summary: View changes
FileSize
191.08 KB

Add needs follow-up to the remain tasks section of IS addressing the concern of #154

jungle’s picture

Issue summary: View changes

Make the screenshot of text field types smaller in IS

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Rajab Natshah’s picture

This is a very important feature!!

Thanks all for working on patches and contributed modules
I hope it will get into Drupal 9

To me it feels that a module like Allowed Formats could be added to Drupal 9 core under the same name or under text formats.

dasginganinja’s picture

Is it recommended to use the core patch or the contributed module at this point?
Thanks!

John Pitcairn’s picture

For production sites I would advise using the contrib module rather than patching.

jungle’s picture

Is it recommended to use the core patch or the contributed module at this point?

Re #169, this feature will be in core sooner or later I think, and eventually, it's preferred than the contributed module.

I would suggest using the patch.

  1. Feedback from PROD is welcome and important which might help to improve the patch.
  2. Meanwhile, reviewing the patch would be appreciated if you have time as the current status is NR.

Thanks!

Brendan.Smith’s picture

Version: 9.1.x-dev » 8.9.x-dev

Tested latest patch from comment #163 on v8.9.x of Drupal Core and it works as expected.

apaderno’s picture

Version: 8.9.x-dev » 9.1.x-dev

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

viappidu’s picture

Rework for 9.1.x
Note: [#https://www.drupal.org/node/3129738]
So,

$this->assertFieldByName() --> $this->assertSession()->fieldExists()
$this-> assertNoFieldByName() --> $this->assertSession()->fieldNotExists()

(Sorry for missing interdiff)

viappidu’s picture

FileSize
31.19 KB

Sorry, my bad

Status: Needs review » Needs work

The last submitted patch, 176: 784672-176.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

raman.b’s picture

Status: Needs work » Needs review
FileSize
31.05 KB
2.18 KB

Addressing a few more deprecations

mr.baileys’s picture

Status: Needs review » Needs work

Quick review:

1. After applying the patch and clearing the cache, when going to the Edit page for an existing field (under Manage Fields), a notice is thrown:

Notice: Undefined index: allowed_formats in Drupal\text\Plugin\Field\FieldType\TextItemBase->fieldSettingsForm() (line 35 of core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php).

Drupal\text\Plugin\Field\FieldType\TextItemBase->fieldSettingsForm(Array, Object) (Line: 117)
Drupal\field_ui\Form\FieldConfigEditForm->form(Array, Object) (Line: 106)
Drupal\Core\Entity\EntityForm->buildForm(Array, Object)
call_user_func_array(Array, Array) (Line: 532)
Drupal\Core\Form\FormBuilder->retrieveForm('field_config_edit_form', Object) (Line: 278)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
<snip>

This means we might need an update path for existing config, or at least improve handling of field config if allowed_formats is missing.

2. When you limit the allowed values on a field, you are still able to provide default content using any of the other (disallowed) text formats. For example, I restricted a text field to only allow "Plain text", but provided a default value (<script>alert('Llama');</script>) using "Full HTML". When creating content using this field, the default value shows up converted to the allowed format (<p>&lt;script&gt;alert('Llama');&lt;/script&gt;</p>). It might make sense to provide some validation to ensure the default value can only be saved using one of the allowed formats?

Setting to needs work for the undefined index notice.

minorOffense’s picture

Reroll updating the patch to swap out "assertIdentical" for "assertSame" in one of the tests.

joegraduate’s picture

Status: Needs work » Needs review

Fixed test failures in #180 by adding 'allowed_formats' to field config schema for the editor_test_text_long field plugin used in the failing EditorFileUsageTest.

joegraduate’s picture

Failed to include updated patch.

joegraduate’s picture

Status: Needs review » Needs work

Setting back to "Needs work" because #182 did not address #179.

vakulrai’s picture

Status: Needs work » Needs review
FileSize
32.93 KB
2.1 KB

Added a patch which will take care of point 1 and 2 mentioned in #179.

For point 2 under #179 I have used massageFormValues() method to format the values as per the selected allowed formats.
This code $text = check_markup($values[0]['value'], $format_type) is responsible for restricting any unsupported inline tags to be save while saving the markup.

Please Review!.
Thanks

AndyF’s picture

Status: Needs review » Needs work

Thanks! A small review of #184:

Update path: As we're updating the schema, I think the ideal solution is to add a hook_update_N() that updates the config of text fields where necessary, see eg. field_update_8003() (although that updates field storage config for ER fields, whereas we're interested in the field config for text fields). There's some more details on this page https://www.drupal.org/node/2535454. We'll also want to test it, which should be quite simple for this change: see https://www.drupal.org/docs/8/api/update-api/writing-automated-update-te....

Limiting default value allowed format: Rather than adding code to text area widgets to handle the case of default values, I think it's more appropriate to add validation to the field settings page that prevents the default value having a prohibited text format.

joegraduate’s picture

Status: Needs work » Needs review
FileSize
35.5 KB
4.8 KB

The attached patch is an iteration of #182 that incorporates @AndyF's suggestions from #185:

- Added hook_update_N() function that updates config of existing text fields
- Added a new list class for the text field type plugins (TextFieldItemList) that overrides the Drupal\Core\Field\FieldItemList::defaultValuesFormValidate() method with additional validation logic for the text format input in the default values form within the field settings form.

joegraduate’s picture

Updated version of patch from #186:
- Fixed typo / Cspell error in TextFieldItemList.php
- Added @vakulrai's empty array default fallback (from #184) to TextItemBase::fieldSettingsForm()

Status: Needs review » Needs work

The last submitted patch, 187: 784672-187.patch, failed testing. View results

joegraduate’s picture

Status: Needs work » Needs review
FileSize
36.23 KB
863 bytes

Added back fix for broken tests from #182 that was mistakenly removed.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Joao Sausen’s picture

I tried the patch from #189 on Drupal 9.2.0-beta and got a

The website encountered an unexpected error. Please try again later.
Error: Call to a member function getName() on null in Drupal\text\Plugin\Field\FieldType\TextFieldItemList->defaultValuesFormValidate() (line 19 of core/modules/text/src/Plugin/Field/FieldType/TextFieldItemList.php). 

I think this line:
$field_name = $this->fieldDefinition->getName();
is supposed to be
$field_name = $this->definition->getName();
?
That made it work.

BramDriesen’s picture

Status: Needs review » Needs work

Needs work in that case.

Meenakshi_j’s picture

Fixed the issue.

Meenakshi_j’s picture

Status: Needs work » Needs review
owenbush’s picture

I have tested patch #193 on 9.3.x and it applied cleanly and worked without issue.

PCate’s picture

Status: Needs review » Reviewed & tested by the community

Patch applied cleanly to 9.x and the functionality worked great for restricting formats.

Rinku Jacob 13’s picture

I have tested patch #193 for 9.3.x dev.it applied cleanly thanks @Meenakshi_j

BramDriesen’s picture

@Rinku Jacob 13 please refrain from uploading screenshots of how a patch applies. It adds zero value to the issue. Did you actually test the functionality?

quietone’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

Just wondering what this patch is doing so started to read the patch. Then I noticed that it has an update hook but no test. Tagging Needs Tests and setting to NW for the test. Then I read the patch and noticed a few more things.

  1. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -7,12 +7,66 @@
    +use Drupal\Core\Form\FormStateInterface;
    

    It is much easier to manage if this is added alphabetically.

  2. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -7,12 +7,66 @@
    +   * Ensure the element's value is an indexed array of selected format IDs.
    ...
    +   * This function is assigned as an #element_validate callback in
    

    Not sure why this is two paragraphs and I am not sure if the ::fieldSettingsForm will be displayed as a link on api.drupal.org. I think this will be better.

    Ensure the element's value is an indexed array of selected format IDs. This function is assigned as an #element_validate callback.
    
    @see static::fieldSettingsForm().
  3. +++ b/core/modules/text/text.install
    @@ -0,0 +1,36 @@
    +function text_update_9201() {
    

    This needs an test. See Writing Automated Update Tests for Drupal 8.

  4. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextFieldItemList.php
    @@ -0,0 +1,34 @@
    + * Represents a configurable entity text field.
    

    This looks like it is a list not a 'text field'. How about 'Defines an item list class for text fields.', which I got from looking at CommentFieldItemList.php.

  5. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextFieldItemList.php
    @@ -0,0 +1,34 @@
    +        $submitted_values = $form_state->getValue(['default_value_input', $field_name]);
    

    Expand the array on multiple lines.

  6. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextFieldItemList.php
    @@ -0,0 +1,34 @@
    +              t("The selected text format is not allowed.")
    

    I reckon t should be $this->t.

quietone’s picture

I should add that I have not done a thorough review, this is outside my area and I was mostly reading the comments.

vsujeetkumar’s picture

Status: Needs work » Needs review
FileSize
36.28 KB
2.49 KB

Hi, I have worked on #199 and fixed the 1, 2, 4, 5, 6 issues. Test case needs to be written for 199.3. Looking for it.

BramDriesen’s picture

Status: Needs review » Needs work

Putting it back to needs work for the test cases. Good to see that the test run passed successfully :-)

Eduardo Morales Alberti’s picture

I am interested in it, but why do not you create a merge request? It is easiest to review, merge and contribute for the maintainer.
I would do it, but I do not want authoring.

smustgrave’s picture

+1 for this feature to be included

Patch in #201 seems to work great.

mkimmet’s picture

Applied patch in #201 and it seems to work. However, I noticed a file, TextFieldItemList.php, in 2 extra places in my drupal install at:

- /web/core/b/core/modules/text/src/Plugin/Field/FieldType
- /web/core/core/modules/text/src/Plugin/Field/FieldType

Is that to be expected?

larowlan’s picture

  1. +++ b/core/modules/editor/tests/modules/config/schema/editor_test.schema.yml
    @@ -15,3 +15,13 @@ editor.settings.trex:
    +field.field_settings.editor_test_text_long:
    +  label: 'Filter test text (formatted, long) settings'
    +  type: mapping
    +  mapping:
    +    allowed_formats:
    +      type: sequence
    +      label: 'Allowed text formats'
    +      sequence:
    +        type: string
    

    this should just defer to the parent, e.g.
    type: field.field_settings.text to avoid the duplication

  2. +++ b/core/modules/text/config/schema/text.schema.yml
    @@ -38,6 +44,12 @@ field.storage_settings.text_long:
    +  mapping:
    +    allowed_formats:
    +      type: sequence
    +      label: 'Allowed text formats'
    +      sequence:
    +        type: string
    

    same here, this should defer to the parent

  3. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextFieldItemList.php
    @@ -0,0 +1,37 @@
    +    if ($allowed_formats = $this->getSetting('allowed_formats')) {
    +      if (!empty($allowed_formats)) {
    +        $field_name = $this->definition->getName();
    +        $submitted_values = $form_state->getValue([
    

    there's no test coverage for this yet

  4. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextFieldItemList.php
    @@ -0,0 +1,37 @@
    +          if (!in_array($value['format'], $allowed_formats)) {
    

    we should use the third argument to in_array when comparing strings

  5. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -13,6 +14,58 @@
    +   * Ensure the element's value is an indexed array of selected format IDs. This function is assigned as an #element_validate callback.
    

    nit, > 80 chars here

  6. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -13,6 +14,58 @@
    +  public static function validateAllowedFormats(array &$element, FormStateInterface $form_state) {
    +    $value = array_values(array_filter($element['#value']));
    

    there's no test coverage for this, as we're setting the allowed formats using the API in the test, not via the UI

  7. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -13,6 +14,58 @@
    +  public static function calculateDependencies(FieldDefinitionInterface $field_definition) {
    +    // Add explicitly allowed formats as config dependencies.
    +    $dependencies = parent::calculateDependencies($field_definition);
    

    we need a corresponding `onDependencyRemoval` to go with this so that removing the filter format doesn't result in the field being deleted.

    And test coverage for that

  8. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -13,6 +14,58 @@
    +      return 'filter.format.' . $format_id;
    +    }, $field_definition->getSetting('allowed_formats'));
    +    $config = $dependencies['config'] ?? [];
    +    $dependencies['config'] = array_merge($config, $format_dependencies);
    

    there's no test coverage for the dependencies being added yet, can we get that added (kernel test would be best)

  9. +++ b/core/modules/text/text.install
    @@ -0,0 +1,36 @@
    +  $config = \Drupal::configFactory();
    +
    +  /** @var \Drupal\Core\Field\FieldTypePluginManager $field_type_manager */
    +  $field_type_manager = \Drupal::service('plugin.manager.field.field_type');
    +
    +  // Iterate over all fields.
    +  foreach ($config->listAll('field.field.') as $field_id) {
    +    $field = $config->getEditable($field_id);
    +    $class = $field_type_manager->getPluginClass($field->get('field_type'));
    +
    +    // Deal only with text fields and descendants.
    +    if ($class == TextItemBase::class || is_subclass_of($class, TextItemBase::class)) {
    +      // Get the existing allowed_formats setting.
    +      $allowed_formats = $field->get('settings.allowed_formats');
    +      if (!is_array($allowed_formats) && empty($allowed_formats)) {
    

    we have a config entity updater class now that we can use here

larowlan’s picture

Category: Task » Feature request

This is a feature request in my opinion.

xeM8VfDh’s picture

I found this issue via: https://drupal.stackexchange.com/questions/228811/how-to-enable-plain-te...

I see it's still in progress, after 11 years. Though, it does seem to be mostly done, minus test case coverage. Any hope on the test coverage mentioned in #201? Is that the only think holding this back at the moment?

Also, with the aforementioned patch, would changing a Basic HTML field that has lots of records, some with HTML tags, convert said data to raw text (including html tags), or would the tags be stripped out after switching the format type?

Thanks for the long journey of work to all those involved!

darvanen’s picture

There is always hope if the issue is not "closed (won't fix)" :)

In addition to the test coverage there is a review from a core committer at #206 that will need to be addressed before this goes RTBC let alone back to Needs Review.

I encourage you to give it a go!

xeM8VfDh’s picture

thanks @darvanen!

error84’s picture

In need for a fix for this 12 year old issue now?

The answer with the hook_field_widget_form_alter() fix on this page https://drupal.stackexchange.com/questions/239068/how-do-i-force-a-text-... worked excellent for me. It's relatively simple and does not require an additional module. And it works for BaseFieldDefinitions too (where the Allowed Formats module does not).

It's a workaround still, so I wish this issue here got fixed so I could fix it decently :) ...

xeM8VfDh’s picture

thanks @error84

vikashsoni’s picture

FileSize
201.82 KB
139.09 KB
184.34 KB

Unable to apply patch in drupal-9.3.x-dev Giving error while going to apply patch
Needs to Re-roll

xeM8VfDh’s picture

this may have been discussed, but for people wanting a quick fix, I've realized I can just use the "strip HTML tags" option when pulling the field in the view to force this type of behavior.

quietone’s picture

@vikashsoni, Adding screenshots of your terminal do not advance this issue. Reading the issue you will see that a few comments above there are changes asked for in the patch. Therefore removing credit per How is credit granted for Drupal core issues.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

MaxMendez’s picture

FileSize
36.16 KB
2.49 KB

This is not and advance about the changes requested on #206, but fixed 9.3.x. compatibility.

vdsh’s picture

Here is the patch 201 rerolled for the 9.3.0 version. It's just a reroll, I haven't reviewed feedbacks from #206

Edit: Sorry MaxMendez, I believe we have the same patch, I didn't refresh the page before working on the patch to reroll for 9.3

DanielVeza’s picture

Took the patch from #217 & addressed most points from #206.

Still a WIP patch, points 3 & 7 need adressing.

larowlan’s picture

Status: Needs work » Needs review
larowlan’s picture

Status: Needs review » Needs work

Back to needs work for this and the #206.3 and #206.7

  1. +++ b/core/modules/text/tests/src/Functional/TextFieldTest.php
    @@ -173,6 +183,7 @@
    +    $format1Id = $format1->id();
    

    nit: this should probably match existing naming patterns, e.g. $format1_id (snake case, not camel case)

  2. +++ b/core/modules/text/tests/src/Functional/TextFieldTest.php
    @@ -226,10 +237,16 @@
    +    //$this->drupalGet('entity_test/structure/entity_test/fields/add-field');
    

    is this intentionally commented? can be removed?

larowlan’s picture

Issue summary: View changes

Adding another task here - we need a validation constraint to ensure that you can't set an invalid format over JSON:API/Rest

andypost’s picture

Related issues: +#2824979: The DataDefinitionInterface is missing setConstraints method

Added #2824979: The DataDefinitionInterface is missing setConstraints method as related because it could help to simplify validation

uberhacker’s picture

I can confirm the patch in https://www.drupal.org/project/drupal/issues/784672#comment-14339340 works. Great effort @MaxMendez!

smustgrave’s picture

Took the patch from #219 and addressed the 2 bullets from #221

ravi.shankar’s picture

FileSize
1.12 KB

Added interdiff of patch #219 and #225.

ravi.shankar’s picture

Fixed Drupal CS issues of patch #225.

apaderno’s picture

Status: Needs work » Needs review
dimr’s picture

Status: Needs review » Reviewed & tested by the community

It is working as expected, thanks!

smustgrave’s picture

Status: Reviewed & tested by the community » Needs work

This patch causes an issue when uninstalling linkchecker module https://www.drupal.org/project/linkchecker/issues/3280409

Not sure if it will break other modules.

smustgrave’s picture

Status: Needs work » Needs review
FileSize
38.3 KB
1.64 KB

Adding a check

Status: Needs review » Needs work

The last submitted patch, 231: 784672-231.patch, failed testing. View results

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

larowlan’s picture

Status: Needs work » Needs review
FileSize
38.91 KB

Reroll for 9.4.x, doesn't include #231

Status: Needs review » Needs work

The last submitted patch, 234: 784672-234.patch, failed testing. View results

smustgrave’s picture

Rerolled with #231. Not sure about the failing test. When I run locally no issues.

smustgrave’s picture

FileSize
36.92 KB
smustgrave’s picture

Looking at the console for dispatcher I expect #237 to fail. Seeing almost 100 failures across random modules now.

test runner returned a non-zero error code (2).

smustgrave’s picture

I stand corrected!

Berdir’s picture

> Exception: Error: Class "\Drupal\text\Plugin\Field\FieldType\TextFieldItemList" not found

is the error.

This class is not in the patch, maybe you forgot to add it?

Build successful actually means that it fails so badly that it can't display the errors.

smustgrave’s picture

I’ll take a look!

smustgrave’s picture

FileSize
39.37 KB

Not sure how I screwed that up but should be fixed.

Status: Needs review » Needs work

The last submitted patch, 242: 784672-242.patch, failed testing. View results

smustgrave’s picture

Status: Needs work » Needs review
FileSize
38.83 KB
724 bytes

Think I found it. I'm still on php8 which is why the error wasn't appearing for me.

smustgrave’s picture

Sweet! Ready for review

Luke.Leber’s picture

Overall, looks great! Nice touch on calling array_values in the validate callback. Failing to do so has bitten me quite a few times.

Just a couple of minor things.

1. Should we add a blurb of text to the widget settings summary?

2. We can probably save the test bot a bit of time here by creating the text formats via API here.

@@ -154,13 +164,107 @@ class TextFieldTest extends StringFieldTest {
     $this->_testTextfieldWidgetsFormatted('text_long', 'text_textarea');
   }
 
+  /**
+   * Test widgets for fields with selected allowed formats.
+   */
+  public function testTextfieldWidgetsAllowedFormats() {
+    // Create one text format.
+    $this->drupalLogin($this->adminUser);
+    $edit = [
+      'format' => mb_strtolower($this->randomMachineName()),
+      'name' => $this->randomMachineName(),
+    ];
+    $this->drupalGet('admin/config/content/formats/add');
+    $this->submitForm($edit, 'Save configuration');
Luke.Leber’s picture

Status: Needs review » Needs work

It looks like Lee's point in #222 still needs to be addressed, setting back to NW.

smustgrave’s picture

#222

we need a validation constraint to ensure that you can't set an invalid format over JSON:API/Rest

Anyone know how to accomplish this?

larowlan’s picture

We might be able to add an additional constraint plugin to \Drupal\text\Plugin\Field\FieldType\TextItem::getConstraints

You can see there its already using the 'ComplexData' plugin to add a 'Length' validation plugin on the 'value' property.

We might be able to extend that to the 'format' property and add the 'AllowedValues' validation plugin

Something like

if ($formats = $this->getSetting('allowed_formats')) {
      $constraints[] = $constraint_manager->create('ComplexData', [
        'format' => [
          'AllowedValues' => [
            'choices' => $formats,
          ],
        ],
      ]);
    }

But I suspect adding two 'ComplexData' constraints is not efficient, and we should be able to add just one with both the 'value' and 'format' keys. That would probably entail building up an $options array for the second argument that was conditional on both the max length and allowed format settings.

This is further complicated by the fact that allowed_formats is on TextItemBase, while max_length is on TextItem, so you may need to do some parent child wrangling - ie add the allowed format constraint in TextItemBase and then add the max_length one on top of it in TextItem if it exists, if not, add a new one.

smustgrave’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
1.63 KB
40.25 KB

Took a shot at #249

smustgrave’s picture

Status: Needs review » Needs work

The last submitted patch, 251: 784672-251.patch, failed testing. View results

smustgrave’s picture

Status: Needs work » Needs review
FileSize
3.92 KB
41.61 KB
larowlan’s picture

larowlan’s picture

Status: Needs review » Needs work

Great work @smustgrave - here's a few observations

  1. +++ b/core/modules/editor/tests/modules/config/schema/editor_test.schema.yml
    @@ -15,3 +15,7 @@ editor.settings.trex:
    +
    +field.field_settings.editor_test_text_long:
    +  label: 'Filter test text (formatted, long) settings'
    +  type: field.field_settings.text
    

    is this an existing bug that this is missing?

    should we split that to its own issue?

  2. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItem.php
    @@ -61,7 +62,11 @@ public function getConstraints() {
    -            'maxMessage' => t('%name: the text may not be longer than @max characters.', ['%name' => $this->getFieldDefinition()->getLabel(), '@max' => $max_length]),
    +            'maxMessage' => t('%name: the text may not be longer than @max characters.', [
    +              '%name' => $this->getFieldDefinition()
    +                ->getLabel(),
    +              '@max' => $max_length,
    +            ]),
               ],
    

    this looks to be an out of scope change

  3. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -13,6 +14,64 @@
    +    $value = array_values(array_filter($element['#value']));
    

    should this use $form_state->getValue($element['#parents']) instead of $element['#value']?
    I'm not sure which is more correct

  4. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -13,6 +14,64 @@
    +  public static function calculateDependencies(FieldDefinitionInterface $field_definition) {
    

    I think we also need an onDependencyRemoval implementation here, as removing a filter format shouldn't delete a field, which in turn could delete a view... 😬

  5. +++ b/core/modules/text/tests/src/Functional/TextFieldTest.php
    @@ -154,13 +164,107 @@ public function testTextfieldWidgetsFormatted() {
    +    // Create one text format.
    +    $this->drupalLogin($this->adminUser);
    +    $edit = [
    +      'format' => mb_strtolower($this->randomMachineName()),
    +      'name' => $this->randomMachineName(),
    +    ];
    +    $this->drupalGet('admin/config/content/formats/add');
    +    $this->submitForm($edit, 'Save configuration');
    +    filter_formats_reset();
    +    /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */
    +    $entity_type_manager = $this->container->get('entity_type.manager');
    +    $filter_format_storage = $entity_type_manager
    +      ->getStorage('filter_format');
    +    /** @var \Drupal\filter\Entity\FilterFormat $format1 */
    +    $format1 = $filter_format_storage->load($edit['format']);
    +    $format1_id = $format1->id();
    +
    +    // Create a second text format.
    +    $edit = [
    +      'format' => mb_strtolower($this->randomMachineName()),
    +      'name' => $this->randomMachineName(),
    +    ];
    +    $this->drupalGet('admin/config/content/formats/add');
    +    $this->submitForm($edit, 'Save configuration');
    +    filter_formats_reset();
    +    /** @var \Drupal\filter\Entity\FilterFormat $format2 */
    +    $format2 = $filter_format_storage->load($edit['format']);
    

    We don't need to do this over HTTP, let's just do $format1 = FilterFormat::create() - we're not testing the filter format edit form here, so we may as well use the more efficient approach

  6. +++ b/core/modules/text/tests/src/Functional/TextFieldTest.php
    @@ -154,13 +164,107 @@ public function testTextfieldWidgetsFormatted() {
    +    $this->drupalGet('entity_test/add');
    +    // We should see the 'format' selector again.
    +    $this->assertSession()->fieldExists("{$field_name}[0][value]", NULL);
    +    $this->assertSession()->optionExists("{$field_name}[0][format]", $format1->id());
    +    $this->assertSession()->optionExists("{$field_name}[0][format]", $format2->id());
    

    I can't see a test for the validation constraint.

    We could add it here while we have all the scaffolding done, or we could add a separate kernel test.

    We should just set the format to an invalid value via $entity->set() and then call $entity->validate() and make sure the violation is returned

  7. +++ b/core/modules/text/tests/src/Kernel/TextItemBaseTest.php
    @@ -57,4 +60,42 @@ public function providerTextFieldSampleValue() {
    +    ], $field->getDependencies());
    

    We should add a test for onDependencyRemoval here too, given we've already got all the parts in place

smustgrave’s picture

FileSize
4.1 KB
40.89 KB

#255
1.

is this an existing bug that this is missing?

should we split that to its own issue?

Not sure I follow this one?

2. Actually was already there just looks like it got formatted differently. Probably from an IDE.

3. Addressed

4. Not 100% how to best address this. I tested manually by adding a format to a field, deleted the format, and the field was untouched. But now appeared empty because it was hanging on to a format that didn't exist.

5. Addressed

6. Address in a kernel test

7. Same as #4

Berdir’s picture

  1. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -92,4 +151,24 @@ public static function generateSampleValue(FieldDefinitionInterface $field_defin
    +   * {@inheritdoc}
    +   */
    +  public function getConstraints() {
    +    $constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager();
    +    $constraints = parent::getConstraints();
    +
    +    if ($formats = $this->getSetting('allowed_formats')) {
    +      $constraints[] = $constraint_manager->create('ComplexData', [
    +        'format' => [
    +          'AllowedValues' => [
    +            'choices' => $formats,
    +          ],
    +        ],
    +      ]);
    +    }
    +
    +    return $constraints;
    

    Do we really need a new constraint for this?

    formats are already validated by \Drupal\filter\Plugin\DataType\FilterFormat::getSettableOptions(), can't we just filter down that list, we can access the field item through $this->getParent(). That is from \Drupal\Core\TypedData\OptionsProviderInterface and a constraint is automatically added for it in \Drupal\Core\TypedData\TypedDataManager::getDefaultConstraints().

  2. +++ b/core/modules/text/text.install
    @@ -0,0 +1,31 @@
    +/**
    + * Add allowed_formats setting to existing text fields.
    + */
    +function text_update_9201(&$sandbox) {
    +  \Drupal::classResolver(ConfigEntityUpdater::class)
    +    ->update($sandbox, 'field_config', function (FieldConfigInterface $field_config) {
    

    the update function number will need to change, this is 10.1 at this point. also not sure if it should be a post update?

larowlan’s picture

Do we really need a new constraint for this?

formats are already validated by \Drupal\filter\Plugin\DataType\FilterFormat::getSettableOptions(), can't we just filter down that list, we can access the field item through $this->getParent().

Isn't embedding knowledge of the settings of a specific field-type in a data-type a bit of a code smell? Not all field-types that use filter format data-types will necessarily have an allowed format setting.

Berdir’s picture

Fair point.

Most computed data types depend on their parent and settings explicitly while non-computed usually don't.

But we could make it an explicit setting and set it in \Drupal\text\Plugin\Field\FieldType\TextItemBase::propertyDefinitions(), see \Drupal\Core\Field\Plugin\Field\FieldType\StringItemBase::propertyDefinitions for an example.

smustgrave’s picture

So what's the verdict regarding #258 and #259

smustgrave’s picture

Following up on the verdict between #258 and #259?

apaderno’s picture

Comment #258 says that a data type class should not have settings for a field type; comment #259 agrees on that and suggests using a field type property that is set in \Drupal\text\Plugin\Field\FieldType\TextItemBase::propertyDefinitions().

smustgrave’s picture

Status: Needs work » Needs review
FileSize
4.75 KB
40.7 KB

Took a shot at addressing #259.

Now question https://www.drupal.org/project/drupal/issues/1278886 is about saving default formatters. Would it be out of the scope of this ticket to make the allowed formatters be a dragable ordered field? That would cover the use case of 1278886

But don't want to delay this ticket.

smustgrave’s picture

The only different between the D9 and D10 patch is the D9 is patching some ckeditor tests that are removing in D10

andypost’s picture

Status: Needs review » Needs work
+++ b/core/modules/text/text.install
@@ -0,0 +1,31 @@
+function text_update_10101(&$sandbox) {

it should be hook_post_update_NAME() as there's only configuration changes

It may help to keep 9.5.x and 10.1.x similar

smustgrave’s picture

Fixed the test failure. Was left over from the constraint I removed.

Addressed #265

andypost’s picture

Version: 9.5.x-dev » 10.1.x-dev

It looks mostly ready, just as feature for 10.1.x

smustgrave’s picture

Would agree. Seems too late for D9.

smustgrave’s picture

bumping again. Hoping to get this in for 10.1

DanielVeza’s picture

Issue tags: +DrupalSouth

Couple of Qs from a code review.

  1. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextFieldItemList.php
    @@ -0,0 +1,35 @@
    +            "default_value_input][{$field_name}][{$delta}][format",
    

    This looks like it has unopened and unclosed [ and ]. Is that correct?

  2. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextItemBase.php
    @@ -13,6 +14,64 @@
    +    else {
    +      $format_dependencies = [];
    +    }
    

    Can we remove this else and set $format_dependencies = []; above the if statement?

darvanen’s picture

#270.1 - Yes that's correct, it's a lovely Drupalism isn't it? It's documented under "Parameters" here.

#270.2 - Agree, new patches attached.

Status: Needs review » Needs work

The last submitted patch, 271: 784672-271-D10.patch, failed testing. View results

smustgrave’s picture

Status: Needs work » Needs review

Must of been a random failure I’m seeing all green so moving back to NR

DanielVeza’s picture

Status: Needs review » Reviewed & tested by the community

Changes look good and tests are green :)

@darvanen and I went through this at DrupalSouth. I think this can be RTBC'd now

xeM8VfDh’s picture

Very cool! A long journey may be reaching the finish line! Well done everyone who stuck with it!

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs change record, +Needs release note
  1. A lot of people will use this feature - nice! We need a change record and release note in the issue summary to inform people about it.
  2. +++ b/core/modules/text/text.post_update.php
    @@ -14,3 +18,24 @@ function text_removed_post_updates() {
    +/**
    + * Add allowed_formats setting to existing text fields.
    + */
    +function test_post_update_allowed_formats(&$sandbox = NULL) {
    

    Should be called text_... which would also indicate this update function is not tested.

  3. +++ b/core/modules/text/text.post_update.php
    @@ -14,3 +18,24 @@ function text_removed_post_updates() {
    +        if (!is_array($allowed_formats) && empty($allowed_formats)) {
    +          // Save default value if existing value not present.
    +          $field_config->set('settings.allowed_formats', []);
    +        }
    +        return TRUE;
    

    Only needs to return TRUE if we set the field to a value.

BramDriesen’s picture

Very early draft added here: https://www.drupal.org/node/3318572 Feel free to edit. I'll enrich it when I find time :) leaving the tag for now

smustgrave’s picture

Status: Needs work » Needs review
FileSize
1.6 KB
43.01 KB

Addressed points in 276

apaderno’s picture

Status: Needs review » Needs work
smustgrave’s picture

Status: Needs work » Needs review
FileSize
744 bytes
42.98 KB

This should be better.

alexpott’s picture

What happens to existing content if you limit formats after the fact and it uses and format that's not allowed? In that case the node would use the format until it is edited... but then then when it is the format will change. That might be very problematic. We need to think about this situation. And we should have test coverage of this.

Berdir’s picture

We've seen that case in production with contrib, you are then forced to pick a new format, I don't think that's very problematic. But yes, test coverage makes sense.

There's one thing I'm wondering about. Beside this feature, the allowed_formats contrib module also has settings to hide the lengthy text format explanations, a feature that we use often. I'm a bit unsure how to handle that, for now you'd still need to use the contrib module for that, so it would require a new major version with a (post) update function and just those two settings? definitely don't want to delay this issue even further, maybe a follow-up that would allow us to move those into the same minor version?

Luke.Leber’s picture

We've seen that case in production with contrib, you are then forced to pick a new format, I don't think that's very problematic.

We just recently ran into this very same thing, only in our case it was with over 5,800 custom block instances across some 300 layout-overridable enabled node-like entities!

We ended up writing a post-update hook to batch-switch the formats over. Otherwise, it could have very well ended up a weird quirk that would have lived for the next decade.

At the very least, I think we should put a warning message up on the UI that describes this behavior if an allowed format is to be removed. It really caught us off-guard at the last minute.

Luke.Leber’s picture

This might be overkill, but I'll just throw out that I absolutely love the UX for text-list field storage settings which won't let an allowed value be removed if there are any references to it that still exist (current or in revision history). 👨‍🔬

smustgrave’s picture

With regards to the concern of this patch just my 2 cents.

If you want to use it for existing fields that would mean you want to limit content that currently is being let through. And if it removes content that was there, I would assume the site admin made the decision they don't want that kind of content allowed anymore for that specific field. So asking the editors to choose an approved editor makes sense to me.

If you don't want to limit your text fields and leave your fields as is, you can do that too.

I see this as a huge improvement to help limit the kind of content users can put in. Example a card body field I may not want to allow tables or embeds. So really hope this feature can make it in.

larowlan’s picture

Issue summary: View changes
Status: Needs review » Needs work

So there are two remaining issues here

1) Create a follow up for #282 to look to add the 'hide filter tips' option like the contrib module
2) Add test coverage for an existing item that has a non allowed format, we want to test the content still outputs with the old format, but that on edit the new format is applied
3) Add a follow-up to discuss #154

Updated the issue summary

Code review:

  1. +++ b/core/modules/text/src/Plugin/Field/FieldType/TextWithSummaryItem.php
    @@ -87,7 +88,7 @@ public function isEmpty() {
    diff --git a/core/modules/text/src/Plugin/Field/FieldType/TextWithSummaryItem.php.orig b/core/modules/text/src/Plugin/Field/FieldType/TextWithSummaryItem.php.orig
    
    diff --git a/core/modules/text/src/Plugin/Field/FieldType/TextWithSummaryItem.php.orig b/core/modules/text/src/Plugin/Field/FieldType/TextWithSummaryItem.php.orig
    new file mode 100644
    
    new file mode 100644
    index 0000000000..9437c381fc
    
    index 0000000000..9437c381fc
    --- /dev/null
    
    --- /dev/null
    +++ b/core/modules/text/src/Plugin/Field/FieldType/TextWithSummaryItem.php.orig
    
    +++ b/core/modules/text/src/Plugin/Field/FieldType/TextWithSummaryItem.php.orig
    +++ b/core/modules/text/src/Plugin/Field/FieldType/TextWithSummaryItem.php.orig
    @@ -0,0 +1,128 @@
    

    there's a patch reject file here

  2. +++ b/core/modules/text/tests/src/Functional/TextFieldTest.php
    @@ -21,6 +21,13 @@ class TextFieldTest extends StringFieldTest {
    +  /**
    +   * Modules to enable.
    +   *
    +   * @var array
    +   */
    

    🧐 ubernit: we can use {@inheritdoc} here

  3. +++ b/core/modules/text/tests/src/Functional/TextFieldTest.php
    @@ -157,13 +167,94 @@ public function testTextfieldWidgetsFormatted() {
    +    $this->assertSession()->optionExists("{$field_name}[0][format]", $format1->id());
    +    $this->assertSession()->optionExists("{$field_name}[0][format]", $format2->id());
    

    should we add a third format in the setup and assert it doesn't exist here?

  4. +++ b/core/modules/text/tests/src/Kernel/TextWithSummaryItemTest.php
    @@ -67,7 +67,7 @@ public function testCrudAndUpdate() {
    -    $entity->summary_field->format = NULL;
    +    $entity->summary_field->format = 'plain_text';
         $entity->name->value = $this->randomMachineName();
         $entity->save();
     
    @@ -76,7 +76,7 @@ public function testCrudAndUpdate() {
    
    @@ -76,7 +76,7 @@ public function testCrudAndUpdate() {
         $this->assertInstanceOf(FieldItemInterface::class, $entity->summary_field[0]);
         $this->assertEquals($value, $entity->summary_field->value);
         $this->assertEquals($summary, $entity->summary_field->summary);
    -    $this->assertNull($entity->summary_field->format);
    +    $this->assertEquals('plain_text', $entity->summary_field->format);
    

    are these changes needed? these are for security sake to ensure if there's no format it falls back to plain text.

    E.g. a migration might set a value but not a format

    We'd need to keep this test or some form of it for security sake

  5. +++ b/core/modules/text/text.post_update.php
    @@ -14,3 +18,24 @@ function text_removed_post_updates() {
    +      if ($class == TextItemBase::class || is_subclass_of($class, TextItemBase::class)) {
    

    nit: we can simplify this to

    if (is_a($class, TextItemBase::class, TRUE))

  6. +++ b/core/modules/text/text.post_update.php
    @@ -14,3 +18,24 @@ function text_removed_post_updates() {
    +        if (!is_array($allowed_formats) && empty($allowed_formats)) {
    +          // Save default value if existing value not present.
    

    devil's advocate, should we look for allowed formats third party settings here and base the default value off that?

    it would be a break from tradition to special case a contrib module but it might smooth the update path?

We're using a flavour of this patch in projects instead of the contrib module, so very keen to see it land in 10.1 🤞

smustgrave’s picture

Status: Needs work » Needs review
Issue tags: -Needs change record
FileSize
10.39 KB
39.92 KB

Opened up follow up tickets per #286.

Added additional test covered to address #2

For the code review addressed 1-5

For 6 not sure what to do for that.

Also see there is a CR started.

larowlan’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs release note +10.1.0 release highlights
Related issues: +#2413335: Expose an option to hide the text format information of textarea fields

Added a release note, updated the follow up

Re-reviewed the changes in #287, thanks for the new test coverage @smustgrave, I think that addresses the question from @alexpott #281

I think this is ready. Thanks everyone who's hung in here this long.

I've updated the issue summary to remove the remaining tasks

alexpott’s picture

Sorted out issue credit. I've tried to credit everyone who contributed a comment or a patch that moved the issue on.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: -Needs backport to D7

Committed 82576b6002 and pushed to 10.1.x. Thanks!

  • alexpott committed 82576b6 on 10.1.x
    Issue #784672 by smustgrave, floretan, lokapujya, joegraduate,...
andypost’s picture

It needs to update CR with example - great feature but too short

BramDriesen’s picture

Yes correct, I drafted the CR but didn't have the time yet to add an example.

alexpott’s picture

Luke.Leber’s picture

Can we add a blurb about what the upgrade path from contrib allowed_formats might look like? Any outstanding blockers or lack of feature parity for site builders to consider?

BramDriesen’s picture

RE #292 I Updated the CR with a field API example and a screenshot of the settings screen.

andypost’s picture

@BramDriesen thank you! it much clear now

smustgrave’s picture

Congrats everyone for this one landing! Already got ideas for this feature on projects.

Berdir’s picture

> Can we add a blurb about what the upgrade path from contrib allowed_formats might look like?

There is none yet. That's something the contrib module needs to handle, typically be creating a 2.x release that requires 10.1 and includes an update function that moves the config over to the core settings structure. Created #3324446: Allowed formats are in Drupal 10.1 now, add an upgrade path for taht.

Would love to se #3323007: Add an option to 'hide filter tips' on text fields get into 10.1 as well, thanks for creating the issue, with that, the contrib module could then be removed, otherwise you'd still need it if you rely on that setting. Thanks for creating the follow-up, I'll try to help review if someone wants to work on that?

ressa’s picture

This is great, thanks everyone for working on it since April 2010! Here's the Change record -- I scanned the last few issues, but only found it after searching on the page for change record: Text fields can enforce a specific text format.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

s_leu’s picture

FileSize
39.45 KB

Here yet a re-roll against latest 9.5.x as none of the existing patches is applying anymore there.

jksloan2974’s picture

Works on 9.5.1

vistree’s picture

Patch from #302 works on 9.5.3

a.dmitriiev’s picture

Re-roll for Drupal 10.0.7, just so that it still can be applied

W01F’s picture

Noting that this change doesn't seem to apply for default taxonomy description fields. It doesn't appear you can limit the allowed formats. I think this issue may also be related - https://www.drupal.org/project/drupal/issues/3106303.

steveoriol’s picture

Patch from #302 works on 9.5.9 but break the site with D9.5.10...

This is the Apache2 error log :

AH01071: Got error 'PHP message: Error: Class "
\\Drupal\\text\\Plugin\\Field\\FieldType\\TextFieldItemList" not found in /var/www/drupalwebsite/web/core/lib/Drupal/Core/TypedData/TypedDataManager.php on line 91 
#0 /var/www/drupalwebsite/web/core/lib/Drupal/Core/TypedData/TypedDataManager.php(103): Drupal\\Core\\TypedData\\TypedDataManager->createInstance()\n#1 /var/www/drupalwebsite/web/core/lib/Drupal/Core/TypedData/TypedDataManager.php(200): Drupal\\Core\\TypedData\\TypedDataManager->create()\n#2 /var/www/drupalwebsite/web/core/lib/Drupal/Core/Field/FieldTypePluginManager.php(74): Drupal\\Core\\TypedData\\TypedDataManager->getPropertyInstance()\n#3 /var/www/drupalwebsite/web/core/lib/Drupal/Core/Entity/ContentEntityBase.php(604): Drupal\\Core\\Field\\FieldTypePluginManager->createFieldItemList()\n#4 /var/www/drupalwebsite/web/core/lib/Drupal/Core/Entity/ContentEntityBase.php(568): Drupal\\Core\\Entity\\ContentEntityBase->getTranslatedField()\n#5 /var/www/drupalwebsite/web/core/lib/Drupal/Core/Entity/EntityViewBui...'
djac’s picture

Patch from #302 is working as expected in our D9 (9.5.10) environment.

@steveoriol perhaps you can include some information about your field setup and steps to reproduce the error you're encountering?

Ncchenm’s picture

Has anybody encountered this error ?
I ran into this error everytime while I trying to access the front page on my Drupal 10.1.6 site. It's seen to be the same error with #307... Any suggestions? many thanks!!!

Error: Class "\Drupal\text\Plugin\Field\FieldType\TextFieldItemList" not found in Drupal\Core\TypedData\TypedDataManager->createInstance() (line 91 of /userap/httpd/htdocs/drupal/web/core/lib/Drupal/Core/TypedData/TypedDataManager.php) #0 /userap/httpd/htdocs/drupal/web/core/lib/Drupal/Core/TypedData/TypedDataManager.php(103): Drupal\Core\TypedData\TypedDataManager->createInstance('list', Array)