Quantcast
Channel: Issues for Drupal core
Viewing all 293247 articles
Browse latest View live

Invalid config structures can result in exceptions when saving a config entity

$
0
0

Problem/Motivation

Pulled from original post

So far, it was always a property inside a views filter, where it expects value to be a string but it's an array.

Pulled from #44

This is specific to views because views defines generic default schema for certain things, like filter plugin values. The config schema system can handle missing config schema, what it can't deal with is mismatches where it's expecting a scalar but actually receives a mapping/array/complex data

Steps to reproduce

Generate a mismatch config schema and try to save it.

Proposed resolution

In the save function for Config.php wrap the code that attempts castValue() in a try/catch block. And loop through the data vs calling it as is.
Log issues vs throw error

Remaining tasks

Update issue summary

User interface changes

NA

API changes

NA

Data model changes

NA

Release notes snippet

NA

Original Post

I had multiple 8.4 upgrades failing with an error like this so far:

#0  Drupal\Core\Config\Schema\ArrayElement->get() called at [/core/lib/Drupal/Core/Config/StorableConfigBase.php:179]
#1  Drupal\Core\Config\StorableConfigBase->castValue() called at [/core/lib/Drupal/Core/Config/StorableConfigBase.php:211]
#2  Drupal\Core\Config\StorableConfigBase->castValue() called at [/core/lib/Drupal/Core/Config/StorableConfigBase.php:211]
#3  Drupal\Core\Config\StorableConfigBase->castValue() called at [/core/lib/Drupal/Core/Config/StorableConfigBase.php:211]
#4  Drupal\Core\Config\StorableConfigBase->castValue() called at [/core/lib/Drupal/Core/Config/StorableConfigBase.php:211]
#5  Drupal\Core\Config\StorableConfigBase->castValue() called at [/core/lib/Drupal/Core/Config/StorableConfigBase.php:211]
#6  Drupal\Core\Config\StorableConfigBase->castValue() called at [/core/lib/Drupal/Core/Config/StorableConfigBase.php:211]
#7  Drupal\Core\Config\StorableConfigBase->castValue() called at [/core/lib/Drupal/Core/Config/Config.php:212]
#8  Drupal\Core\Config\Config->save() called at [/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php:280]
#9  Drupal\Core\Config\Entity\ConfigEntityStorage->doSave() called at [/core/lib/Drupal/Core/Entity/EntityStorageBase.php:392]
#10 Drupal\Core\Entity\EntityStorageBase->save() called at [/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php:259]
#11 Drupal\Core\Config\Entity\ConfigEntityStorage->save() called at [/core/lib/Drupal/Core/Entity/Entity.php:377]
#12 Drupal\Core\Entity\Entity->save() called at [/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php:637]
#13 Drupal\Core\Config\Entity\ConfigEntityBase->save() called at [/core/modules/views/views.post_update.php:213]
#14 {closure}()
#15 array_walk() called at [/core/modules/views/views.post_update.php:214]
#16 views_post_update_revision_metadata_fields() called at [/core/includes/update.inc:241]
#17 update_invoke_post_update() called at [/vendor/drush/drush/commands/core/drupal/batch.inc:163]
#18 _drush_batch_worker() called at [/vendor/drush/drush/commands/core/drupal/batch.inc:111]
#19 _drush_batch_command() called at [/vendor/drush/drush/includes/batch.inc:98]
#20 drush_batch_command() called at [/vendor/drush/drush/commands/core/drupal/update.inc:193]

So far, it was always a property inside a views filter, where it expects value to be a string but it's an array.

While it's bad that those mismatches exists, we ignore missing schema outside of tests, so I think we should also ignore those kind of problems, possibly just log them, without failing the update.

Example errors:
InvalidArgumentException: The configuration property display.default.display_options.filters.type.value.audio doesn't exist. in Drupal\Core\Config\Schema\ArrayElement->get() (line 76 of /h
InvalidArgumentException: The configuration property display.default.display_options.filters.type_1.value.image doesn't exist.


