Problem/Motivation
Inactive initiatives are listed in Drupal's maintainers file.
Steps to reproduce
Proposed resolution
Remove them.
Inactive initiatives are listed in Drupal's maintainers file.
Remove them.
When using Layout Builder and the Layout Builder Advanced Permissions module, a lot of queries are done to the database in DatabaseStorageExpirable
. This is done because all layout and block related actions (links) use the LayoutSectionStorageParamConverter
, which uses DatabaseStorageExpirable
to fetch the layout from the database.
Install the layout builder module and Layout Builder Advanced Permissions.
Create a page with multiple layouts and inline blocks.
Observe the number of queries growing.
It would be nice to add static caching to <code>LayoutTempstoreRepository
, to prevent it from loading the same data from the database multiple times.
-
-
-
-
This feature is needed more than you think.
If you do not agree with me, can anyone please tell me how to do this in a hook with a concrete code example?
I need this (it's only one example):
- Field: Some filter
- AND Field: Some filter
- AND Filter Group
- Field: Some filter
- OR Filter Group
- Field: Some filter
- AND Field: Some filter
Some filters are also exposed.
The URL language detection using an empty path prefix for the default language does not work properly and leads to sites being displayed in the incorrect language.
This is because empty prefixes are not taking into consideration, when identifying the language via URL prefix. And the second language negotiation in line is taken into account (e.g. browser language
Configure multiple languages and import translations:
- en (default language)
- fr
- de
- nl (default fallback in selected language detection)
Configure URL language detection:
- en (/en)
- fr (/fr)
- de (/de)
- nl (leave empty)
Configure Selected language detection:
- nl
Expected result would be that visiting the site without a path prefix (e.g. http://localhost/) would turn up in Dutch. Unfortunately it turns up in English.
http://localhost/en shows up in English
http://localhost/fr shows up in French
http://localhost/de shows up in German
http://localhost/ shows up in English <= this is an issue.
Note: One could argue that it's a bad practice to have an empty prefix:
- it's not so clear for the user as you can have content at the same level as language codes;
- may complicate future migrations or url cleanups as you need 2 different rules instead of one;
Fix the LanguageNegotiationUrl class "getLangcode()" method, to consider empty prefixes.
Trying to use #create_placeholder on a block causes blocks not to render at all in the Umami theme.
I did some debugging, and the #lazy_builder callback for those blocks gets called and works OK, but it seems like the block placeholder markup doesn't get into page markup at all, meaning there's nothing to replace. This is because Umami calls striptags in its page template, which when you have a bigpipe placeholder without any non-tag content, strips the entire thing.
Found in #3437499: [PP-2] Use placeholdering for more elements to optimize asset serving.
When a "Paragraphs (stable)" widget is used, which uses a long list of dropdowns, those items are only "hidden" with CSS, which means they are still present and causing a very long gap of whitespace at the end of the page.
Create a component which uses the "Paragraphs (stable)" widget display type. Create or edit an item. See large white space gap.
Or with only core:
core/profiles/demo_umami/modules/demo_umami_content/demo_umami_content.module
:<?php
/**
* Implements hook_entity_operation().
*/
function demo_umami_content_entity_operation(\Drupal\Core\Entity\EntityInterface $entity) {
$operations = [];
for ($i = 0; $i < 50; $i++) {
$operations['dummy_' . $i] = [
'title' => t('Dummy ' . $i),
'url' => \Drupal\Core\Url::fromRoute('<front>'),
'weight' => 50,
];
}
return $operations;
}
Update the Claro theme CSS `dropbutton.css` file for `.dropbutton-wrapper:not(.open) .dropbutton__item:first-of-type ~ .dropbutton__item` items to have a height of 1px, see #12
Review
Before
After
N/A
N/A
N/A
Meeting will happen in #d11readiness on drupal.slack.com.
Hello and welcome to this Drupal 11 readiness meeting!
This meeting:
➤ Is for core and contributed project developers as well as people who have integrations and services related to core. Site developers who want to stay in the know to keep up-to-date for the easiest Drupal 11 upgrade of their sites are also welcome.
➤ Happens every other Monday at 20:00 CET (currently 19:00 UTC).
➤ Is done over chat.
➤ Happens in threads, which you can follow to be notified of new replies even if you don’t comment in the thread. You may also join the meeting later and participate asynchronously!
➤ Has a public agenda anyone can add to: `https://www.drupal.org/project/drupal/issues/3448343`
➤ *Transcript will be exported and posted* to the agenda issue. For anonymous comments, start with a :bust_in_silhouette: emoji. To take a comment or thread off the record, start with a :no_entry_sign: emoji.
0️⃣ Who is here today? Comment in the thread below to introduce yourself.
1️⃣ Do you have suggested topics you are looking to discuss? Post in this thread and we’ll open threads for them as appropriate.
2️⃣ Celebrations 🎉
Some argument handlers provide their own default argument handling, like the Date argument. The Date argument handler does so by extending the list of of options in the defaultArgumentForm. An exception is however thrown on saving the form.
/admin/structure/views/add
using (node) contentnode.created
)Result: A fatal error occurred on dblog: Drupal\Component\Plugin\Exception\PluginNotFoundException: The "date" plugin does not exist.
Get the date handlers in line with the other default argument handlers.
Add a 'Current date', a "Current node's creation time" and "Current node's update time" default argument handler.
Steps to reproduce:
My module does some tasks via Batch API. To avoid duplicating code, I want to do those same tasks during a cron run by programmatically starting and executing the batch without trying to redirect the user to the standard batch job progress bar thingie. There seems to be the facility for this by setting the 'progressive' value of the $process_info array to FALSE, but by the same token, there doesn't seem to be a way to do that - it's hard-coded to TRUE . From D6's form.inc (D7's version is the same in this regard):
function batch_process($redirect = NULL, $url = NULL) {
$batch =& batch_get();
if (isset($batch)) {
// Add process information
$url = isset($url) ? $url : 'batch';
$process_info = array(
'current_set' => 0,
'progressive' => TRUE, // <= HERE
'url' => isset($url) ? $url : 'batch',
'source_page' => $_GET['q'],
'redirect' => $redirect,
);
$batch += $process_info;
if ($batch['progressive']) {
// Clear the way for the drupal_goto redirection to the batch processing
// page, by saving and unsetting the 'destination' if any, on both places
// drupal_goto looks for it.
// […snip…]
drupal_goto($batch['url'], 'op=start&id='. $batch['id']);
}
else {
// Non-progressive execution: bypass the whole progressbar workflow
// and execute the batch in one pass.
require_once './includes/batch.inc';
_batch_process();
}
}
}
Unless I'm missing something, this means that, though the functionality exists to do what I want to do, it's not actually possible to do so without hacking core - the code in that "else" branch will never, ever execute. One dead kitten later, I get the expected result.
However, I will allow that I'm just misunderstanding how to use an esoteric feature of this esoteric API and that doing what I need to do is possible without slaughtering kittens; in which case, a bit of edumacation would be appreciated.
Set the progressive status in the batch based on batch definition
\Drupal\content_moderation\Plugin\Field\ModerationStateFieldItemList
provides a computed field for content entities with the current moderation state of a content entity. When a piece of code calls $moderatedRevisionableTranslatableEntity->get('moderation_state')
, Drupal performs a database query similar to the following (note the following snippet uses PostgreSQL syntax, but this issue applies to all database engines)...
SELECT
"base_table"."revision_id" AS "revision_id",
"base_table"."id" AS "id"
FROM
"content_moderation_state_revision""base_table"
INNER JOIN "content_moderation_state_field_revision""content_moderation_state_field_revision" ON "content_moderation_state_field_revision"."revision_id" = "base_table"."revision_id"
WHERE
("content_moderation_state_field_revision"."content_entity_type_id"::text ILIKE :entity_type)
AND ("content_moderation_state_field_revision"."content_entity_id" = :entity_id)
AND ("content_moderation_state_field_revision"."content_entity_revision_id" = :revision_id)
AND ("content_moderation_state_field_revision"."workflow" = :workflow_name)
AND ("content_moderation_state_field_revision"."langcode" = :current_langcode)
ORDER BY
"base_table"."revision_id" DESC NULLS LAST;
If you ask MySQL, PostgreSQL, and/or SQLite to EXPLAIN how they would run the query, they all report that they need to perform what PostgreSQL refers to as a "Seq[uential] Scan" (SQLite calls it a "SCAN"; MySQL/MariaDB calls it a "data row scan") on the content_moderation_state_field_revision table: essentially, the query engine has to loop through every row in the table at query-run-time. A sequential scan is necessary because the schema for content_moderation_state_field_revision
doesn't define any indexes on the content_entity_revision_id
column by itself (even though it does define other indexes on other combinations of columns).
Anyway, the performance impact of performing a sequential scan on the table rows is magnified when there is a lot of content on the site: for example, a client site running PostgreSQL with ~90,000 nodes and ~5 revisions per node has nearly ~450,000 rows in content_moderation_state_field_revision
, taking nearly 500ms (half a second) on an optimized, load-balanced environment, and nearly 11 seconds on local environments.
Add an index to the content_moderation_state_field_revision
table, on the content_entity_revision_id
column.
For the aforementioned client site with ~450,000 rows in content_moderation_state_field_revision
, adding an index reduced the time needed to complete the query on an unoptimized local environment running PostgreSQL from around ~11 seconds to around ~17 milliseconds, a performance improvement of around ~647%.
None.
None.
Add an index named content_moderation_state__content_entity_revision_id
to the content_moderation_state_field_revision
table, on the content_entity_revision_id
column
To be determined.
Claro theme does not have the right form error class.
The files core/themes/claro/templates/details.html.twig and core/themes/claro/templates/navigation/details--vertical-tabs.html.twig have the class "form-item--error-message" but in the stylesheet core/themes/claro/css/components/form.css is defined "form-item__error-message" so if any error is displayed on the details component it is shown without styles.
inline_form_errors
moduleform_test
module. It is a test module so you'll need $settings['extension_discovery_scan_tests'] = TRUE;
in your settings if it isn't already there.form_test/details-form
and submit the form. There will be an error "I am an error on the details element." that should be styled red but it is not due to the class being incorrect as reportedUse the right class.
Test for this by expanding \Drupal\form_test\Form\FormTestDetailsForm
to try with Claro in addition to the default test theme, and assert the expected class is present.
Deprecated function: strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated in Drupal\path_alias\PathProcessor\AliasPathProcessor->processOutbound() (line 54 of core/modules/path_alias/src/PathProcessor/AliasPathProcessor.php).
Deprecated function: strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated in Drupal\Core\Routing\UrlGenerator->generateFromRoute() (line 301 of core/lib/Drupal/Core/Routing/UrlGenerator.php).
Deprecated function: rawurlencode(): Passing null to parameter #1 ($string) of type string is deprecated in Drupal\Core\Routing\UrlGenerator->generateFromRoute() (line 306 of core/lib/Drupal/Core/Routing/UrlGenerator.php).
This is another small step in simplifying the dialog.
It does not require any special testing and backward compatibility because:
- jQuery will also respond to it
- There are no arguments in this event
I left the listeners for this event as is to show that nothing changes after this merge request
Since I have upgrade severals sites from 10.0.9 to 10.1.2, a problem with ajax pager (front [like news views] and back [like media browser]).
When I take the views module from 10.0.9 core it (re)works fine, but not with 10.1.2.
Umami uses themed unformatted lists to get a 'responsive grid layout', but since 10.0.0, we've had an actual responsive grid in core, so we should use that instead.
If we're lucky, this might just be reconfiguring the views, then locating and deleting any unnecessary CSS.
Navigation Blocks page (/admin/config/user-interface/navigation-block) is the place to go to edit the navigation layout and manage the blocks to be included there.
Current NavigationSectionStorage::access()
implementation just gives free access to the page. That added to logic in LayoutBuilderAccessCheck::access()
ends up being just like checking for configure any layout
permission.
That permission is not very restrictive nor representative for Navigation module.
Would be great to have a more representative and intituive way to manage access to that page.
Create a new Administer Navigation Layout
permission
Override NavigationSectionStorage::access()
to check for that permission
Add handles_permission_check
to NavigationSectionStorage class attributes to not grant access based on configure any layout
permission.
Implement changes.
Add tests.
None
New permission added.
This is a followup from #3151553: Create new “Views Responsive Grid” format for Views Core.
Now that "Responsive Grid" is being added to core, we should deprecate the old "Grid" style in preparation to remove it for Drupal 11.
Warning: Undefined variable $target_base_table in views_field_default_views_data() (line 436 of core/modules/views/views.views.inc).
Appears after each drush cr
drush cr
load a page of the website
Initialiaze $target_base_table and $pseudo_field_name before line 436 of core/modules/views/views.views.inc
if ($target_base_table && $field_storage->isTranslatable()) {
$data[$target_base_table][$pseudo_field_name]['relationship']['join_extra'][] = [
'field' => 'langcode',
'left_field' => 'langcode',
];
}
This is a follow-up of #1927648: Allow creation of file entities from binary data via REST requests which added support for uploading file through a REST endpoint.
The implementation only support file transferred with the Content-Type: application/octet-stream
.
It's also possible (and widely used) to upload file using Content-Type: multipart/form-data
.
Some client libraries, such as ngx-uploader
for Angular projects, only support the multipart way.
It's valid to consider that the burden should be on client library and that it's up to it to be compatible with the simple binary way, but it's also valid to want to have both use cases supported by Drupal.
I think we should add a basic support for multipart/form-data uploads, which can at first be limited to only 1 file per request to reduce scope & complexity.
Declare a new format alongside "bin" to match multipart content-type and handle such requests.
The Drupal link CKEditor button can be used to add links to embedded media items. However, we can't guarantee that the rendered representation of that media item will be a single HTML element, or one that can be safely wrapped with <a>
tags. As a result, editors can create links that have arbitrary HTML elements inside them.
1) Go to simplytest.me and spin a vanilla install of Drupal 8.8.x. Log in with admin/admin, install the "Media" and "Media Library" modules.
2) Go to /admin/config/content/formats/manage/basic_html?destination=/admin/config/content/formats
and drag the "Insert from Media Library" button into the CKEditor toolbar. Enable the "Embed media" filter, and click "Save configuration".
3) Go to /admin/structure/media/manage/image/display
and drag the "Authored by" field up into the visible fields area. Click "Save" to save this view display settings.
4) Go to /node/add/article
to open the article node form. In the wysiwyg, click the "Insert from Media Library" button. Upload a file into the upload zone, give it an ALT text. Save and insert. At this point you will have something like this:
5) Click the media item to select it, then click the "Link" button from the CKEditor toolbar. Give it a random URL (such as https://drupal.org)
6) At this point, if you view the source markup you will have something similar to this:
<p>text before media</p>
<a href="https://drupal.org">
<drupal-media data-align="center" data-entity-type="media" data-entity-uuid="94a3ff34-a958-427c-ac51-127259cbc1e2"></drupal-media>
</a>
<p>text after media</p>
7) Fill in the required fields and save the node.
8) Inspect the markup of the node body, you will find something like this:
TBD
- Discuss and agree on a reasonable approach
- Implement it
- Review & commit
TBD
TBD
TBD
TBD
With the progress being made on #2801307: [META] Support WYSIWYG embedding of media entities, I've been playing with the new capabilities and have run into what seems like an important issue for typical users: after embedding some media entities, particularly images, a user will probably expect to be able to link the media to another page. At present, this doesn't really work.
<drupal-media data-entity-type data-entity-uuid>
is added to the allowed HTML tags automatically.You'll see that the image is, indeed, linked to https://drupal.org. However, if you inspect the element, the <a>
tag has been wrapped around the entire media entity:
<article data-history-node-id="1" role="article" about="/node/1" typeof="schema:WebPage" class="node node--type-page node--view-mode-full clearfix">
<header>
<span property="schema:name" content="Test Page 1" class="rdf-meta hidden"></span>
</header>
<div class="node__content clearfix">
<div property="schema:text" class="clearfix text-formatted field field--name-body field--type-text-with-summary field--label-hidden field__item">
<p>This is a test. </p>
<a href="https://drupal.org">
<article class="media media--type-image media--view-mode-full">
<div class="field field--name-field-media-image field--type-image field--label-visually_hidden">
<div class="field__label visually-hidden">
Image
</div>
<div class="field__item">
<a href="https://drupal88.dd:8443/sites/default/files/2019-08/pears_1.jpg">
<img src="/sites/default/files/2019-08/pears_1.jpg" width="640" height="480" alt="Pears" typeof="foaf:Image" />
</a>
</div>
</div>
</article>
</a>
<p>This is only a test. </p>
</div>
</div>
</article>
While we can wrap block elements in <a>
tags in HTML5, the result here is problematic. The image itself is (by default) linked to the raw image file, so we've got nested hyperlinks, which AFAIK isn't permitted in HTML5. And browsers (Safari, anyway) will ultimately render this as multiple separate <a>
tags, most of them empty or wrapping whitespace.
It seems like the expected default behavior for a typical user would be that after using the Link button, there would be some kind of visual indication in CKEditor that the entity is linked, and the rendered page would simply have the image linked to the destination specified using the Link button.
However, to complicate matters, we have to anticipate the possibility that the media entity being embedded is more complex than just an image. For example, what if I have a custom media type that looks like the Image type, but has a few more fields:
...and a default view mode that displays the image, the copyright date, the location, and a link to the Photographer entity.
If I embed this entity, and then use the link button, the desired behavior is probably for the image to link to the URL entered using the link button, while leaving the link to the Photographer node untouched so that it still works.
I'm not sure if this more complex case can be handled in any reasonably generalized fashion that'll work for most users. However, the more basic behavior of simply linking an embedded image entity should probably work out of the box, shouldn't it?
I hope this is useful! Let me know if I can clarify anything.