# Question
Title: How can I pass existing variables to a custom module template?
I'm having trouble working out how to pull existing variables into my custom module TWIG template.

I can create my own variables and pass them, but do not know how to expose variables that already exist from the theme or other entities and then pass them to the template in my custom module.

I'm working in Drupal 10, and my general goal is to create a custom module that will build a custom landing page for me. The code I'm trying right now is just test code to work out how to use a custom module to inject such a page into my site.

My custom module is called `main_sections`. To start I have a TWIG template called `pphtml--landing.html.twig`. I've named it this weird way so I can distinguish custom syntax vs any potential default naming formats Drupal might be pulling from elsewhere. My primary theme is a Drupal Bootsrap sub-theme, that has no customization yet. For testing I'm starting by trying to pull in the `site_slogan` variable and the `page.primary_menu` variable which is normally available as part of the existing theme `page.html.twig` template.

In my module I have my template: `main_sections/templates/pphtml--landing.html.twig`

```
<div class="layout-container">
  <header role="banner">
    <div>
      <p>TESTING HEAD</p>
    </div>
    {{ page.header }}
  </header>
      <div>
        <p>TESTING BODY</p>
        <p>test_var: {{ test_var }}</p>
        <div>{{ site_slogan }}</div>
        <div>{{ page.primary_menu }}</div>
        <div>{{ kint(existing) }}</div>
        <div>{{ kint(theme) }}</div>
      </div>
    <footer role="contentinfo">
        <div>
          <p>FOOTER TESTING</p>
        </div>
      </footer>
    </div>

```

my controller `main_sections/src/Controller/SectionsController.php` is:

```
  /**
   * Returns landing page.
   *
   * @return array
   *   for landing page template pphtml--landing
   */
  public function landingPage() {
    return [
      '#theme' => 'pphtml__landing',
    ];
  }

```

In my module's routing file `main_sections/main_sections.routing.yml` I have:

```
main_sections.landing:
  path: '/landing'
  defaults:
    _controller: '\Drupal\main_sections\Controller\SectionsController::landingPage'
    _title: 'Spoon Soup Landing Page'
  requirements:
    _permission: 'access content'

```

and then in my module's `main_sections/main_sections.module` I have:

```
function main_sections_theme($existing, $type, $theme, $path) {
  return [
    'pphtml__landing' => [
      'variables' => [
        'test_var' => 'my var',
        'theme' => $theme,
        'existing' => $existing,
      ],
    ],
  ];
}

```

This is the result of the code above, that also highlights what the site slogan and main navigation menu is that I'm trying to also pull into the landing page template. Though as one can see they are not displaying in the custom template.

Here is a screenshot of the $existing array expanded:

I'm guessing that I may have to use some kind of pre-processing function to grab variables that are natively pre-processed for templates that are inside the theme folder, but I can't seem to work out how to do that.

# Answer
> 0 votes
Using the custom template pre-process function or trying to mine the theme hook `$existing` parameter, or pre-process `$variables` parameter, to get data from existing Drupal entities to use in the custom module template, was the wrong approach.

It turns out I needed to use general Drupal methods to pull the desired Drupal entities from within the custom template's theme hook function. Then pass them to the template by adding them to custom template variables array.

So inside the `main_sections_theme` function we can do the following:

## **Getting Config Parameter to Pass to Custom Template**

With the Drupal::configFactory() interface, we can use the listAll() method to get a list of the available configuration objects.

```
$site_config = \Drupal::configFactory()->listAll();

```

Once we have figured out the name of the config entity we want we can use Drupal::config($name) to get a read only config object. In this case I wanted the site information configuration which I figured out is contained in `system.site`.

Thus, we can get the full set of `system.site` configuration parameters using:

```
$site_info = \Drupal::config('system.site')->get();

```

Wanting only the site slogan parameter, this can be further refined to pull just the site slogan by using:

```
$site_slogan = \Drupal::config('system.site')->get('slogan');

```

## Getting Existing Menu Object to Pass to Custom Template

Reviewing the Drupal Menu System API Docs page, **Rendering Menus** section, we see that we can use the Drupal function menuTree(), to get a MenuLinkTreeInterface that we can use to load an existing menu by name.

```
// get the menu tree interface object
$menu_tree_interface = \Drupal::menuTree();
// create menu tree parameters object needed to load requested menu
$menu_parameters = new \Drupal\Core\Menu\MenuTreeParameters();
// get menu tree object for the 'main' navigation menu
$main_menu_tree = $menu_tree_interface->load('main', $menu_parameters);

```

In this case the `$main_menu_tree`, at this point, can be built into a renderable array and passed as a template variable, however, from the documentation it seems most proper to also add standard manipulators to ensure access and menu order properties are maintained. Using the same `MenuLinkTreeInterface` we can use the `transform()` method to add a couple standard manipulators. Then we can finally prepare our pulled menu data back into a renderable array that can be passed as the template variable, using the `MenuLinkTreeInterface` function, `build($tree)`:

```
// create array of desired manipulators to apply to menu tree
$manipulators = array(
  // Only show links that are accessible for the current user.
  array(
    'callable' => 'menu.default_tree_manipulators:checkAccess',
  ),
  // Use the default sorting of menu links.
  array(
    'callable' => 'menu.default_tree_manipulators:generateIndexAndSort',
  ),
);
// apply manipulators to the menu tree using \Drupal::menuTree()->transform()
$tree = $menu_tree_interface->transform($main_menu_tree, $manipulators);
// convert main menu tree into renderable object for TWIG
$main_menu = $menu_tree_interface->build($tree);

```

## Passing Pulled Existing Site Parameters as Variables to the Custom Template

Finally, we can now pass the discovered Drupal entity parameters, we pulled into the theme hook function above, as variables for our custom TWIG template. We do this by assigning a hook variable name to each variable we want to pass and add them to the template variables array in the theme\_HOOK return object.

```
return [
  'pphtml__landing' => [
    'variables' => [
      'test_var' => 'test text variable',
      'theme' => $theme,
      'main_menu' => $main_menu,
      'main_menu_tree' => $main_menu_tree,
      'site_slogan' => $site_slogan,
      'site_information' => $site_info,
      'site_config' => $site_config,
    ],
  ],
];

```

---

The final `function main_sections_them()`, found in the `main_sections.module` file, in full:

```
/**
 * Implements hook_theme()
 * Primary module hooks for test_module module.
 */

function main_sections_theme($existing, $type, $theme, $path) {

  // get the menu tree interface object
  $menu_tree_interface = \Drupal::menuTree();
  // create menu tree parameters object
  $menu_parameters = new \Drupal\Core\Menu\MenuTreeParameters();
  // get menu tree object for the 'main' navigation menu
  $main_menu_tree = $menu_tree_interface->load('main', $menu_parameters);
  // create array of manipulators to add to menu tree object
  $manipulators = array(
    // Only show links that are accessible for the current user.
    array(
      'callable' => 'menu.default_tree_manipulators:checkAccess',
    ),
    // Use the default sorting of menu links.
    array(
      'callable' => 'menu.default_tree_manipulators:generateIndexAndSort',
    ),
  );
  // Transform the menu tree using the manipulators you want.
  $tree = $menu_tree_interface->transform($main_menu_tree, $manipulators);
  // build transformed menu tree into renderable array object for TWIG
  $main_menu = $menu_tree_interface->build($tree);

  // get list of site configuration entities
  $site_config = \Drupal::configFactory()->listAll();
  // get array of all system site information configuration parameters
  $site_info = \Drupal::config('system.site')->get();
  // get the site slogan the Drupal system site information configuration
  $site_slogan = \Drupal::config('system.site')->get('slogan');

  return [
    'pphtml__landing' => [
      'variables' => [
        'test_var' => 'test text variable',
        'theme' => $theme,
        'main_menu' => $main_menu,
        'main_menu_tree' => $main_menu_tree,
        'site_config' => $site_config,
        'site_information' => $site_info,
        'site_slogan' => $site_slogan,
      ],
    ],
  ];
}

```

---

The final custom TWIG template `pphtml--landing.html.twig` using our new variables:

```
<div class="layout-container">
  <header role="banner">
    <div>
      <p>TESTING HEAD</p>
    </div>
  </header>

  <div>
    <p>TESTING BODY</p>
    <div>{{ kint(theme) }}</div>
    <p>Simple text variable: {{ test_var }}</p>
    {{ kint(site_config) }}
    {{ kint(site_information) }}
    {{ kint(site_slogan) }}
    {{ kint(main_menu_tree) }}
    {% if site_slogan %}
      <div class="d-inline-block align-top site-name-slogan">
        {{ site_slogan }}
      </div>
    {% endif %}
    <nav class="navbar navbar-dark bg-primary navbar-expand-lg">
      <div class="container contextual-region block block-menu navigation menu--main">
        {{ main_menu }}
      </div>
    </nav>
  </div>

  <footer role="contentinfo">
    <div>
      <p>FOOTER TESTING</p>
    </div>
  </footer>
</div>

```

---

Final resulting page showing devel kint variables we used to figure things out and the properly rendered site slogan and main menu inside our custom template.

---

Expanded kint arrays:

---
Tags: theming, 10
---


# Question
Title: Condition that deletes rows older than 30 days
How can I query a condition that deletes the rows with column Date older than the last 30 days in DBTNG format?

I have tried this, but it's wrong.

```
$connection = \Drupal::database();
$connection->delete('my_table')
    ->condition('Date', now() . ' - INTERVAL 30 day', '>');
$connection->execute();

```

# Answer
Considering that the field Date is type date and has values with the following format: Y-m-d (2023-04-04).

```
// Returns a timestamp equivalent to: 2023-07-01 17:20:53 UTC (today is 2023-07-31)
$range = strtotime('now -30 days');

// Converts the previous timestamp to Y-m-d format
$rangeTimestamp = date('Y-m-d', $range);

// Stores the database service into a variable
$connection = \Drupal::database();

// Query that retrieves rows with column Date (Y-m-d) with a value older than specific range.
$query =  $connection->delete('my_table')
          ->condition('Date', $rangeTimestamp, '<=')
          ->execute();

// If Date is greater or equal '>=', it's inside the range of 30 days.
// If Date is lower or equal '<=', it's outside the range, and is older than 30 days.

```
> 1 votes

---
Tags: database
---


title: All variables invisible to twig files

text:
# Question
Title: All variables invisible to twig files
I created a theme whose minimal.theme file contains the following lines (among others).

```
/**
 * Implements hook_preprocess_HOOK() for node templates.
 */
function minimal_preprocess_node(&$variables) {
  // Declare the test variable and set its value.
  $variables['test_variable'] = 'Hello, this is a test variable!';
}

```

The following is the content of the template file.