Visually-hidden refresh button in Field UI fails WCAG Focus Visible.

$
0
0

Problem/Motivation

The Entity Display forms ("manage display" and "manage form display") have a visually-hidden button:

<input class="visually-hidden button js-form-submit form-submit" data-drupal-selector="edit-refresh" id="edit-refresh" name="op" value="Refresh" type="submit">

This button is triggered programatically as part of Field UI's ajax behaviours. It seems this button is NOT intended to be activated by human users, hence the visually-hidden class. Mouse/pointer users cannot operate this button, because it has zero height and width.

However, this button is still in the keyboard tabbing order, and can be activated by a keyboard user. The visually-hidden class means the focused button isn't perceivable though, which is a failure of WCAG 2.4.7 Focus Visible. It acts as a confusing extra tab-stop for keyboard users, who can activate it by accident (though doing so seems to be harmless).

Proposed resolution

Hide the button from all users, not just sighted mouse/pointer users.

Possible Approaches:
The most reliable way to hide the button from all user is with display: none. This will hide it from screen readers, and remove it from the tabbing order for sighted keyboard-only users. There are a few ways we could do that.

  • Hide the refresh button with the .hidden class instead of .visually-hidden. REJECTED in #2, it was being overridden by author styles.
  • Hide the refresh button with the .hidden class instead of .visually-hidden, and provide a more specific override (like toolbar and contextual modules do, see comment #8).
  • Use a custom class for this button, and use display:none on that. WORKS see comment #2.
  • Use the HTML5 hidden attribute instead of the .visually-hidden class. See comment #8.

Important: will the button still accept a programatically-triggered mousedown event?

  • YES, still works in Firefox.
  • TODO: confirm this still works in other browsers.

Remaining tasks

  • Patch to hide the button
  • Make sure the need to hide it from all users is documented in comments.
  • Cross-browser testing - test the tabbing order in all our supported browsers, confirm the button isn't tabbable.
  • Cross-browser manual testing - Confirm the trigger('mousedown') in Drupal.fieldUIOverview.AJAXRefreshRows() still works, in all our supported browsers.

User interface changes

Accessibility improvements - remove the confusing button from the keyboard-only and screen reader experience.
No visual design changes.

API changes

None.

Data model changes

None.

make the 'group' property on EntityReferenceSelection plugins implicitly derived

$
0
0

Problem/Motivation

The interplay between the plugin ID and the group property on EntityReferenceSelection plugins is weird.

Despite improving the docs for this #2945789: Document quirks of Entity reference selection plugins while a fix is figured out, it's still confusing #3270898: Misleading documentation in \Drupal\Core\Entity\Annotation\EntityReferenceSelection. There is a long-standing issue to fix it #2649712: Entity reference selection plugins break when not following a weird ID pattern but no way forward.

I have an alternative suggestion: since the group property MUST conform to a certain pattern, remove it from the plugin attribute and derive it in the plugin manager.

The current rule is:

- group and id must be identical, OR
- if id is of the form foo:bar, group must be foo

Therefore, we can remove the group property from the attribute and set it in the plugin manager like this:

- if id does not contain a ':', set group to the same as the id
- if id is of the form foo:bar, set group to foo

We keep the concept of group, because it's used by EntityReferenceItem (see my comments on #3270898: Misleading documentation in \Drupal\Core\Entity\Annotation\EntityReferenceSelection for an explanation), but it's now impossible to get it wrong.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Add option to un-sticky table headers to benefit assistive tech users

$
0
0

Problem/Motivation

Some accessibility concerns about the use of sticky table headers were brought up in #3070558: Implement bulk operation designs.

@andrewmacpherson pointed out that the use of a sticky header obscures content. There are two categories of issues this causes:

  1. In a table such as admin/content users can can navigate to an items hidden beneath a sticky header, so there's no longer a visual indication of the item in focus.
  2. Speech control users may encounter a problem with "show numbers" functionality, which displays a number label for each control on the page. These labels would also be applied to items concealed by the sticky and cause confusion.

Steps to reproduce

In admin/content, get the page in a position where the header is sticky, then tab-navigate through the table. Note that items hidden underneath the sticky header can still be focused, but the item+focus state is not visible.

Proposed resolution

This issue was discussed with @rain. There was agreement that there are UX benefits to sticky headers (and potentially other sticky elements such as the one proposed in #3070558). While are several straightforward ways to address concern #1 (keyboard users) while retaining the benefits of Sticky navigation, this doesn't seem possible for addressing #2 (Speech control "show numbers"). @rain suggested adding a toggle that allows enabling/disabling of sticky headers. This would allow the subset of users adversely impacted by sticky headers to bypass that functionality.

Remaining tasks

Determine if this is an acceptable change to core
Review the patch

User interface changes

A new toggle button above tables with sticky headers.

Release notes snippet

A translation already exists for the specified language

$
0
0

I am using Drupal 8.9.13, and when click on save this page then getting some error.

Drupal\Core\Entity\EntityStorageException: A translation already exists for the specified language (de-de). in Drupal\Core\Entity\Sql\SqlContentEntityStorage->save() (line 846 of /code/docroot/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).

Please need help ASAP.

Enabling aggregation breaks views with "Moderation state" fields

$
0
0

Problem

Steps to reproduce

  1. Enable content_moderation
  2. Assign a workflow to a node bundle
  3. Create a new node view and add a "Moderation state" field
  4. Enable aggregation and execute the view

Result:

Drupal\Core\Entity\Sql\SqlContentEntityStorageException: Column information not available for the 'moderation_state' field. in Drupal\Core\Entity\Sql\DefaultTableMapping->getFieldColumnName() (line 430 of core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php).

Proposed resolution

As a workaround the deprecated moderation state relationship can still be used with a view that has aggregation enabled.

View result counter as token not work when use in Output this field as a custom link

$
0
0

Problem/Motivation

When enabled "Output this field as a custom link" checkbox , add counter field token in link path , then counter token broken in href on FE.

Steps to reproduce

  • Add/edit the view
  • Add field: View result counter
  • Add field: Custom text, Add value in text field
  • After scroll down, you 'll find opt: rewrite results > click on it
  • Then you 'll find checkbox: "Output this field as a custom link"& enable it
  • You 'll see opt link path , add here counter field token for eg: /test/{{ counter }}
  • Click on apply btn & save the view

Issue is replicable Drupal 10 version as well
Note: I didn't find any issue w.r.t to counter that fails this mentioned scenario, if anyone finds then can close ir as duplicate by attaching the link of existing issue.

counter-token-img

Expected behaviour

Instead of this broken counter field token "/test/%7B%7B%20counter%20%7D%7D" in href tag counter field's token value should render(eg: /test/1)

Proposed resolution

When checked "Output this field as a custom link" checkbox & add the counter field token in to link path, then counter token should work instead of broken in href

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

#states not working correctly when built from a logical combination of multliple fields

$
0
0

Problem/Motivation

I noticed this issue while developing a relatively complex form, but I have since refined the problem down to a very simple form and have tested on a vanilla instance of Drupal 9.5.10.

The issue occurs when an element's state is built from a logical combination of multiple other fields.

For example:

'visible' => [
    ':input[name="select1"]' => ['value' => 0],
    ':input[name="select2"]' => ['value' => 1],
  ],

Also note the same behaviour occur if written:

'visible' => [
    ':input[name="select1"]' => ['value' => 0],
    'and',
    ':input[name="select2"]' => ['value' => 1],
  ],

Steps to reproduce

- BigPipe module has been installed.
- Use the following form:

  $form['select1'] = [
    '#type' => 'select',
    '#title' => 'Select 1',
    '#options' => [0 => 0, 1 => 1],
    '#default_value' => 0,
  ];

  $form['select2'] = [
    '#type' => 'select',
    '#title' => 'Select 2',
    '#options' => [0 => 0, 1 => 1],
    '#default_value' => 0,
  ];

  $form['select3'] = [
    '#type' => 'select',
    '#title' => 'Select 3',
    '#options' => [0 => 0, 1 => 1],
    '#states' => [
      'visible' => [
        ':input[name="select1"]' => ['value' => 0],
        'and',
        ':input[name="select2"]' => ['value' => 1],
      ],
    ],
  ];

After the form loads, you see the select elements 1 and 2. You don't see select 3 because the default values aren't as defined in #states.

If I select a value of 1 in select element 2, the values *should* be correct to trigger the appearance of select element 3. However, this doesn't happen.

Instead you have to set element 2 back to a value of 0, then again to a value of 1, before select element 3 appears.

Proposed resolution

Modules like big_pipe invoke attachBehaviors that results in multiple attachment of behaviors for a given context. If the attachBehavior is called multiple times, then in states multiple states.Dependent objects are created for the same elements. However the initialise is not called in Trigger function for all the states.Dependent object since it checks if it was already initialised for an element. Thus resulting in the bug. Proposed solution is to ensure that the states are attached only once.

- Approach 1: 3386191-states-not-working

Modify core/misc/states.js to use the library once to avoid duplicate attach calls multiple times.

Drupal.behaviors.states = {
    attach(context, settings) {
       // Uses once to avoid duplicates if attach is called multiple times.
      const elements = once('states', '[data-drupal-states]', context);

Warning: Illegal offset type in ContentEntityStorageBase->getFromPersistentCache()

$
0
0

When I add add {{ drupal_view('bijbehorende_producten', 'block_1', field_producttype_1 )}} in my view I get the warning below, Only after saving the view or clearing the cache. Without an argument it does not give any errors

Not sure if the fault lives here or somewhere else as I found a related issue.

Warning: Illegal offset type in Drupal\Core\Entity\ContentEntityStorageBase->getFromPersistentCache() (line 591 of core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php).
Drupal\Core\Entity\ContentEntityStorageBase->getFromPersistentCache(Array) (Line: 396)
Drupal\Core\Entity\Sql\SqlContentEntityStorage->doLoadMultiple(Array) (Line: 242)
Drupal\Core\Entity\EntityStorageBase->loadMultiple(Array) (Line: 507)
Drupal\Core\Entity\Entity::loadMultiple(Array) (Line: 19)
Drupal\taxonomy\Plugin\views\argument\IndexTid->titleQuery() (Line: 153)
Drupal\views\Plugin\views\argument\ManyToOne->title() (Line: 976)
Drupal\views\Plugin\views\argument\ArgumentPluginBase->getTitle() (Line: 1099)
Drupal\views\ViewExecutable->_buildArguments() (Line: 1254)
Drupal\views\ViewExecutable->build(NULL) (Line: 1378)
Drupal\views\ViewExecutable->execute(NULL) (Line: 1441)
Drupal\views\ViewExecutable->render() (Line: 2391)
Drupal\views\Plugin\views\display\DisplayPluginBase->preview() (Line: 1649)
Drupal\views\ViewExecutable->preview('block_1', Array) (Line: 63)
Drupal\views\Element\View::preRenderViewElement(Array)
call_user_func(Array, Array) (Line: 376)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 474)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 94)
__TwigTemplate_24cdf5df7d7fb14a7ef085dd4347a3d935fd098fbc4a8818edf1079f09f7cb21->doDisplay(Array, Array) (Line: 432)
Twig_Template->displayWithErrorHandling(Array, Array) (Line: 403)
Twig_Template->display(Array) (Line: 411)
Twig_Template->render(Array) (Line: 116)
Drupal\Core\Template\TwigEnvironment->renderInline('{# inline_template_start #}

{{ field_productfoto }} 
{{ title }}
{{ body }}


Ingrediënten
{{ field_ingredienten }}






{# Match integer #}
{% if field_producttype_1 matches '/^\\d+$/' %}
{{ drupal_view('bijbehorende_producten', 'block_1', field_producttype_1 )}}
{% endif %}

', Array) (Line: 52)
Drupal\Core\Render\Element\InlineTemplate::preRenderInlineTemplate(Array)
call_user_func(Array, Array) (Line: 376)
Drupal\Core\Render\Renderer->doRender(Array, 1) (Line: 195)
Drupal\Core\Render\Renderer->render(Array, 1) (Line: 151)
Drupal\Core\Render\Renderer->Drupal\Core\Render\{closure}() (Line: 574)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 152)
Drupal\Core\Render\Renderer->renderPlain(Array) (Line: 407)
Drupal\views\Plugin\views\PluginBase->viewsTokenReplace('

{{ field_productfoto }} 
{{ title }}
{{ body }}


Ingrediënten
{{ field_ingredienten }}






{# Match integer #}
{% if field_producttype_1 matches '/^\\d+$/' %}
{{ drupal_view('bijbehorende_producten', 'block_1', field_producttype_1 )}}
{% endif %}

', Array) (Line: 1345)
Drupal\views\Plugin\views\field\FieldPluginBase->renderAltered(Array, Array) (Line: 1238)
Drupal\views\Plugin\views\field\FieldPluginBase->renderText(Array) (Line: 1173)
Drupal\views\Plugin\views\field\FieldPluginBase->advancedRender(Object) (Line: 224)
template_preprocess_views_view_field(Array, 'views_view_field', Array) (Line: 287)
Drupal\Core\Theme\ThemeManager->render('views_view_field', Array) (Line: 435)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 1736)
Drupal\views\Plugin\views\field\FieldPluginBase->theme(Object) (Line: 765)
Drupal\views\Plugin\views\style\StylePluginBase->elementPreRenderRow(Array)
call_user_func(Array, Array) (Line: 376)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array) (Line: 713)
Drupal\views\Plugin\views\style\StylePluginBase->renderFields(Array) (Line: 580)
Drupal\views\Plugin\views\style\StylePluginBase->renderGrouping(Array, Array, 1) (Line: 466)
Drupal\views\Plugin\views\style\StylePluginBase->render(Array) (Line: 2117)
Drupal\views\Plugin\views\display\DisplayPluginBase->render() (Line: 1520)
Drupal\views\ViewExecutable->render() (Line: 171)
Drupal\views\Plugin\views\display\Page->execute() (Line: 1617)
Drupal\views\ViewExecutable->executeDisplay('page_1', Array) (Line: 78)
Drupal\views\Element\View::preRenderViewElement(Array)
call_user_func(Array, Array) (Line: 376)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 226)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 574)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 227)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 117)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object) (Line: 149)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 64)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 652)
Drupal\Core\DrupalKernel->handle(Object) (Line: 22)

