Previously code uses:
$attribute_value = Html::cleanCssIdentifier($attribute_value);
This method is designed to sanitize CSS identifiers (e.g., class names, IDs).
It ensures they are valid by replacing leading numbers and stripping disallowed characters. However, this is too strict when applied to
HTML attribute values (such as `data)', because:
Valid `data-` attribute values may begin with digits (e.g., `550`).
Sanitization with cleanCssIdentifier()
incorrectly rewrites these values (`550 → _550`).
$attribute_value = Html::escape($attribute_value);
-
Context-appropriate sanitization:
- `Html::escape()` encodes special HTML characters (`<`, `>`, `"`, `'`, `&`).
- This prevents injection into the DOM or breaking out of the attribute context.
- Preserves valid values:
- Digits, letters, and safe symbols remain unchanged (`550` stays `550`).
- Mitigates XSS:
- Any attempt to inject markup like `">
...` will be safely escaped:
- `"><script>...</script>`
-
Security Conclusion
- `Html::cleanCssIdentifier()` is only necessary when generating CSS identifiers.
- For attribute values in HTML, `Html::escape()` provides the correct level of protection against XSS.
- Therefore, this change maintains security while restoring correct behavior for numeric and other valid attribute values.
Also there is a warning on this page:
In the above image, we can see that in the Project Browser settings, the Recipes and Contrib Modules options are disabled, so the Recommended tab is not showing.
After enabling them, the Recommended tab becomes visible.
To fix this issue, we need to ensure that these options are automatically enabled during installation.
Replaced Html::cleanCssIdentifier()
with Html::escape()
to prevent numeric data-* attribute values from being prefixed with underscores.
Please review.
Are there any other configurations or settings that need to be set on the Drupal site? If I install the memcache_status module, there are no errors on the page.
Working on this.
Thanks to all reviewers.
- I have cleaned up the
ImportConfigManipulator
, and based on this, I also changed theImportConfigManipulatorInterface
- Methods can’t be made protected since they are defined in the interface. Implementations must keep them public; otherwise, it would break the contract and cause fatal errors.
Please review.
Working on this.
I have solved the error and generated MR.
The reason $form_element = FormElementHelper::getElementByName([$key], $form);
or $form_element = FormElementHelper::getElementByName(['submitted', $child_key], $form);
does not work is because getElementByName() in Drupal core only accepts a string as its first argument, not an array.
Core internally compares this string against the element’s #parents
array, joined with implode('][', …)
. Passing an array directly causes a PHP type error:
TypeError: Argument 1 ($name) must be of type string, array given
The correct approach is to convert any array of parent keys into a string before passing it, like this:
$form_element = FormElementHelper::getElementByName(implode('][', ['submitted', $child_key]), $form);
This ensures compatibility with both flat and nested form elements (Webforms, nodes, user profiles, etc.) without touching core.
Also, I have fixed this Issue 📌 webform file document field generates php TypeError caused by protected forms module Active .
Please review.
Thanks
Working on it.
penyaskito → credited kul.pratap → .
Creating MR for this.
I fixed the warning by checking if the config value exists before using it. If nothing is saved yet, we just use an empty array as the default, so the form doesn’t try to read data from false.
Working on it.
@berdir, I have removed it from the correct file.
Please review.
Working on this.
Working on this
@drupal-baby Already a Issue 🐛 Warning: Undefined property: Drupal\amazon_ses\Form\AmazonSesTestForm::$config in Drupal\amazon_ses\Form\AmazonSesTestForm->submitForm() (line 83 of /home/www/drupal/web/modules/contrib/amazon_ses/src/Form/AmazonSesTestForm.php) Active present and this is already fixed now in 3.0.1 the issue resolved.
I have tested this patch and it is working fine, creating MR for this.
Thanks
I can't reproduce the issue with different file names; both use the same file path in my case, and no copy is created.
This MR fixes the handling of the decline URL.
Right now, the block always assumes the value is an internal path, which breaks when you try to use a full external URL. The change makes it detect http:// or https:// and use the link as-is, while keeping the current behavior for internal paths.
Please review.
Thanks
Working on it.
You have already done the changes, i have assigned this issue beacuse i didn't see any MR.
Working on this.
Right now, when you add #attached['drupalSettings'] in a block’s build() method, those settings don’t always make it into the global drupalSettings unless the block also attaches a library. This feels like a change in behavior compared to earlier versions.
It would be more intuitive if settings from a block were always passed through, even without a library. That way we can attach simple data for frontend scripts without having to create a library just for it.
As a temporary workaround, you can either attach a library in the block or move the settings into hook_page_attachments().
@jonedahn I didn't find this $view_config_updater = \Drupal::service(ViewsConfigUpdater::class);
i think it is already updated.
Working on this.
@sandeep_k you have not installed the "league/html-to-markdown": "^5.1" this is a package which is require to run this module.
You can see in the composer.json
After that reinstall the module.
@omarlopesino I have created an action that downloads a ZIP file. For now, I have only created action for markdown.
For reference, I am attaching a video on how it works.
Please review.
Thanks
Yes, I am on it and doing it the same way as you mentioned.
@omarlopesino We want both HTML and Markdown, or just Markdown, in the downloaded ZIP.
Working on it.
Creating MR for this.
@heddn I think you forgot to give credit to me :)
Thanks
I have fixed the pipeline issues.
Please review.
After investigating, we found that the script expects a data-babel-source attribute on each
Working on this.
Creating MR for this patch.
Working on this.
Tested this patch and it works well.
- The `layout_builder_preprocess_language_content_settings_table()` logic is migrated cleanly to a new class using the #[Hook] attribute.
- layout_builder.module is now safely removable.
Marking this RTBC.
I have applied the MR on a fresh Drupal 11.x site and confirmed the following through the UI:
- Created a content type with a File field and tested upload and remove functionality. Everything worked as expected.
- Repeated the test with an Image field — both upload and remove actions work correctly.
- Verified behavior for single and multi-value fields.
- Tested required field validation by removing the uploaded file — validation triggers as expected.
- Confirmed no errors in the PHP logs or JavaScript console.
- Verified that file_managed_file_submit() is now deprecated and the logic is moved to \Drupal\file\Element\ManagedFile::submit(), maintaining BC correctly.
- Everything works as expected, and the code looks clean and standards-compliant.
Marking this issue RTBC.
Thanks!
Unassigning this so everyone can follow up on this.
- Investigated and confirmed the issue originates from jQuery UI 1.10+ strict method behavior.
- Searched Webform module and custom code for any direct autocomplete('destroy') usage.
- Verified no explicit destroy calls exist — deduced issue happens during Drupal.detachBehaviors().
- Added data('ui-autocomplete') checks before calling .autocomplete('destroy') in patched logic but it also didn’t work.
- Explored related Webform behaviors (webformElementStates, webform.form.js, clientside_validation) for improper destroy usage.
- Validated that validate().destroy() was also unsafe and fixed it using a data('validator') check but it also didn’t work.
Working on this.
Working on it.
@avpaderno So, shall we move forward?
Working on it.
Fixed the text also.
@tim-diels I've updated the autofill behavior to include a more robust slugification process that properly removes consecutive hyphens and handles custom replacements.
Please review.
Thanks
@harlor, I have done the changes as per your suggestions.
Please review.
Thanks harlor
Working on it.
Working on it.
Working on it.
Since the MR was merged, please change the state of the issue.
Thanks.
@lostcarpark Thanks, done the changes as per your suggestion.
Please review.
Working on it.
@avpaderno If everything looks good now, can we move forward?
I have updated the MR with the patch.
@bigbabert Thank you for your suggestions,
But the ExtensionDiscovery service scans the entire filesystem and returns all available modules—whether enabled or disabled—including core, contributed, and custom modules. This makes it ideal for use cases requiring a comprehensive list of modules. In contrast, extension.list.module (or ModuleExtensionList) only lists currently installed and enabled modules, better suited for runtime logic such as plugin management or routing requiring active modules.
In my module, users can generate README files even for disabled modules, so we use ExtensionDiscovery to ensure those modules are included in the selection list. Additionally, we exclude modules located under core/modules to avoid cluttering the list with core system modules not relevant for README generation. Using ExtensionDiscovery allows us to provide a more complete and relevant module list for our use case, while extension.list.module would restrict us to only enabled modules and miss disabled but potentially important modules.
Also, the module is installing fine on my Drupal 11 fresh site. I have attached a video for reference.
Thank you.
@bigbabert Thanks for the suggestion.
But I think it would become too complex if we had to read the main project composer.json file to determine the custom and the contrib folders.
So I updated the GenerateReadmeForm
and ReadmeGeneratorCommands
to use a reliable method for collecting only top-level custom and contrib modules using ExtensionDiscovery.
src/Form/GenerateReadmeForm.php
public function getTopLevelCustomAndContribModules(): array {
$modules = [];
$discovery = new ExtensionDiscovery(DRUPAL_ROOT);
$discovery->setProfileDirectories([]);
$all_modules = $discovery->scan('module');
foreach ($all_modules as $machine_name => $extension) {
$module_path = $extension->getPath();
if (str_starts_with($module_path, 'core/')) {
continue;
}
$path_parts = explode('/', $module_path);
$modules_index = array_search('modules', $path_parts);
if ($modules_index !== FALSE) {
$after_modules = array_slice($path_parts, $modules_index + 1);
if (count($after_modules) !== 2) {
continue;
}
}
$info = $this->infoParser->parse($extension->getPathname());
$modules[$machine_name] = $info['name'] ?? $machine_name;
}
asort($modules);
return $modules;
}
ReadmeGeneratorCommands
public function generate(string $module): void {
$discovery = new ExtensionDiscovery(DRUPAL_ROOT);
$discovery->setProfileDirectories([]);
$all_modules = $discovery->scan('module');
if (!isset($all_modules[$module])) {
$this->output()->writeln("Module '$module' not found in the filesystem.");
return;
}
$extension = $all_modules[$module];
$relative_path = $extension->getPath();
if (str_starts_with($relative_path, 'core/')) {
$this->output()->writeln("Core module '$module' is not supported.");
return;
}
$module_path = DRUPAL_ROOT . '/' . $relative_path;
$scanner = new CodebaseScanner($module_path);
$moduleData = $scanner->scan();
$config = $this->configFactory->get('ai_readme_generator.settings')->get();
$apiKey = $config['api_key'] ?? NULL;
$chatEndpoint = $config['chat_endpoint'] ?? NULL;
$model = $config['model'] ?? NULL;
if (empty($apiKey) || empty($chatEndpoint) || empty($model)) {
$this->output()->writeln('<error>Please fill the AI configuration form first!</error>');
return;
}
$ai = new AIResponse($config);
$summary = $ai->summarizeArray($moduleData);
$readme_path = $module_path . '/README.md';
file_put_contents($readme_path, $summary);
$this->output()->writeln("✅ README.md generated at: $readme_path");
}
Please review the above code. If it's correct, I will update it in the module.
@avpaderno Thank you for the review.
I've made the suggested changes.
Kindly have a look and let me know if anything else needs to be updated.
Thanks.
@vishal.kadam Thank you for the review.
I've made the suggested changes.
Kindly have a look and let me know if anything else needs to be updated.
Thanks
kul.pratap → created an issue.
kul.pratap → created an issue.
Working on it.
I have resolved the styling issue.
Please review.