```
{#
  This is a custom Twig template for the front page (homepage).
  It will override the default page template for the front page.
#}
<!DOCTYPE html>
<html lang="en">
<head>
  <!-- Head content here -->
</head>
<body>
  <header>
    <h1>Welcome to Our Website</h1>
  </header>

  <main>
    <div class="my-custom-class">
      <p>{{ test_variable }}</p> {# not showing up #}
    </div>
  </main>
</body>
</html>

```

The template file does not show the value for `test_variable`?

What else do I need to do to make `test_variable` usable in the template file?

# Answer
> 4 votes
Variables that are set in `hook_preprocess_node()` are only accessible in node templates. You are trying to access `test_variable` in a page template and that is the reason why that template file does not render any value for `test_variable`.

If you want to add the same variable to all the template files, you should implement `hook_preprocess()`.

```
/**
 * Implements hook_preprocess().
 */
function minimal_preprocess(&$variables, $hook, $info) {
  // Declare the test variable and set its value.
  $variables['test_variable'] = 'Hello, this is a test variable!';
}

```

You could also implement `hook_preprocess()` when the same code is used for more than one template file, but not all the template files. In that case, you can check the value of `$hook`.

```
/**
 * Implements hook_preprocess().
 */
function minimal_preprocess(&$variables, $hook, $info) {
  if ($hook == 'page' || $hook == 'node') {
    // The variable is accessible only from page and node templates.
    $variables['test_variable'] = 'Hello, this is a test variable!';
  }
}

```

---
Tags: theming
---


# Question
Title: How to find image style URL from within twig template?
I'm implementing a node template that uses an image twice; once in a 'normal' way (i.e. using the image style defined in the field's display configuration for that view mode), and the other is as a css background-image property.

I need one of two things:

1. (ideally) a way to get the URL for a different image style of the same image.
2. a way to get the URL for the image field.

I'm struggling to use `dump()` and `kint()` to help myself to an answer. They both output far far too much (thanks to embedded links to "parent" etc.) and seem to not have the info I need. e.g. looking at `dump(content.field_image)` output the actual URL of the image is not there (so where does it come from such that it can be rendered with `{{ content.field_image }}`?!). `kint()` on the other hand dies completely if I pass an argument to it and the top-level version is again far too big to navigate. Debugging was soo much easier with phptemplate + xdebug. (Yes I know it's good that themers can't drop the database.)

There's an answer to (1) that implies you can't do it, but I don't understand why I can't get the existing URL in (2)?