a11y: Input type file fields lack aria-describedby to the description

$
0
0

Description: Within the “Create Node” page, when the “File” field is accessed, JAWS announces “File file upload edit browse…” and does not announce the additional information “One file only. 256 MB limit. Allowed types: pdf doc docx xls xlsx ppt pptx csv txt”. Instead, JAWS is expected to announce the label and the additional information e.g. “File upload edit browse, One file only. 256 MB limit. Allowed types: pdf doc docx xls xlsx ppt pptx csv txt”.

File field with help text that is not getting read aloud

• Testing was performed using JAWS v18.0.2945.
• This defect exists in IE 11 and Google Chrome v68.0.3440.106.

Steps to reproduce:

  1. Add a file field to a content type: Limit 1, add as many "Allowed file extensions" as you choose.
  2. Open JAWS v18.0.2945.
  3. Create/Edit a node that has the file field.
  4. Use the Tab key to navigate to the “File” field.

Notice that JAWS announces “File file upload edit browse…” and does not announce the additional information “One file only. 256 MB limit. Allowed types: pdf doc docx xls xlsx ppt pptx csv txt”.

Expected result: All additional information needed to complete form fields is expected to be announced by JAWS.

Review/update $adminTags variable for new html elements to be whitelisted

$
0
0

Problem/Motivation

Xss::filterAdmin() is currently stripping out the picture & source html elements that are part of the Core module Responsive Image. $adminTags sets the elements that are whitelisted and would need to be updated.

This bug was first found at https://www.drupal.org/node/2687479. Views is stripping out the picture & source elements when responsive images fields are being rewritten. The patch there will be uploaded here to start / demo a fix that would need to be reviewed.

Steps to reproduce

This is for testing responsive image support (picture):

1. Install Drupal with Umami profile
2. Create new View: Content of type Article, Create a page, Save and edit
3. Switch Format from Content to Fields
4. Add a Media Image field
5. Choose Formatter = Rendered entity and View mode = Responsive 3x2
6. Look at the page
7. Result: See original image for the articles
8. Expected: See responsive image for the articles

Proposed resolution

Review/update $adminTags to include picture & source. It would probably be good to review $adminTags to see if there are any other html elements that should be whitelisted at the same time.

Remaining tasks

  • Verify steps to reproduce
  • Review what HTML elements to add
  • New HTML elements to be reviewed for XSS vulnerabilities

HTML elements to add:

  • button

User interface changes

none

API changes

none

Data model changes

none

Symfony\Component\Validator\Exception\LogicException: The LangcodeRequiredIfTranslatableValues constraint can only operate on the root object being validated