# Answer
You can get the image style url in a preprocess function and pass it to the node template. (in my case, I needed at the page level, I'm guessing this would still work for node)

Something like this, with "myimagefield" being the machine name for your image field, and "myimagestyle" being the machine name for your style, also make sure you include the Entity\ImageStyle.

```
use Drupal\image\Entity\ImageStyle;

/**
 * Implements hook_preprocess_page().
*/
function mytheme_preprocess_page(&$variables, $hook) {
  if ($variables['node']) {
    $node = $variables['node'];
    if($node->myimagefield[0]){
        $cover_image = $node->myimagefield[0]->entity->getFileUri();
        $image_url = ImageStyle::load('myimagestyle')->buildUrl($cover_image);
        $variables['my_image'] = $image_url;
    }
  }
}

```
> 11 votes

# Answer
The first part is already answered in the linked question, where there is the code how to do this. To answer the second part of the question, you can access the original image in the node object:

```
{{ file_url(node.field_image.entity.uri.value) }}

```

One remark about `content`:

In a node template the image field in `content` is not ready to be rendered. The field contains the configuration how it should be displayed and the field object which contains all raw data. Later this will be put together in the field, image-formatter and image templates. That is the reason you don't find the url you are looking for in `content` at this point.

In the node template you can use the fields on the top level of the content array, for example display the image field

```
{{ content.field_image }}

```

as configured in the view mode.

**Edit:**

There is a new filter in the module Twig Tweak. Now you can generate the image style url in twig directly from an uri or url of the original image:

```
{{ node.field_image.entity.uri.value | image_style('thumbnail') }}

```
> 18 votes

# Answer
Install the Twig Tweak Module https://www.drupal.org/project/twig\_tweak

And this module Twig Field https://www.drupal.org/project/twig\_field\_value

If you are using regular image upload field images use this in your node template:

```
<img src="{{ node.field_regular_image.entity.uri.value | image_style('thumbnail') }} " >

```

If you are using entity reference image use this:

```
<img src="{{ file_url(content.field_global_image|field_target_entity.image.entity.uri.value | image_style('thumbnail'))}} " >

```
> 8 votes

# Answer
With twig tweaks you don't need the twig\_field\_value module as in @paulcap1's answer.

```
{% set image_uri = content.field_sbb_background_image['#items']|file_uri %}
{% set image_url =  file_url(image_uri) %}

```

Or if you are printing out with an image style you don't even need the image url. To print, say, the image style thumbnail:

```
{{ image_uri|image_style('thumbnail') }}

```
> 2 votes

# Answer
Thanks to the other contributors. In my situation I needed something slightly different to get it working:

**My solution that I found to work, with background image application of it**

I found this to work with Drupal 9.2.4, with contrib module twig tweak 3.1.2

```
url({{ node.field_background_media.entity.field_media_image.0.entity.uri.value | image_style('background_image_xl') }});

```

**Example - Background image for page**

Here's my example to illustrate the above

I have a field in my content type 'Landing Page', the field is called 'Background Media', machine name `field_background_media`

In my twig template in my own custom theme, (in my case, `web/themes/custom/clau2/templates/content/node--landing-page.html.twig` )for my content type I have:

```
{%
  set bg_img_styled_url = node.field_background_media.entity.field_media_image.0.entity.uri.value | image_style('background_image_xl')
%}

```

Where background\_image\_xl is the machine name of an existing style, listed in `admin/config/media/image-styles`

And then also in my twig, I have, which performs the purpose of providing a background image for the whole page that my content of my content type is on.

```
<style>

#clau-page-container-id {
    background: linear-gradient( rgba(0, 0, 0, 0.5),rgba(0, 0, 0, 0.5) ), url({{ bg_img_styled_url }});
    height: 100vh;
    background-size: cover;
    background-position: left top;
    background-color: rgba(0,0,0,0.5);
}

</style>

```

Where `#clau-page-container-id` is set in in my `html.html.twig` template, `web/themes/custom/clau2/templates/layout/html.html.twig` : -

```
  <body{{ attributes.addClass(body_classes).setAttribute('id', 'clau-page-container-id') }}>

```

( As an aside, in manage display tab of content type, this field is actually in the disabled section of the 'Full' view mode in 'manage display' for my content type ( `admin/structure/types/manage/landing_page/display/full` ), for my purpose - I am using it to provide a background image and don't want it output again by `{{ content }}` . This is only really relevant to my case. If the field is enabled the other steps will still work, because I've seen them myself to have. )

As another aside, my example means that Media entity (and convenient media browser of existing content) can be used for choosing a background image, re-using existing images, without the need for an additional contrib module.

There are good modules like bg\_img\_field, look and modifiers but at time of writing I'm not aware of them using the Media field type, instead they seem to use the 'legacy' image field type - less flexibility - i.e. can't browse for and re-use existing images. See further discussion about this here

**See my example in action here:**

(website I'm working on). I think the screenshot gives good value as to how the above twig actually provides the markup and image output.

And from that we can observe that the required image with the image style applied is used - in that markup shown in the screenshot, the image path is: `sites/default/files/styles/background_image_xl/public/2020-10/Join-us-img.jpg` which contains the `background_image_xl` image style machine name, so that the path as a whole selects the image of that style.
> 2 votes

# Answer
I had a similiar scenario, and needed to get the URL of an image to use for the CSS for a background image for the whole page, except I was using a media entity instead of a file entity. I thought it might be useful to note it here. I also wanted to use the original image URL instead of a particular style. I used a modified version of the first answer:

```
use Drupal\file\Entity\File;

    // Get media file path to add to template variables to use as background image in template

    function mytheme_preprocess_page(&$variables, $hook) {
      if (isset($variables['node'])) {
        $node = $variables['node'];

        if($node->field_image_media[0]){
          $media_entity = $node->field_image_media[0]->entity;
          $file_id = $media_entity->getSource()->getSourceFieldValue($media_entity);
          $bg_file = File::load($file_id);
          $path = $bg_file->createFileUrl();
          $variables['bg_image'] = $path;
        }
      }
    }

```

The difference is after returning the media entity, I then needed an extra step to get the entity for the file, before returning the file URL. (Thanks to Akhilavnair's comment in the How to get image file uri from media entity id thread, in showing how to retrieve the File entity from the media entity)

As this is a page preprocess function the variable was not available for the html.html.twig template, and only for the page.html.twig template. This meant to get the background image to apply to the whole page I needed to wrap the `<header>`, `<main>` and `<footer>` html elements in a `<div>` and apply the style to that wrapper `<div>`.

To retrieve the path and apply the styling I added the following to my page.html.twig:

```
{% if bg_image is defined %}
  {% set bg_style = "background-image:url('" ~ bg_image ~ "'); background-size: cover;" %}
{% endif %}

<div class="box-wrapper" style="{{ bg_style }}">
  <header>
    ...
  </header>
  <main>
    ...
  </main>
  <footer>
    ...
  </footer>
</div>

```

The image I am retrieving from the media field can also be used within the manage display form as normal using any of the available image styles, or it can hidden (as in my case). And voila:
> 1 votes

---
Tags: theming, 8, media
---


# Question
Title: Add target="_blank" in menu items (main navigation)
I use Drupal 8.9.3 with custom theme. I need to do a menu item on the main navigation who go on an external link.

I would like to add `target="_blank"` on this link, but I don't see where I can put that attribute from the user interface.

Do I need a module? I would like to avoid a PHP function.

I tried https://www.drupal.org/project/menus\_attribute/releases/8.x-1.2. I added my attr but nothing appears in my code.

# Answer
> 2 votes
The module for this is menu\_link\_attributes.

# Answer
> 0 votes
Try the Mix module, which allow you to set id/class/target attributes and other advanced settings to menu links.

---
Tags: 8, navigation
---


title: How to fix a broken or missing block?

text:
# Question
Title: How to fix a broken or missing block?
On a Drupal 8 site, I see an error on a block which says:

> This block is broken or missing. You may be missing content or you might need to enable the original module.

How can I resolve this error?

# Answer
You have created a Custom block and the custom block was placed in a region, then you lost the custom block maybe was deleted or you made a Config Export from one environment and a Config Import in other. So the custom block is no longer exists but in the Block layout page (admin/structure/block), the references exist.

So, remove the missing Block from the Block layout page (admin/structure/block) and create again the Custom block and place it again in the region.

There is a core issue open discussing this problem: https://drupal.org/project/drupal/issues/2756331

This can also be overcome by using this module: https://www.drupal.org/project/recreate\_block\_content
> 14 votes

# Answer
The placement of the block is stored as configuration. This is what gets exported and synced between environments. The actual content of the block is considered exactly that: *content*. This means that when you import your new configuration into a different environment (or delete the block and then re-import the configuration) there is a mismatch between the configuration for the block and the actual block instance (which no longer exists).

To resolve this issue, you simply need to delete the configuration for the missing block and then recreate the block. This allows your site to resolve the discrepancies.

Another option would be to use the fixed\_block\_content contributed module to manage this process for you.

There is a Drupal Core issue discussing this very thing. https://drupal.org/project/drupal/issues/2756331
> 6 votes

# Answer
I had the same problem with Views. After trying a different theme, some of my Views blocks were gone. I checked and the actual Views was disabled. I was able to restore it by going to the views page and "enabling" the Views and all the blocks displayed as expected.
> 3 votes

# Answer
This happens because when a block is created, a unique id is generated (uuid). This can be seen from the block\_content table.

A custom block is a piece of content similar to a Node, so if you create a block in one environment (dev for example) and recreate the block manually on a different environment (Production or QA). The block will have a different uuid.

The Configuration Synchronization will be looking for an uuid that doesn't exist. In order to fix this, you need to import the data from the database. Or simply update (id and uuid) on the following tables:

block\_content;

block\_content\_field\_data;

block\_content\__body;

block\_content\_field\_revision;

block\_content\_revision;

block\_content\_revision\__body;
> 3 votes

# Answer
I encountered this myself, using modules or patches did not work for me. Doing the Database fix route, thinking this has something to do with UUIDs or IDs. Everything seems fine. What worked for me to fix this is to modify the `block_content_field_data` table and made sure all the existing blocks for the field `reusable` is not `NULL`

Then do a cache clear for the site and you'll see the missing custom blocks. So far this workaround worked for me.

Oh and i'm at 8.6.13 at this time.
> 2 votes

# Answer
My problem was caused by a block existing only on dev and then configuration pointing to a block that did not exist elsewhere. It came up in Layout Builder. I'm on Drupal 8.7.6 and I was able to simply go in to the layout builder, remove the bad block reference, re-add the correct block and the problem was solved. I just had to be sure to re-export my configuration and update my repo so as not to recreate the problem.
> 1 votes

# Answer
(Expanding on Marcelo's answer)

Steps to reproduce:

1. Block is created
2. Block is added to Block Layout
3. Configs are exported
4. Block is deleted (or does not exist on target)
5. Configs are imported to target
6. Import contains: \[warning\] The "block\_content:\[UUID\]" was not found

Steps to fix:

1. Copy the uuid from the error
2. Find the correct block in the database table - block\_content\*
3. Update the uuid of the block in block\_content with the one from the error
4. Make sure the block is removed from the Block Layout
5. Re-import configs

\*It can be difficult to figure out which entry in the block\_content table is the correct one. If necessary, copy the block data and metadata somewhere, delete the block and then re-add it. The highest id number in the block\_content table will now be the newly created block. Change the uuid on this entry.
> 0 votes

# Answer
**Make Sure the BLOCK ID is the same as in the productions database.**

I solved this issue which occurs while importing the production database to lower environments by deleting the block and creating/configuring it again with the same **block id** that is in the production database.
> 0 votes

# Answer
If you're familiar with drush, you can remove a custom block and related config with two commands. The first one removes the custom block entity.

```
drush entity:delete block block_machine_name

```

The second one removes the block instance from the block config. This is what you see on the Block Layout view.

```
drush config:delete block.block.block_layout_machine_name

```
> 0 votes

# Answer
Try the Content synchronization feature from the Mix module, which allows you to export/import and recreate block contents, menu item links and taxonomy terms between environments (sites)

You can easily choose which items to sync via UI like below:
> 0 votes

---
Tags: 8, blocks
---


# Question
Title: How can I correctly use an if-condition along with a for-loop in Twig 3.x?
The Upgrade Status module tells me this code is no longer valid for Drupal 10 but I'm not sure how that needs to be changed.

```
{% for paragraph in card_page.entity.field_paragraphs if not break %}
  {% set _paragraph = paragraph.entity %}
  {% set _paragraph_type = paragraph.entity.type.entity %}
  {% if _paragraph_type.id == 'landing_hero' %}
    {% set break = true %}
    {% set image_id = _paragraph.field_image.0.entity.id %}
    {% set image_file = file_url(_paragraph.field_image.0.entity.uri.value) %}
  {% endif %}
{% endfor %}

```

# Answer
Drupal 10 updated Twig from 2.x to 3.x. The `{% for ... if ... %}` statement is removed from Twig 3.x.

In Twig 3.x put the if statement outside the loop or in the loop body:

```
{% set break = false %}
{% for paragraph in card_page.entity.field_paragraphs %}
  {% if not break %}
    {% set _paragraph = paragraph.entity %}
    {% set _paragraph_type = paragraph.entity.type.entity %}
    {% if _paragraph_type.id == 'landing_hero' %}
      {% set break = true %}
      {% set image_id = _paragraph.field_image.0.entity.id %}
      {% set image_file = file_url(_paragraph.field_image.0.entity.uri.value) %}
    {% endif %}
  {% endif %}
{% endfor %}

```

See the change record https://www.drupal.org/node/3256890
> 0 votes

---
Tags: theming, 10
---


# Question
Title: Custom views filter plugin: filter over two fields of a custom entity where one of the fields is a multi value field in a seperate table
I have a custom entity with two basefields of type "list\_string": "role" and "additional\_role". I need this as "role" is used for sorting the entities by a very specific logical order (like the "boss" comes first and the "team lead" after the "boss"). The "role" basefield is a simple one-value field which is stored in the entity table in one column but the "additional\_roles" is a multi value field which is therefore stored in a seperate table "my\_entity\__additional\_roles".

What I now want to have is a custom (exposed) filter plugin which allows the user to choose from a list of roles. The result should be filtered over both fields so that when the role "developer" is chosen every entity with this value in "role" OR in "additional\_roles" is listed.

So far I have overwritten the views filter plugin for the "role" field to some custom filter plugin which extends InOperator. My idea was to overwrite the method opSimple() - I did it that way for some other custom filter plugins but there I always was able to filter with fields which are all in the same entity table. For example I checked for a date range over two date fields of another entity:

```
  public function query() {
    $this->ensureMyTable();

    if ($this->value && isset($this->value[0]) && $this->value[0] == 1) {
      $date = $this->getDate();
      if (!$date) {
        $date = date('Y-m-d');
      }
      $this->query->addWhere($this->options['group'], (new Condition('OR'))
        ->condition('end_date', '', 'IS NULL')
        ->condition('end_date', $date, '>='));

      $this->query->addWhere($this->options['group'], (new Condition('OR'))
        ->condition('start_date', '', 'IS NULL')
        ->condition('start_date', $date, '<='));
    }
  }

```

But know I fail in getting the relationship for the multi value field into the views query. My idea is to adjust the query in a way that I could add such an OR subquery including a condition involving the value from the multi value field table.

# Answer
I think the easiest way would be to get all corresponding entity ids to this role and filter the query based on this ids. You can override the opSimple method of the inOperator for example with the following code:

```
protected function opSimple() {
  if (empty($this->value)) {
    return;
  }
  $this->ensureMyTable();

  // Get all corresponding entities of this role.
  $ids = $query = \Drupal::entityTypeManager()->getStorage('custom_entity_type')->getQuery();
  $or_condition = $query->orConditionGroup();
  $or_condition->condition('role', $this->value)
    ->condition('additional_role', $this->value);
  $query->condition($or_condition);
  $query->accessCheck(FALSE);
  $ids = $query->execute();

  if (empty($ids)) {
    // If we haven`t found some entities, we have no results.
    $this->query->addWhereExpression($this->options['group'], '1 != 1');
    return;
  }

  if ($this->operator == 'in') {
    $this->query->addWhereExpression($this->options['group'], "$this->tableAlias.id IN (:ids[])", [':ids[]' => $ids]);
  }
  elseif ($this->operator == 'not in') {
    $this->query->addWhereExpression($this->options['group'], "$this->tableAlias.id NOT IN (:ids[])", [':ids[]' => $ids]);
  }
  else {
    // Adjust if you have other operators.
  }
}

```
> 1 votes

# Answer
Here is a quick tip. I recommend do not spend time on "fighting" with views and separate this feature into UI and Query parts.

* UI element: you can add/adjust it in hook\_form\_views\_exposed\_form\_alter().
* Query part: any suitable views query hooks or hook\_query\_TAG\_alter() (just add specific query tag in views display settings).
> -1 votes

---
Tags: views, database, plugins
---


# Question
Title: Why don't these Composer dependencies allow upgrading to Drupal 10?
I'm currently on Drupal Version 9.5.10, and I cannot update to Drupal 10 due to some depdendancy conflicts.

I updated my database, cleared cache, ran a cron. It doesn't fix.

How can I upgrade to Drupal 10 ? I am currently on Drupal 9.5.10

```
[root@vlstage22 master]#
[root@vlstage22 master]# composer require drupal/core-recommended:10.1.1 drupal/core-composer-scaffold:10.1.1 drupal/core-project-message:10.1.1 -W --ignore-platform-reqs
Do not run Composer as root/super user! See https://getcomposer.org/root for details
Continue as root/super user [yes]?
./composer.json has been updated
Running composer update drupal/core-recommended drupal/core-composer-scaffold drupal/core-project-message --with-all-dependencies
Loading composer repositories with package information
Info from https://repo.packagist.org: #StandWithUkraine
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires drupal/core-recommended 10.1.1 -> satisfiable by drupal/core-recommended[10.1.1].
    - drupal/core-recommended 10.1.1 requires drupal/core 10.1.1 -> found drupal/core[10.1.1] but these were not loaded, likely because it conflicts with another require.

Installation failed, reverting ./composer.json and ./composer.lock to their original content.
[root@vlstage22 master]#

```

composer.json file

```
{
    "name": "drupal/recommended-project",
    "description": "Project template for Drupal 9 projects with a relocated document root",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "homepage": "https://www.drupal.org/project/drupal",
    "support": {
        "docs": "https://www.drupal.org/docs/user_guide/en/index.html",
        "chat": "https://www.drupal.org/node/314178"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    ],
    "require": {
        "php": "^7.3||^8.0",
        "composer/installers": "^1.9",
        "drupal/admin_toolbar": "^3.4",
        "drupal/api": "^2.0@RC",
        "drupal/auto_entitylabel": "^3.0",
        "drupal/bootstrap": "^3.29",
        "drupal/core-composer-scaffold": "^10.0",
        "drupal/core-project-message": "^10.0",
        "drupal/core-recommended": "^10.0",
        "drupal/ctools": "^4.0",
        "drupal/devel": "^5.1",
        "drupal/diff": "^1.1",
        "drupal/encrypt": "^3.1",
        "drupal/entityreference_filter": "^1.4",
        "drupal/flood_control": "^2.3",
        "drupal/fpa": "^4.0",
        "drupal/masquerade": "^2.0@RC",
        "drupal/module_filter": "^4.0",
        "drupal/pathauto": "^1.11",
        "drupal/queue_ui": "^3.1",
        "drupal/search_api": "^1.29",
        "drupal/superfish": "^1.6",
        "drupal/token": "^1.12",
        "drupal/views_bulk_operations": "^4.2",
        "drupal/watchdog_prune": "^2.3",
        "drush/drush": "^11.6",
        "php-imap/php-imap": "^2.0",
        "symfony/finder": "^6.1"
    },
    "conflict": {
        "drupal/drupal": "*"
    },
    "minimum-stability": "stable",
    "prefer-stable": true,
    "config": {
        "sort-packages": true,
        "allow-plugins": {
            "composer/installers": true,
            "drupal/core-composer-scaffold": true,
            "drupal/core-project-message": true
        }
    },
    "extra": {
        "drupal-scaffold": {
            "locations": {
                "web-root": "web/"
            }
        },
        "installer-paths": {
            "web/core": [
                "type:drupal-core"
            ],
            "web/libraries/{$name}": [
                "type:drupal-library"
            ],
            "web/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "web/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "web/themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "drush/Commands/contrib/{$name}": [
                "type:drupal-drush"
            ],
            "web/modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "web/profiles/custom/{$name}": [
                "type:drupal-custom-profile"
            ],
            "web/themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ]
        },
        "drupal-core-project-message": {
            "include-keys": [
                "homepage",
                "support"
            ],
            "post-create-project-cmd-message": [
                "<bg=blue;fg=white>                                                         </>",
                "<bg=blue;fg=white>  Congratulations, you’ve installed the Drupal codebase  </>",
                "<bg=blue;fg=white>  from the drupal/recommended-project template!          </>",
                "<bg=blue;fg=white>                                                         </>",
                "",
                "<bg=yellow;fg=black>Next steps</>:",
                "  * Install the site: https://www.drupal.org/docs/8/install",
                "  * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html",
                "  * Get support: https://www.drupal.org/support",
                "  * Get involved with the Drupal community:",
                "      https://www.drupal.org/getting-involved",
                "  * Remove the plugin that prints this message:",
                "      composer remove drupal/core-project-message"
            ]
        }
    }
}