$
0
0

Problem/Motivation

When I try to arrange text formats and editors settings I get the following error.

Symfony\Component\Validator\Exception\LogicException: The LangcodeRequiredIfTranslatableValues constraint can only operate on the root object being validated. in Drupal\Core\Config\Plugin\Validation\Constraint\LangcodeRequiredIfTranslatableValuesConstraintValidator->validate() (line 26 of var/www/html/mysite/web/core/lib/Drupal/Core/Config/Plugin/Validation/Constraint/LangcodeRequiredIfTranslatableValuesConstraintValidator.php).

File formatter render absolute url to file

$
0
0

Problem/Motivation

Currently, file and image field's field formatter doesn't have support to render/display absolute URL.
ImageUrlFormatter and UrlPlainFormatter classes doesn't have flexibility to display absolute url.

Steps to reproduce

Configure the field formatter and check that we don't have flexibility to render absolute url.

Proposed resolution

- Add an option to both the field formatters.
- Validate option value in viewElements() method and display URL accordingly.
- Add test cases to validate newly added options.

Remaining tasks

Contact Usability for wording of new text in the UI.
- Review MR https://git.drupalcode.org/project/drupal/-/merge_requests/5882 which represents further changes since patch #122

User interface changes

- New option is added on both the field formatters.

File field:

Image field

API changes

- N/A

Data model changes

- N/A

Release notes snippet

XSS attribute filtering is inconsistent and strips valid attributes

$
0
0

Follow-up to #2105841: Xss filter() mangles image captions and title/alt/data attributes

Problem/Motivation

\Drupal\Component\Utility\Xss::filter() cleans potentially dangerous protocols like "javascript:" from element attributes. It does this by stripping any set of characters that ends with a colon, unless the string is "http:" or "https:".

The filter strips out valid attribute name/value combinations that provide RDF metadata, such as rel="schema:author" or property="foaf:name".

Some attributes are exempt from this treatment, including alt, title, and any data-* attribute. In #2105841: Xss filter() mangles image captions and title/alt/data attributes, the decision was made to hard-code the exempt attributes list, and possibly make the list configurable in a follow-up issue.

Proposed resolution

Create two lists: one for for safe attributes (for which we can skip protocol check) and one for unsafe attributes (for which we enforce a protocol check).

User interface changes

None.

API changes

None.

Beta phase evaluation

Reference: https://www.drupal.org/core/beta-changes
Issue categoryBug because RDF attributes are being stripped
Issue priorityMajor because ... Critical/Not critical because ...
Unfrozen changesUnfrozen because it is a bug fix
Prioritized changesThe main goal of this issue is bug fix and security
DisruptionDisruptive for core/contributed and custom modules/themes because it will require a BC break/deprecation/data model changes/an upgrade path/internal refactoring/widespread changes... (Which? Specify.)