```

# Answer
> 0 votes
I have taken this file and ran the same command. The full output is:

```
composer require drupal/core-recommended:10.1.1 drupal/core-composer-scaffold:10.1.1 drupal/core-project-message:10.1.1 -W --ignore-platform-reqs
./composer.json has been updated
Running composer update drupal/core-recommended drupal/core-composer-scaffold drupal/core-project-message --with-all-dependencies
Loading composer repositories with package information
Info from https://repo.packagist.org: #StandWithUkraine
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Root composer.json requires drupal/core-recommended 10.1.1 -> satisfiable by drupal/core-recommended[10.1.1].
    - Root composer.json requires drupal/entityreference_filter ^1.4 -> satisfiable by drupal/entityreference_filter[1.4.0].
    - drupal/entityreference_filter 1.4.0 requires drupal/core ^8 || ^9 -> satisfiable by drupal/core[8.0.0, ..., 8.9.20, 9.0.0, ..., 9.5.10].
    - You can only install one version of a package, so only one of these can be installed: drupal/core[8.0.0, ..., 8.9.20, 9.0.0, ..., 9.5.10, 10.0.0, ..., 10.1.2].
    - You can only install one version of a package, so only one of these can be installed: drupal/core[8.7.0, ..., 8.9.20, 9.0.0, ..., 9.5.10, 10.0.0, ..., 10.1.2].
    - drush/drush 11.6.0 conflicts with drupal/core 9.1.15.
    ...
    - drupal/core-recommended 10.1.1 requires drupal/core 10.1.1 -> satisfiable by drupal/core[10.1.1].
    - Root composer.json requires drush/drush ^11.6 -> satisfiable by drush/drush[11.6.0].

```

So the issue is:

```
drupal/entityreference_filter 1.4.0 requires drupal/core ^8 || ^9

```

drupal/entityreference\_filter is not compatible with Drupal 10. You must remove it or use the beta version:

```
composer require drupal/core-recommended:10.1.1 drupal/core-composer-scaffold:10.1.1 drupal/core-project-message:10.1.1 'drupal/entityreference_filter:^2.0@beta'  -W --ignore-platform-reqs

```

# Answer
> 1 votes
Looks like the command you are running is `composer require...` that's incorrect you need to run composer update. Please see the docs they are very clear and easy to follow https://www.drupal.org/docs/updating-drupal/updating-drupal-core-via-composer

---
Tags: composer
---


title: fix-permissions.sh for Drupal 8

text:
# Question
Title: fix-permissions.sh for Drupal 8
With Drupal 7, when I upload a project from local to server, I usually run fix-permisions shell script to change owner and permissions of folder/files.

Is provided in : https://www.drupal.org/node/244924#script-based-on-guidelines-given-above

This script, may not work with Drupal 8, I had some trouble when running it.

Is there something similar to Drupal 8 version?

# Answer
> 1 votes
Finally, after some tries and fixes in Server config, I solve the problem running the shell script provided in:

https://www.drupal.org/node/244924#script-based-on-guidelines-given-above

It works in version 8 correctly as it do in version 7.

# Answer
> 1 votes
Here you can find a script that fixes permissions on Drupal installations: https://github.com/Metadrop/drupal-fix-permissions-script

Permissions scheme:

> The scripts tries to secure the site using the following scheme:
>
> * Code is owned by the deploy user and by the web server's group. Deploy user can write, web server group only read.
> * Content is owned using the same scheme but the web server can write as well.
> * Other users have no permissions on content or code.

Strategy:

> The scripts checks if the target folder is a Drupal installation and stops if it is not detected.
>
> Once checked, it fixes the ownership of all folder and files (because it is the same for content and code). Then, it fixes the code and later the content.
>
> The script assumes that files and private folders under sites are content folders.
>
> If there are content folders outside the Drupal root folder you can use the --files-path option and the script will take care of it.

Performance

> The script only changes the files and folder with the wrong permissions or ownership, making it very fast when only a few files or folders need a fix. For really big installations this is very important as other scripts apply the permissions and ownership regardless are needed o not.

DISCLAIMER: I'm the author of the script.

---
Tags: 8, security
---


# Question
Title: How to place 2 blocks on same page which are based off page's rendered content?
To be honest, not sure of a good title for this. This is the issue:

I am using the TOC API to create a block. This API requires parsing the node content to determine the heading structure (H2s, H3s, etc). The module does not include a block for this as it is just an API module. I wrote a custom block to use the API to create this block. This works fine.

I now have a use case where I need to put multiple versions of this block on the page, but I am only able to render one of them. This has nothing to do with the TOC API but how the node content is rendered in the block code. I have simplified the code to remove all the API parts:

```
  public function build() {
    // Required to break block - render page - insert block - render page, etc, etc.
    $rendered = &drupal_static('toc_block_rendered');
    if (isset($rendered) && in_array($this->configuration['toc_type'], $rendered)) return [];
    else $rendered[] = $this->configuration['toc_type'];

    $build = [];

    // Get TOC Type configured for this Block.
    $toc_type_id = $this->configuration['toc_type'];

    $node = \Drupal::routeMatch()->getParameter('node');
    $view_builder = \Drupal::entityTypeManager()->getViewBuilder('node');
    $full_content = $view_builder->view($node, 'full');
    $content = (string) \Drupal::service('renderer')->render($full_content);

    return ['#markup' => $this->configuration['toc_type']];
  }

```

$this-\>configuration\['toc\_type'\] is a configuration value set for the block instance and is set differently for each of the 2 blocks I have placed on the page.

The static var code at the top is required to break the recursive loop caused due to trying to render the page which has the block which tries to render the page which has the block.. and so on and so on.

This simplified block just renders the block's config value. Although 2 of them are added to the node layout; only one gets shown. If I comment out the $view\_builder-\>view($node, 'full') line; then both are displayed correctly.

I have tried multiple approaches such as static and even session vars for the rendered content; but with no luck. I also tried cloning or createDuplicate() of the node but this also does not help.

Can anyone explain why this is being broken by running this code for a 2nd instance of the block and if there is a better way to do this?

NOTE: the session var idea does work but the code I had for this isn't properly seeded the first time through. The 2nd refresh of the page shows both blocks. I would need a way to set for the first time and then also to clear these in a later hook (hook\_node\_view). But ugly approach.

# Answer
Did you consider a #post\_render callback to avoid the early and recursive rendering?

If you want to place the block via UI in the node layout then return from the block builds static placeholders. For example:

```
return ['#markup' => '<span toc-data="' . $this->configuration['toc_type'] . '"></span>'];

```

Otherwise you could simply put the placeholders directly in the node build in the same hook where you add the callback.

The post render callback receives the entire HTML of the node layout which it can use for the TOC API and then replace the placeholders.

See How to alter page content?
> 0 votes

---
Tags: 9
---


# Question
Title: How to set a webform default value for anonymous user?
I have been using hook form alter for a webform, to set a default value for a webform added as a block to a page. Below is the code, the code only works for users who have logged, but for anonymous or non logged in user the field is not working with a default value even with else condition or with anonymous check. what is wrong in the code below?

```
function mytheme_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
{
$current_role = \Drupal::currentUser()->getRoles();
if ($form_id == 'webform_submission_add_form'){
  if (in_array("user1", $current_role)) {
     $form['elements']['user']['#default_value'] = 'logged';
    }
  else{
     $form['elements']['user']['#default_value'] = 'not logged';
    }
  if (\Drupal::currentUser()->isAnonymous()) {
     $form['elements']['user']['#default_value'] = 'not logged';
     }
  if (in_array("anonymous", $roles)) {
     $form['elements']['user']['#default_value'] =
     'not logged';
     }
   }
}