-->

Ajax attached to Views exposed filter form does not trigger callbacks

$
0
0

If you try to use #ajax on a Views exposed filter form element, the callback is never invoked. This was discussed at length in the Views issue queue here:

#1183418: Ajax attached to exposed filters in form_alter doesn't trigger callback

The same bug exists in the version of Views in Drupal 8 core. As merlinofchaos wrote:

Views are $_GET forms and they specifically remove the form_id and form_build_id and form_token because they are 'submitted' even when they aren't submitted. That means the standard #ajax tools don't work with them, since those rely on being able to cache the form in core's form cache. That system is to naive to work with core's filters. I've never really tried to do anything like this in D7 yet, so I don't know what the solutions might be, but I can say that it's going to provide very ugly URLs if you hack the form id back in.

The proposed solution is to add a little custom JS magic so that we identify all the form info via after_build callbacks, stash those in JS settings, and then inside the JS, we reattach the relevant form info to the #ajax-enabled form elements so that their callbacks can be properly invoked.


Improve fast-backend write performance of ChainedFastBackend by serializing upfront

$
0
0

Problem/Motivation

ChainedFast is a nice backend, which has it's problems as it needs to write back all data again and again to the fast backend.

One of the most CPU intensive things is the constant serialization and unserialization -- even if it's usually handled by the cache backends themselves.

One of the reasons is that Drupal uses DEEP arrays, and DEEP objects.

However if you do:

$item = (object) [
  'data' => serialize($data),
];
$store = serialize($data);

this is almost as fast as:

$item = (object) [
  'data' => $data,
];
$store = serialize($data);

because the one level for serialization is not responsible for a huge performance penalty.

And we can use this to our advantage!

Proposed resolution

If we serialize() the data before set() and unserialize() the data after get() / getMultiple(), then in practice it means that 90% of the data is already serialized, which we get back from the consistent backend!

Which means we save 90% of the serialization effort when saving data to the fast backend!

And that in the end means that things are 90% faster.

(And APCu is storing serialized data as well and no longer copying raw PHP objects into memory, so that's no longer a concern.)

Also: Because we do not need to unserialize the data coming from APCu, we can effectively save the unserialize() step when the data is invalid -- before we would unserialize twice.

Remaining tasks

- Create patch based on the following:

diff --git a/web/core/lib/Drupal/Core/Cache/ChainedFastBackend.php b/web/core/lib/Drupal/Core/Cache/ChainedFastBackend.php
--- a/web/core/lib/Drupal/Core/Cache/ChainedFastBackend.php
+++ b/web/core/lib/Drupal/Core/Cache/ChainedFastBackend.php
@@ -170,6 +170,10 @@ public function getMultiple(&$cids, $allow_invalid = FALSE) {
       }
     }
 
+    foreach ($cache as $cid => $item) {
+      $item->data = unserialize($item->data);
+    }
+
     return $cache;
   }
 