```

# Answer
> 1 votes
Webform has the built-in ability to define default values for form fields when they're empty. If I remember correctly, it's in the Advanced section when you configure a field. The default value accepts either a static value or a token. Create a custom token if you want to programmatically generate the default value, then configure the webform field to use that token as the default value.

I recommend doing it this way to not hardcode that logic to a specific form, i.e. you can reuse that token in another form. You can also remove it easily from admin without going into code, should you not want it anymore.

---
Tags: theming, hooks, webforms
---


# Question
Title: Can I use entityQuery() in a Drupal 10 site to query entities from a Drupal 7 database?
Can I use entityQuery() to query entities in a Drupal 7 table?

I know it's possible to change the active database and then use a dynamic query to access the database, but can I do that also with entityQuery(), or does it only work with the default database?

# Answer
> 1 votes
The object returned from `Drupal::entityQuery()`, in Drupal 10, assumes the database has been created from Drupal 10. It will not work with a database created from Drupal 7 because Drupal 7 creates different tables which have different schemas.

With the object returned by `Drupal::database()`, you could query entities from a Drupal 7 database, but you would need to adjust the query for the schema used from Drupal 7.
Since you are directly querying the database table, that is not different from querying a database table that is not for entities, as long as you keep in mind the schema used for those tables in Drupal 7.

---
Tags: entities, database, 10
---


title: How do I port this event subscriber?

text:
# Question
Title: How do I port this event subscriber?
The following code works fine with Drupal 9.

```

namespace Drupal\vl_login\EventSubscriber;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
// use Symfony\Component\EventDispatcher\Event;
use Drupal\Component\EventDispatcher\Event;

/**
 * Event subscriber subscribing to KernelEvents::REQUEST.
 */
class RedirectAnonymousSubscriber implements EventSubscriberInterface {

  public function __construct() {
    $this->account = \Drupal::currentUser();
  }

  public function checkAuthStatus(GetResponseEvent $event) {

    $allowed = [
      'user.logout',
      'user.register',
      'user.login',
      'user.reset',
      'user.reset.form',
      'user.reset.login',
      'user.login.http',
      'user.logout.http',
      'user.pass'
    ];

    //redirect anonymous user to user login page
    if ( ($this->account->isAnonymous()) && ( !in_array(\Drupal::routeMatch()->getRouteName(), $allowed)) ) {
      $response = new RedirectResponse('/user/login', 302);
      $response->send();
    }
  }

  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = array('checkAuthStatus');
    return $events;
  }
}

```

### The module file

```

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\Core\Link;

/**
 * Implements hook_form_FORM_ID_alter().
 */
function vl_login_form_user_login_form_alter(&$form, FormStateInterface $form_state) {
  $form['#submit'][] = 'vl_login_user_login_submit';
}

/**
 * Form submission handler for user_login_form().
 *
 * Redirects the user to the dashboard after logging in.
 */
function vl_login_user_login_submit(&$form, FormStateInterface $form_state) {

  $url = Url::fromRoute('vl_login.dashboard');

  // Check if a destination was set, probably on an exception controller.
  // @see \Drupal\user\Form\UserLoginForm::submitForm()
  $request = \Drupal::service('request_stack')->getCurrentRequest();

  if (!$request->request->has('destination')) {
    $form_state->setRedirectUrl($url);
  }
  else {
    $request->query->set('destination', $request->request->get('destination'));
  }
}

```

I upgraded to Drupal 10 and I am not able to log in after I changed class from `Symfony\Component\EventDispatcher\Event` to `Drupal\Component\EventDispatcher\Event` because I get this exception.

> TypeError: `Drupal\vl_login\EventSubscriber\RedirectAnonymousSubscriber::checkAuthStatus()`: Argument #1 ($event) must be of type `Drupal\vl_login\EventSubscriber\GetResponseEvent`

# Answer
The correct Drupal 10 version would be using `RequestEvent`:

```
  public function checkAuthStatus(RequestEvent $event) {

    $allowed = [
      'user.logout',
      'user.register',
      'user.login',
      'user.reset',
      'user.reset.form',
      'user.reset.login',
      'user.login.http',
      'user.logout.http',
      'user.pass'
    ];

    //redirect anonymous user to user login page
    if ($this->account->isAnonymous() && !in_array(\Drupal::routeMatch()->getRouteName(), $allowed)) {
      $response = new RedirectResponse('/user/login', 302);
      $event->setResponse($response);
    }
  }

```

For all Drupal versions since Drupal 8, don't send a response, set it in the event.

And add the use statement at the top:

```
use Symfony\Component\HttpKernel\Event\RequestEvent;

```
> 4 votes

---
Tags: event-subscribers
---


# Question
Title: Why should a Drupal copy be extracted in the web directory?
I am trying to create a multi-site using Set up a multisite, but I do not understand the reason for step 1.2.

Why should a Drupal copy be extracted in the web directory?

There doesn't seem to be anything written about this.

# Answer
That refers to installing Drupal in the ordinary way. Using the recommended install process to the directory referred to as “base-site”, which could have any name you want, there will be a subdirectory named “web” that you will reference in the virtual host configuration.
> 0 votes

---
Tags: files
---


# Question
Title: in hook_views_pre_render, how to get the current display of the ViewExecutable
I have this code:

```
function my_module_views_pre_render(\Drupal\views\ViewExecutable $view) {
  if (isset($view) && $view->storage->id() == 'myview') {
    // Do something.
  }
}

```

This runs my code for all displays of my view, hoever, if I have page\_1 and page\_2 displays, and I only want to pre-render page\_2, I can't figure it out:

I am looking for something like this:

```
function my_module_views_pre_render(\Drupal\views\ViewExecutable $view) {
  if (isset($view) && $view->storage->id() == 'myview' && $view->getDisplayId() == 'page_2') {
    // This does not work
    // Do something.
  }
}

```

# Answer
> 0 votes
It's just `$view->current_display === 'page_2'` that you're looking for. Also, in my experience, you don't need "storage" to get the view id; you can just use `$view->id()`

---
Tags: views
---


title: Run drush cron for a single module

text:
# Question
Title: Run drush cron for a single module
Is it possible to run drush cron over a single module, something similar to "drush cron my\_module"?

# Answer
You can do

```
drush php-eval 'my_module_cron();'

```

and it should run.
> 26 votes

# Answer
If you install the contrib project Ultimate Cron, you get extra Drush commands including:

```
drush cron:run my_module

```

which allows you to run a cron for a specific module.
> 0 votes

# Answer
You can implement your own drush commands. Have look at the sandwich example code in the drush source package.
> -1 votes

# Answer
I think you can just use,

```
drush cron module_name

```
> -1 votes

---
Tags: drush, cron
---


# Question
Title: Why am I getting "Page not found" for a simple "hello world" custom page
In my custom module, ed\_helper, I have this ed\_helper.routing.yml:

```
ed_helper.my_page:
  path: '/mypage/page'
  defaults:
    _controller: '\Drupal\ed_helper\Controller\EdHelperController::myPage'
    _title: 'My first page in D8'
  requirements:
    _permission: 'access content'

```

In ed\_helper/src/Controller, I have this EdHelperController.php:

```
<?php
namespace Drupal\ed_helper\Controller;

use Drupal\Core\Controller\ControllerBase;

/**
 * Utility pages.
 */
class EdHelperController extends ControllerBase {

  /**
   * Returns a simple page.
   *
   * @return array
   *   A simple renderable array.
   */
  public function myPage() {
    return [
      '#markup' => 'Hello, world',
    ];
  }

}

```

I have confirmed that the module is installed, and I cleared the cache, but am still getting "Page not found" at /mypage/page. What am I missing?

I tried switching the theme to Claro, but I still get "page not found" at my custom route. I also tried uninstalling ed\_helper and re-installing it.

My Drupal version is 10.1.

# Answer
You can create the same simple hello world custom page with Drush:

```
drush generate module

```

Enter a module name `mymodule` and skip all questions except the one for a controller where you answer yes.

Install the module

```
drush en mymodule

```

and then visit *www.example.com/mymodule/example* to see the controller result.
> 0 votes

---
Tags: page-controller, 10
---


# Question
Title: Hide field programmatically in "manage display"
I develop a contrib module. I added a new field to "user" entity. I need to hide this field from display in "manage display"

I run this code

```
$entity_view_display = \Drupal::entityTypeManager()
  ->getStorage('entity_view_display')
  ->load('user.user.default');
if ($entity_view_display) {
  $entity_view_display->setComponent('field_myfield', [
    'region' => 'hidden',
  ])->save();
}

```

In "manage display" page (/admin/config/people/accounts/display) I see that my field moved to "hidden" region, but when I view user profile I see my field.

If I press "save" button in "manage display" page my field is gone when I view user profile.

How to resave "manage display" programmatically? Is it possible?

# Answer
You can use EntityDisplayBase::removeComponent():

```
$entity_view_display->removeComponent('field_myfield')->save();

```
> 2 votes

---
Tags: entities, 10
---


# Question
Title: Using common database for multiple developers in local environment gets slow
When use the **common database to develop in local environment for multiple developers** in one **Drupal 9** project is getting too slow. This issue occurs on Drupal sites only, others (**Wordpress, Laravel, Codeigniter and slim**) are working fine with the same database from the server and found that not an network and server issue. In our scenario, we want to use a common database for multiple developers in our local environment for a Drupal 9 project. We may clear the cache frequently during the development process.Can you give me any suggestions for achieving this process?

Used the common database from host server to develop in local environment for multiple developers in one Drupal 9 project. But it gets slow when loading (for ex. doing CRUD operation, cache clear and etc).

Could any one provide the suggestion to implement the common database for multiple developers in local environment Drupal sites?

# Answer
Yes. There is a documented base configuration for performance with MySQL. It is too long to quote here. It includes instructions for next steps if needed.
> 0 votes

---
Tags: database, 9, caching, performance
---


title: How to avoid converting URLs to links?

text:
# Question
Title: How to avoid converting URLs to links?
Using CKeditor5 in Drupal site... is there a way to avoid converting a specific URL to link in a specific page or paragraph? How?

**Update: explanation**

I have a paragraph where I give the bibtex to copy; one of the entries of the bibtex is an url which has to be presented like in this picture:

But CKeditor5 presents it this way:

```
howpublished = {\href{<a href="http://www.chandia.net/corlexim">http://www.chandia.net/corlexim</a>}{<a href="http://www.chandia.net/corlexim">http://www.chandia.net/corlexim</a>}},

```

Note that in this explanation I have entered the line as it should be presented but it has been automatically converted to links...

# Answer
> 3 votes
I can reproduce this only when the node is using the *Full HTML* input format an the *Convert URLs into links* filter is enabled for that input format. In this case, a node that contains `<textarea>howpublished = {\href{http://www.chandia.net/corlexim}{http//www.chandia.net/corlexim}}</textarea>` is rendered as the following screenshot shows.

>

The only way to avoid that is disabling the *Convert URLs into links* filter in /admin/config/content/formats/manage/full\_html. When I do that, the node is rendered as expected.

>

# Answer
> 0 votes
Thanks to @apademo's answer I came up with the idea (actually it is so logically obvious) of creating a new "text format" in Drupal which **does not** have activated "Convert URLs into links" option, but it has all of the others (or the ones you need) that make it a "Complete Html" format.

Then, I have applied that format to the page where I don't want the urls converted into links...

Obviously, if there is some other URL in the same page that you do want to convert into link, you will have to do it manually:

```
<a href="https://www.example.com">Manualy Linked URL</a>

```

Thanks for the answers!

---
Tags: wysiwyg
---


# Question
Title: Webform Create node, send email when webform is submitted
I'm creating a node when a webform is submitted and adding the webform submission id to an int field on the node so the node is linked to the webform submission. I'm also sending an email when the webform is submitted.

Here's the node creation handler code.

```
<?php

namespace Drupal\my_module\Plugin\WebformHandler;

use Drupal;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\Node;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\webformSubmissionInterface;

/**
 * Create Award Nominee nodes from a webform submission.
 *
 * @WebformHandler(
 *   id = "award_nominee_from_webform",
 *   label = @Translation("Award Nominee node"),
 *   category = @Translation("Webform"),
 *   description = @Translation("Creates an Award Nominee node."),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_UNLIMITED,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 *   submission = \Drupal\webform\Plugin\WebformHandlerInterface::SUBMISSION_REQUIRED,
 * )
 */

class AwardNomineeWebformHandler extends WebformHandlerBase {

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
    $webform = $webform_submission->getWebform();
    // Get an array of form field values.
    $submission_array = $webform_submission->getData();
    // Todo: Prevent this save from sending emails.
    $webform_submission->save();

    $sid = $webform_submission->id();

    $term = \Drupal::entityTypeManager()
      ->getStorage('taxonomy_term')
      ->load($submission_array['nomination_award']);
    $award_name = $term->getName();

    if (empty($submission_array['member_information'])) {
      $nominee_middle_name = !empty($submission_array['nominee_middle_name']) ? ' ' . $submission_array['nominee_middle_name'] . ' ' : ' ';
      $title = $submission_array['nominee_first_name'] . $nominee_middle_name . $submission_array['nominee_last_name'];
      $nominee_accomplishments = $submission_array['nominee_accomplishments'];

      $this->getNode($title, $award_name, $nominee_accomplishments, $sid);
    }
  }

  /**
   * Creates the node when it's a new webform submission.
   *
   * @param string $title
   * @param string $award_name
   * @param mixed $nominee_accomplishments
   * @param int $sid
   *
   * @return void
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  protected function getNode(string $title, string $award_name, mixed $nominee_accomplishments, int $sid): void {
    $node = Node::create([
      'type' => 'award_nominee',
      'status' => FALSE,
      'title' => $title,
      'field_award_nominee_plaque_name' => '',
      'field_award_nominee_award_name' => $award_name,
      'field_award_nominee_organization' => '',
      'field_award_nominee_members' => '',
      'body' => [
        'value' => $nominee_accomplishments,
        'format' => 'bold_italic',
      ],
      'field_webform_submission_id' => $sid,
      'field_award_nominee_city' => '',
      'field_award_nominee_state' => '',
    ]);
    $node->save();
  }

}

```

There's even a hook to delete the nodes when the submission is deleted. Here's the hook:

```
/**
 * Implements hook_webform_submission_delete().
 */
function my_module_webform_submission_delete(WebformSubmissionInterface $webform_submission) {
  $entity_ids = Drupal::entityQuery('node')
    ->condition('type', 'award_nominee')
    ->condition('field_webform_submission_id.value', $webform_submission->id())
    ->execute();
  $nodes = Node::loadMultiple($entity_ids);
  foreach ($nodes as $node) {
    $node->delete();
  }
}

```

Although I think another webform handler could "handle" the deletions too.

The problem is the emails are being sent: one from the configured email handler, and one from the `webform_submission->save()` in the node creation handler. How can I prevent an email being sent from the node creation handler? `$webform_submission->resave()` seems to solve the problem like this.

```
$sid = '';
if ($webform_submission->id()) {
  $webform_submission->resave();
  $sid = $webform_submission->id();
}

```

# Answer
Use \Drupal\webform\Entity\WebformSubmission::resave instead of \Drupal\webform\Entity\WebformSubmission::save
> 1 votes

---
Tags: webforms, 9
---


title: Can not get the module by composer

text:
# Question
Title: Can not get the module by composer
My Drupal Version is 9.5.10 PHP Version 8.1.18 I am trying to get the module: `composer require 'drupal/rocket_chat:^3.0'`

But unsuccessful: Problem 1

* Root composer.json requires drupal/rocket\_chat, it could not be found in any version, there may be a typo in the package name.

composer.josn

```
    "name": "drupal/recommended-project",
    "description": "Project template for Drupal 9 projects with a relocated document root",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "homepage": "https://www.drupal.org/project/drupal",
    "support": {
        "docs": "https://www.drupal.org/docs/user_guide/en/index.html",
        "chat": "https://www.drupal.org/node/314178"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8",
        "type": "composer",
        "url": "https://asset-packagist.org"
    }
    ],
    "require": {
        "bower-asset/swagger-ui": "^5.1",
        "composer/installers": "^1.9",
        "drupal/admin_toolbar": "^3.4",
        "drupal/advanced_cors": "^1.4",
        "drupal/aet": "^2.0@alpha",
        "drupal/auto_entitylabel": "^3.0",
        "drupal/better_exposed_filters": "^6.0",
        "drupal/bootstrap": "^3.29",
        "drupal/captcha": "^2.0",
        "drupal/chat_livehelperchat": "^1.3",
        "drupal/colorbox": "^2.0",
        "drupal/configure_contextual_links": "^1.0@alpha",
        "drupal/core-composer-scaffold": "^9.5",
        "drupal/core-project-message": "^9.5",
        "drupal/core-recommended": "^9.5",
        "drupal/country": "^1.1",
        "drupal/dashboards": "^2.1",
        "drupal/date_popup": "^2.0",
        "drupal/dbug": "^2.0",
        "drupal/devel": "^5.1",
        "drupal/diff": "^1.1",
        "drupal/draggableviews": "^2.1",
        "drupal/entity": "^1.4",
        "drupal/entity_reference_views": "^1.1@beta",
        "drupal/field_group": "^3.4",
        "drupal/file_entity": "^2.0@RC",
        "drupal/flags": "^1.0@beta",
        "drupal/flood_control": "^2.3",
        "drupal/fpa": "^4.0",
        "drupal/google_analytics": "^4.0",
        "drupal/imce": "^3.0",
        "drupal/jquery_ui": "^1.6",
        "drupal/libraries": "^4.0",
        "drupal/masquerade": "^2.0@RC",
        "drupal/media_bulk_upload": "^3.0",
        "drupal/module_filter": "^4.0",
        "drupal/paragraphs": "^1.15",
        "drupal/pathauto": "^1.11",
        "drupal/phone_number": "^2.0@alpha",
        "drupal/profile": "^1.7",
        "drupal/rdf": "^2.1",
        "drupal/recaptcha": "^3.2",
        "drupal/rules": "^3.0@alpha",
        "drupal/services": "^4.0@beta",
        "drupal/site_verify": "^2.0@alpha",
        "drupal/smart_date": "^4.0",
        "drupal/smtp": "^1.2",
        "drupal/swagger_ui_formatter": "^4.0",
        "drupal/typed_data": "^1.0@beta",
        "drupal/ultimate_cron": "^2.0@alpha",
        "drupal/username_validation": "^1.2",
        "drupal/userpoints": "^2.0@beta",
        "drupal/views_autocomplete_filters": "^1.4",
        "drupal/views_bulk_operations": "^4.2",
        "drupal/views_dates": "^1.1",
        "drupal/watchdog_prune": "^2.3",
        "drupal/xmlrpc": "^1.0@RC",
        "drupal/xmlsitemap": "^1.4",
        "oomphinc/composer-installers-extender": "^2.0"
    },
    "conflict": {
        "drupal/drupal": "*"
    },
    "minimum-stability": "stable",
    "prefer-stable": true,
    "config": {
        "allow-plugins": {
            "composer/installers": true,
            "drupal/core-composer-scaffold": true,
            "drupal/core-project-message": true,
            "dealerdirect/phpcodesniffer-composer-installer": true,
            "oomphinc/composer-installers-extender": true
        },
        "sort-packages": true
    },
    "extra": {
        "drupal-scaffold": {
            "locations": {
                "web-root": "web/"
            }
        },
    "installer-types": ["bower-asset", "npm-asset"],
        "installer-paths": {
            "web/core": [
                "type:drupal-core"
            ],
            "web/libraries/{$name}": [
                "type:drupal-library",
        "type:bower-asset",
        "type:npm-asset"
            ],
        "web/libraries/swagger-ui": ["bower-asset/swagger-ui"],
            "web/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "web/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "web/themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "drush/Commands/contrib/{$name}": [
                "type:drupal-drush"
            ],
            "web/modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "web/profiles/custom/{$name}": [
                "type:drupal-custom-profile"
            ],
            "web/themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ]
        },
        "drupal-core-project-message": {
            "include-keys": [
                "homepage",
                "support"
            ],
            "post-create-project-cmd-message": [
                "<bg=blue;fg=white>                                                         </>",
                "<bg=blue;fg=white>  Congratulations, you’ve installed the Drupal codebase  </>",
                "<bg=blue;fg=white>  from the drupal/recommended-project template!          </>",
                "<bg=blue;fg=white>                                                         </>",
                "",
                "<bg=yellow;fg=black>Next steps</>:",
                "  * Install the site: https://www.drupal.org/docs/installing-drupal",
                "  * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html",
                "  * Get support: https://www.drupal.org/support",
                "  * Get involved with the Drupal community:",
                "      https://www.drupal.org/getting-involved",
                "  * Remove the plugin that prints this message:",
                "      composer remove drupal/core-project-message"
            ]
        }
    }
}

```

# Answer
> 1 votes
The repositories section is syntactically broken. It should be:

```
"repositories": [
    {
        "type": "composer",
        "url": "https://packages.drupal.org/8"
    },
    {
        "type": "composer",
        "url": "https://asset-packagist.org"
    }
],

```

---
Tags: composer
---


# Question
Title: How do I aggregate the number of posts for each selection of a specific field?
# Background

I have a custom content type "Change Request" that has an "Urgency" field which is a list with three options to choose from:

* Low (3 or more days)
* Medium (Less than 3 days)
* High (Emergency)

I created four change requests with sample data and tried to create a view with an unformatted list that shows how many change requests there are with each selection.

When I try to create this view, the result shows duplicate entries with a count of 1 instead of grouping the duplicate results and showing their combined count.

## Current Result (Incorrect)

```
Low (3 or more days)
1
High (Emergency)
1
Medium (Less than 3 days)
1
Low (3 or more days)
1

```

## Desired Result

```
High (Emergency)
1
Medium (Less than 3 days)
1
Low (3 or more days)
2

```

## Goal

My end goal is to use the result to create Charts using the Charts module. The docs for this module recommend setting the aggregator up with an unformatted list or table and then switching the format to Charts.

# Setup

1. Created a view showing the content type **Change request** with the format **Unformatted list of fields**
2. Added Urgency field to fields twice (once for labels, again for data)
3. Enabled **use aggregation**
4. For the first Urgency field, I used the aggregation settings **Group Results Together** and set the column to **Value**
5. For the second Urgency field, I used the aggregation settings **Count**

# Attempted Solutions

1. Searched for the solution on the Module Issues page and Drupal Stack Exchange. I found some solutions where the problem was similar, but none of them worked for me.
2. Several different modules including Field Count Formatter and Views Aggregator Plus. The first one only counted how many options were selected for the field in each change request (always resulted in 1), and the second one was not compatible with the Charts module so it was not an option.
3. Tried multiple variations for the aggregator settings for each field unsuccessfully.
4. Attempted to use the Table format with the same duplicated results. Also attempted to do this directly in the Charts module, once again with the same results.
5. Found a SQL query that does what I want but was unsuccessful in replicating this using the Views module.

## Working SQL Query

I successfully used GROUP BY and COUNT with the below query:

```
SELECT field_urgency_value, COUNT(field_urgency_value)
FROM node__field_urgency
GROUP BY field_urgency_value;

```

This results in:

```
+---------------------------+-------+
| field_urgency_value       | count |
+---------------------------+-------+
| Low (3 or more days)      | 2     |
+---------------------------+-------+
| Medium (Less than 3 days) | 1     |
+---------------------------+-------+
| High (Emergency)          | 1     |
+---------------------------+-------+

```

However I was unable to replicate these results in Views.

# Answer
The problem turned out to be a Sort Criteria that was added by default to the view. The default "Sort by: authored by" caused issues with the aggregation and duplicated labels, but the issue was resolved as soon as this option was removed.
> 0 votes

---
Tags: views, charts
---


# Question
Title: Why is my pie chart showing multiple labels and incorrect count?
# Background

I have a site where users can submit change requests. I created a custom content type "Change Request" which has numerous fields in it, some of which I want to generate charts for.

One of these fields is a **list** called "urgency" which includes the options "Low", "Medium" and "High". Only one option can be selected per change request.

# Goal

I created 4 change requests with sample data which I am using to generate a chart. My goal is to create a pie chart that shows the number of change requests that falls under each urgency level.

# Issue

I am experiencing two related issues which I believe are stemming from an issue with my aggregation settings. First, the labels are being duplicated, and second, those duplicated values are being counted and charted separately instead of being combined into one item on the chart.

For example, I have 2 change requests that are "Low" urgency, and the other two change requests are "Medium" and "High" respectively. Instead of having this reflected in the pie chart, it is showing "Low" as two separate labels, and both of them has a count of 1. These should be instead combined into a single label with a count of 2. I understand that I need to aggregate the results, but I am struggling to achieve this.

# Setup

* I created a new view called "Overview".
* The view settings are set to show Content of type "change requests".
* I enabled create a page and set it to display a chart of fields.
* I enabled Advanced \> Other \> Use aggregation on the display.
* I added the Urgency field to be used as a label.
* I added the Urgency field a second time to be used as data. For this, I attempted multiple aggregation functions listed below in attempts. **This is the same urgency field**, but I am using it once for labels, and again to count the number of requests for each value in the field.
* I clicked Format \> Chart \> Settings and set my label and data fields to match the above fields.

# Attempts

## First Attempt: Using Field Count Formatter

1. I tried using the Field Count Formatter module at first, but I discovered that this was not counting the amount of content with that field, but is rather counting the number of items in the field. This resulted in a count of 1 for each urgency even if there was multiple change requests with one of the urgencies.

## Second Attempt: Using aggregation settings

1. For the duplicate labels, I set the aggregation type to "Group results together" and set the Group Column to "Value". My thoughts were that it would group the duplicate values together but this didn't do anything.
2. For the counts being separate for the duplicate values, I set the aggregation type to "Count" but this didn't seem to do anything. I also attempted "Count Distinct". I also attempted to use grouping settings.

# More Info

* Drupal 10
* Module: https://www.drupal.org/project/charts
* I'm using Charts with views integration, not programmatically
* I read Charts documentation but it is limited and doesn't touch on aggregation
* I looked for aggregation documentation but I couldn't find anything that helped
* Charting Library: Highcharts

# Answer
> 0 votes
As per this question:

> The problem turned out to be a Sort Criteria that was added by default to the view. The default "Sort by: authored by" caused issues with the aggregation and duplicated labels, but the issue was resolved as soon as this option was removed.

---
Tags: views, charts, 10
---


# Question
Title: Override contrib module's template for an admin module
I need to override a contrib module's template for an admin module. For example, the webform\_composite module has `hook_theme()` in its module file.

```
/**
 * Implements hook_theme().
 */
function webform_composite_theme() {
  return [
    'webform_composite' => [
      'render element' => 'element',
    ],
  ];
}

```

and a template in its templates folder at

```
modules/contrib/webform_composite/templates/webform-composite.html.twig

```

Changes made to the template print on the webform. I don't want to make changes to the module's template and I don't want to make a sub-theme of the admin theme. I want to override the contrib module's template in my custom module.

In my custom module, `hook_theme()` is like this:

```
/**
 * Implements hook_theme().
 */
function my_module_theme($existing, $type, $theme, $path) {
  return [
    'webform_composite__custom' => [
      'base hook' => 'webform_composite',
    ],
  ];
}

```

And `hook_theme_suggestions_alter()` is like this:

```
/**
 * Implements hook_theme_suggestions_alter().
 */
function my_module_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  if ($hook === 'webform_composite') {
    $suggestions[] = $hook . '--' . 'custom';
  }
}

```

as well as adding a template in modules/custom/my\_module/templates/webform-composite--custom.html.twig

This adds my template but not as an override since `webform-composite.html.twig` still has the `x`.

```
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'webform_composite' -->
<!-- FILE NAME SUGGESTIONS:
   * webform-composite--my-award.html.twig
   * webform-composite--custom.html.twig
   x webform-composite.html.twig
-->
<!-- BEGIN OUTPUT from 'modules/contrib/webform_composite/templates/webform-composite.html.twig' -->

```

How do I override a contrib module's template for an admin module?

# Answer
Changing `'--'` to `__` in the $suggestions array fixed the problem per this core issue: hook\_theme\_suggestions\_alter does not work for hyphens

Here's the working code:

```
/**
 * Implements hook_theme().
 */
function my_module_theme($existing, $type, $theme, $path) {
  return [
    'webform_composite__custom' => [
      'base hook' => 'webform_composite',
    ],
  ];
}

/**
 * Implements hook_theme_suggestions_alter().
 */
function my_module_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  if ($variables['theme_hook_original'] == "webform_composite") {
    $suggestions[] = $hook . '__' . 'custom';
  }
}

```

Now the debug reports:

```
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'webform_composite' -->
<!-- FILE NAME SUGGESTIONS:
   * webform-composite--my-award.html.twig
   x webform-composite--custom.html.twig
   * webform-composite.html.twig
-->
<!-- BEGIN OUTPUT from 'modules/custom/my_module/templates/webform-composite--custom.html.twig' -->

```

The first template suggestion is from webform\_composite.module -\> hook\_theme\_suggestions\_HOOK\_alter().
The second template suggestion is my custom module.
The third template suggestion is from webform\_composite.module -\> hook\_theme().

My custom template has the `x` and is the template read in by Drupal.
> 0 votes

---
Tags: webforms, 9, theme-negotiation
---


# Question
Title: What methods are available to resolve "The node.field_name field needs to be updated."?
When Drupal status report says field “field\_name” needs to be updated I found out that it sometime hard to resolve. In the past we used to have `entup` but that was removed. The following works in many cases:

1. Edit a field and resave then export it. This will add a missing schema property: this way you can tell what changed.
2. Delete the configuration from the database and re-import it `\Drupal::configFactory()->getEditable($name)->delete()`. (not sure if this has bad side effects?)
3. uninstall/reinstall a module (that;s not always possible).

However, how do I know what exactly need to be updated ? I looked in the code (entityUpdateManager) getChangeSummary can can’t figure out exactly what needs to be update. Is there a way? And could method #2 have any bad consequences?

# Answer
> 0 votes
In my similar case, I had Status error shows on `/admin/reports/status` :

```
node.field_hashtags field needs to be updated

```

I ended up checking the only content type that has hashtags enabled (Book Page) and just saved the storage settings at `/admin/structure/types/manage/book/fields/node.book.field_hashtags/storage`

The above fixed it. However, saving the same field storage using the `devel` module at `/devel/config` hadn't made any difference.

---
Tags: 8, nodes
---


# Question
Title: Paragraph Entity Query returns too many results
I'm trying to find a paragraph that have a certain taxonomy term value and on a matching parent node. I tried the code below, but it always returns over 30 values, when really only one paragraph entity is possible. Not sure what I'm missing.

```
$query = \Drupal::entityQuery('paragraph')
    ->condition('status', 1)
    ->condition('type', 'player_assignment')
    ->condition('field_year_season', $term_id)
    ->condition('parent_id', $node_id);

$results = $query->execute();

```

# Answer
If this returns 30 paragraphs then all of them were at some point stored in the parent node, but not necessarily in the current revision. It might be easier to load the node and then check the paragraph field content of the current revision or, in case you don't know the node ID, start your entity query with the node entity:

```
$query = \Drupal::entityQuery('node')
  ->accessCheck(FALSE)
  ->condition('field_paragraph.entity.field_foo', 'bar');

```
> 1 votes

---
Tags: database, paragraphs
---


# Question
Title: How to assign a paragraph to a node correctly?
I'm currently facing an issue while trying to link paragraphs to a content type in a newer version of Drupal. I have data from an older Drupal website that I need to migrate to a more updated Drupal version. I'm using the JSON:API to achieve this, but I'm encountering problems in associating paragraphs with a specific field in the content type.

Here's an overview of the process and the code involved:

1. I retrieve data from an older website's endpoint using JSON:API. The fetched data is stored in the currentData object, which contains both data and included arrays.
2. For each medical profile data fetched from the older site, I create a new node of the content type medical\_profile in the newer site using the JSON:API.
3. Paragraphs are created and stored in an array called paragraphs. Each item in this array has the type and id of the paragraph.
4. Finally, I use the axios.patch method to update the node of the medical\_profile content type and associate the created paragraphs with the field\_conteudo field using the paragraphs array.

```
const createParagraphContent = async (id, medicalNid) => {
  const paragraphContent = currentData.included.find(element => element.id === id);

  const newParagraph = {
    type: 'paragraph--descricao_profissional',
    attributes: {
      field_label: paragraphContent.attributes['field_text_120'],
      field_texto: {
        value: paragraphContent.attributes['field_richtext']['value'],
        format: 'cohesion',
      },
      parent_id: medicalNid,
      parent_type: "node",
      parent_field_name: "field_conteudo",
    },
  };

  const axiosConfig = {
    headers: {
      'Content-Type': 'application/vnd.api+json',
      Authorization: authHeader,
    },
  };

  try {
    const response = await axios.post(`${process.env.EQUALIZACAO_SITE_URL}/jsonapi/paragraph/descricao_profissional`, { data: newParagraph }, axiosConfig);
    return response.data.data.id
  } catch (error) {
    console.error('Erro ao criar novo paragraph:', error);
    return error;
  }
}

```

The block bellow is the usage of this function

```
const response = await axios.post(`${process.env.EQUALIZACAO_SITE_URL}/jsonapi/node/medical_profile`, { data: newMedicalProfile }, axiosConfig);

      const paragraphs = [];
      for (let idx = 0; idx < element.relationships.field_label_input.data.length; idx++) {
        const elementTwo = element.relationships.field_label_input.data[idx];
        paragraphs.push({
          type: 'paragraph--descricao_profissional',
          id: await createParagraphContent(elementTwo.id, response.data.data.attributes.drupal_internal__nid)
        })
      }

      const responseParagraphs = await axios.patch(`${process.env.EQUALIZACAO_SITE_URL}/jsonapi/node/medical_profile/${response.data.data.id}`, { data: {
        type: "node--medical_profile",
        id: response.data.data.id,
        relationships: {
          field_conteudo: {
            data: paragraphs
          }
        }
      } }, axiosConfig);

```

paragraphs array looks like this:

```
[
  {
    type: 'paragraph--descricao_profissional',
    id: 'fb01c352-2f1f-4a3f-b730-d8e298a2b271'
  }
]

```

Thank you for your time and assistance!

**@edit:** After receiving assistance from Giuseppe, I've made a few changes to my approach.

I've updated the createParagraphContent function to return the complete entity object instead of just the ID:

```
 try {
    const response = await axios.post(`${process.env.EQUALIZACAO_SITE_URL}/jsonapi/paragraph/descricao_profissional`, { data: newParagraph }, axiosConfig);
    return response.data.data
  } catch (error) {
    console.error('Erro ao criar novo paragraph:', error);
    return error;
  }

```

And some changes at paragraphs loop:

```

      const paragraphs = [];
      for (let idx = 0; idx < element.relationships.field_label_input.data.length; idx++) {
        const elementTwo = element.relationships.field_label_input.data[idx];
        const newParagraph = await createParagraphContent(elementTwo.id, response.data.data.attributes.drupal_internal__nid)
        paragraphs.push({
          type: 'paragraph--descricao_profissional',
          id: newParagraph.id,
          meta: {
            target_revision_id: newParagraph.attributes.drupal_internal__revision_id
          }
        })
      }

```

# Answer
For entity reference revisions it's necessary to specify also the `target_revision_id`

So, your paragraphs' array should be something like:

```
[
  {
    type: 'paragraph--descricao_profissional',
    id: 'fb01c352-2f1f-4a3f-b730-d8e298a2b271'
            "meta": {
              "target_revision_id": 120
            }
  }
]

```

By the way, be careful in case you PATCH paragraphs via JSON:API because the same applies, so you need to update the `target_revision_id` on the node, otherwise it will referer the "old" paragraph.
> 0 votes

---
Tags: 9, migrations
---


# Question
Title: How can I display @total in view display rest export in json format?
In a block or page display view i can put Result Summary @total in header. But in rest export display view does not use header plugins.

How can i get @total in rest export json format?

I have search in drupal.org and StackExchange, but no luck.

Is there a way to get @total Drupal 9?

# Answer
You will have to create a custom serializer in a custom module as shown in https://gist.github.com/svetlio/79f3c32667b21d89ed03cdb660308668 and select the "Custom Serializer"(custom name you give for serializer) in the Views Display as shown in the figure below

As @kevin suggested there is a module for this now - https://www.drupal.org/project/views\_rest\_serializer\_extra
> 1 votes

---
Tags: views
---


# Question
Title: Why does content disappear for logged in users?
I have two examples of this. One, I'm using the Umami demo profile, and the pre-header language selector disappears for the logged-in user. I would like the language selector to be visible at all times.

Two, I created a view that shows published articles tagged (1) current issue, (2) sketches. This view works as intended for anonymous users, but the view renders nothing for logged-in users.

What setting do I change to make this view available at all times?

# Answer
> 1 votes
The Views Admin UI shown in your screenshot is for creating the block and customizing what data is fed from the database into the block. Under **Block settings** *Access*, you can set permission for all instances of the block. In this case, the permission is *View published content*, which in nearly all cases both anonymous and authenticated users have, so this is not where you want to look.

Instead, I would check the block layout settings at `/admin/structure/block`. Here, find the relevant blocks, click edit for each block, and check the permissions (are they set to be displayed by role?). If you do not see the blocks here, it's possible they are configured via Layout Builder, Panels, or some other module, so you will have to examine your site configuration to see how the blocks are being placed.

---
Tags: views
---


# Question
Title: Drupal 7: How to create dynamic link based upon url
I simply want a menu item which scans the url, grabs the second argument, and plugs it into the second wildcard location of the new menu item it's creating.

So if the URL is: http://drupal.org/contenttype1/johndoe (johndoe = 2nd argument)

the menu item displayed will be: http://drupal.org/contenttype2/johndoe (johndoe = wildcard location)

So far, based upon a few forum, I've sketched out the following code, which is clearly incomplete, and it is doing nothing right now.

Basically, I just want this menu item to link to an existing page mysite.com/\[coach name\]/page. I'm using clean URLs by the way.

```
        <?php
    function coachmenu_menu() {
      $items = array();

      $items['%/page'] = array(
        'title' => 'Coach Page',
        'page callback' => 'coachpagelink',
        'page arguments' => array('0'),
        'access arguments' => array('access content'),
        'type' => MENU_NORMAL_ITEM,
        'menu_name'=>"menu-coach-menu",
      );
        return $items;
    }

    function coachpagelink($wildcard) {
        return $wildcard;
    }

```

Any ideas on what I can do?

# Answer
> 2 votes
Your code is fine except for a detail. The correct menu definition is the following one.

```
$items['%/page'] = array(
  'title' => 'Coach Page',
  'page callback' => 'coachpagelink',
  'page arguments' => array(0),  // Use an integer, not a string.
  'access arguments' => array('access content'),
  'type' => MENU_NORMAL_ITEM,
  'menu_name'=>"menu-coach-menu",
);

```

If you use a string in the page arguments, the page callback is not receiving part of the URL, but that string. In your case, the page callback is always receiving `'0'` as argument, even when the page callback is invoked for example.com/jhondoe/page.

# Answer
> 0 votes
AFAIK, wildcards cannot be used as a first argument. See "Simple Wildcards" under "Wildcards in Paths" section in hook\_menu() documentation.

---
Tags: routes
---


# Question
Title: I see some weid WordPress urls in my "Recent log messages", but i am using drupal
Lately i am having an issue with Drupal, i don't know how to solve it, i get too many "page not found" errors, but when i check the log, i found out that all of those URLs are Wordpress URLs, as you may see the in attached images.

What could be the issue?

# Answer
> 3 votes
It is just an external script that scans your site to find any security issue to attack it. It happened to my personal site too.
Those log entries are not caused by any issue on your site.

The only effect those attempts to access non-existent pages could have is that they could slow down your site, if they are repeated many times in few seconds.

---
Tags: log-messages
---


# Question
Title: The Quantity field increments in decimals instead of whole numbers
Default installation of Commerce 2.x. The qty field for a product, when you click the up arrow to increase the quantity it goes from 1 to 1.01. I want it to go from 1 to 2 to 3, etc.

# Answer
> 0 votes
1. Navigate to: Administration \>\> Commerce \>\> Configuration \>\> Default \>\> Manage Form display
2. Under **Default** tab, set Quantity field to Quantity widget.
3. Under **Add to cart** tab, set Quantity field to Quantity widget.

Save and clear cache.

---
Tags: commerce
---


# Question
Title: Modal form opened from modal form doesn't submit
I have a user form mode (like node view mode except for forms) opened in a modal. When this form is submitted the user entity is updated and the modal is closed. This works fine. I now want to extend this where the user is updated, the modal is closed and a 2nd modal is opened with another custom form.

In my original AJAX response call I have simply added this:

```
  // Get the modal form using the form builder.
  $accept_form = \Drupal::formBuilder()->getForm('Drupal\sia_mpep\Form\SendPolicyEndorsementForm');

  // Add an AJAX command to open a modal dialog with the form as the content.
  $response->addCommand(new OpenModalDialogCommand(t('Send policy endorsement form'), $accept_form, ['width' => '1000']));

```

The custom form is fairly simple and has this at the end:

```
$form['actions'] = ['#type' => 'actions'];
$form['actions']['send'] = [
  '#type' => 'submit',
  '#value' => $this->t('Send'),
  '#attributes' => [
    'class' => [
      'use-ajax',
    ],
  ],
  '#ajax' => [
    'callback' => [$this, 'submitModalFormAjax'],
  ],
];

$form['#attached']['library'][] = 'core/drupal.dialog.ajax';

return $form;

```

but when I submit the 2nd form; neither the submitForm nor the submitModalFormAjax methods are hit. I noticed that the action attribute in the form tag is still set to the original user form edit (modal #1) and I read that I need to define a route to my new form and set #action to the new route:

```
$form['#action'] = \Drupal\Core\Url::fromRoute('route_to_my_form')->toString();

```

This does set the action in my form tag to point to that path; but still doesn't submit to my submitForm() handler. It also has the downside of now having a page which shows my form - which I don't need.

When I submit the ajax spinner spins for a while and then I get an AJAX error in console which looks as though the form may still be submitting to the user form handler.

I am guessing there must be something simple missing here.

# Answer
This is a gotcha of AJAX forms.

When you load an AJAX form via AJAX it loses its AJAX functionality.

In order to keep it working, for the form that is getting loaded via ajax, you need to add a `url` and `options` keys to `#ajax`

```
  '#ajax' => [
    'callback' => [$this, 'submitModalFormAjax'],
    'url' => \Drupal\Core\Url::fromRoute('your.form.route.name'),
    'options' => [
      'query' => [
        Drupal\Core\Form\FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
      ],
    ],
  ],

```
> 1 votes

---
Tags: forms, 9, modal-dialogs
---