@@ -177,6 +181,8 @@ public function getMultiple(&$cids, $allow_invalid = FALSE) {
    * {@inheritdoc}
    */
   public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
+    $data = serialize($data);
+
     $this->consistentBackend->set($cid, $data, $expire, $tags);
     $this->markAsOutdated();
     // Don't write the cache tags to the fast backend as any cache tag
@@ -188,6 +194,10 @@ public function set($cid, $data, $expire = Cache::PERMANENT, array $tags = []) {
    * {@inheritdoc}
    */
   public function setMultiple(array $items) {
+    foreach ($items as &$item) {
+      $item['data'] = serialize($item['data']);
+    }
+
     $this->consistentBackend->setMultiple($items);
     $this->markAsOutdated();
     // Don't write the cache tags to the fast backend as any cache tag

User interface changes

- None

API changes

- None

Data model changes

- None

Make config sequences sortable with sub keys

$
0
0

Problem/Motivation

Sequences in a config schema are used for many things and they can define if they should be ordered by key or value. Unfortunately, however, most sequences do not specify a sorting order.
For some sequences there is already an order defined in the config entity class which can not easily be translated to order by key or value.

In order to allow more sequences to be sorted the way they are we need to add a more flexible sorting definition.

However, unlike in #3246905: Add optional sorting method for sequences we don't want the flexibility to run arbitrary code and instead keep things declarative.

Proposed resolution

Add a new allowed values to orderby.
The new values have the form of subkey:[somekey] for example subkey:weight
For some sequences however just one property is not enough, so we should allow multiple, and also allow drilling down into sub-sub keys is an option.

Remaining tasks

decide on name
decide on whether or not we want to drill into sub-sub-keys
implement

User interface changes

none

API changes

new allowed values for orderby in sequence config schema.

Data model changes

none

Release notes snippet

Config sequences can be sorted with more fine grained control.

Dropbutton widget not accessible to screen readers

$
0
0

Problem/Motivation

The dropbutton widget from core does not work well with screen readers:

  1. The change in state of the dropdown (visible or not) is not communicated to the screen reader.
  2. The toggle button's screen reader text says "list additional actions" which is unclear, especially if the dropdown is open.
  3. The dropdown automatically closes after focusing out, which may be confusing for screen reader users if they aren't aware it closed. This behavior is inconsistent for mouse users as well since the button opens on click, but closes by hovering out.

Steps to reproduce

Visit a page that has dropbuttons such as /admin/structure/types.

  1. Use a screen reader or emulator and open/close the dropdown. The change of visibility to dropdown menu is not communicated to the screen reader.
  2. Focus the screen reader on the toggle button to hear the text "list additional actions".
  3. Using the keyboard, open the dropdown, then tab away from it. The dropdown closes automatically.

Proposed resolution

  1. Implement aria-expanded and aria-controls attributes to communicate the open/closed state.
  2. Change the arrow button's screen reader text to just "additional actions".
  3. Have the dropdown stay open after focusing/hovering out - to close it, users should click the arrow button again.

User interface changes

Screenshots (gray box indicates VoiceOver text):

Before:
 list additional actions, button, group

After:
 additional actions, collapsed, button, group

Drupal Usability Meeting 2024-06-28

$
0
0

This meeting takes place every Friday at 14:00 UTC (currently 7:00am PT, 10:00am ET). See Time.is to see what that is in your timezone.

The meetings are held using Zoom, and a link is posted in the #ux Slack channel 10 minutes before the meeting. Agenda is first come, first serve and set by attendees. Use the Needs usability review issue tag for issues that need review and/or suggest issues in comments here.

List of Slack users to ping 10 minutes before the meeting:
@worldlinemine, @lauriii, @AaronMcHale, @anmolgoyal74, @Ravi, @shaal, @ckrina, @simohell, @gauravvv, @Quynh, @yoroy, @nod_, @andrei.zvonkov, @rachel.hart

This list gets copied to the issue for the next meeting. If that has already happened, then go to that issue to add/remove yourself to/from the list.

Recording of this week's meeting: TODO

Rough transcript of this week's meeting: Drupal Usability Meeting - 2024-06-28.txt

We discussed the following issue:

  • [#TODO]

NR and RTBC issues marked Needs usability review.

The group is actively tracking progress on these issues:

Remaining tasks

  1. Add issue credits for the participants.
  2. Add the issue(s) we discussed to the issue summary and as related issues.
  3. Add a rough transcript.
  4. Add a link to the recording on YouTube.
  5. Comment on the issue(s) we discussed.

TypeError: round(): Argument #1 ($num) must be of type int|float, string given in round()

$
0
0

While working with the Translation Management Tool module on Drupal 10.2, I encountered the following error while reviewing translation:
TypeError: round(): Argument #1 ($num) must be of type int|float, string given in round() (line 114 of core/lib/Drupal/Core/Field/Plugin/Field/FieldType/DecimalItem.php).

Viewing all 293247 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>