# Question
Title: How to remove the separator between values of a multi value field in a Views result?
I'm working on a D8 project. I have a webform with multiple fields and one of those is a taxonomy term. The taxonomy term consist of the title and a file upload field. The admin uploads a file in the taxonomy, and in the webform selects which file/s should be visible to the end user.

In order to display those files to the user I created a webform submission view where I get the specific field. The point is that the field might return multiple values (taxonomy terms) which are separated by comma.

How can I remove that comma? In D7 you could choose the separator in mulivalue field but now I can't find something similar.

EDIT: The last idea was to change the output in the template file. So in views-view-field.html.twig I try to replace the comma with space in the output of the field.

```
{% set output = output|replace({(',') : (' '),}) %}

```

What I get is the html of the view with a lot of debug informations but the view is not rendered as it should. I get something like \<!-- THEME DEBUG --\> \<!-- THEME HOOK: 'webform\_element\_base\_html' --\> \<!-- FILE NAME SUGGESTIONS: *

Any idea why?

# Answer
> 2 votes
Finally, I found the solution. I'm not sure if is the best, but it works.

```
function MY_THEME_preprocess_views_view_field(&$variables){
  $view = $variables['view'];

  if ($view->id() == 'VIEW_ID'){
    $output = str_replace(',', '', $variables['output']);
    $variables['output'] = \Drupal\views\Render\ViewsRenderPipelineMarkup::create($output);
  }
}

```

# Answer
> 1 votes
You are seeing `<!-- THEME DEBUG -->` because Twig debug is enabled in either your `sites/default/services.yml` or `sites/development.services.yml`. You can disable Twig debug as follows:

**services.yml**

```
parameters:
  twig.config:
    debug: false

```

# Answer
> 1 votes
You can change or remove the separator from the view configuration of the field:

# Answer
> 0 votes
I was expecting the solution provided by @Achraf should've worked as I've been using the same thing for a decade! Surprisingly, the "MULTIPLE VALUES HANDLING" option is missing if I check "Use entity field rendering" at the view field option while using Drupal 9.4.8.

I've tried to improve the code snippet provided by @Ismini. In the following, apart from checking the Views ID, I'm also restricting it to a SPECIFIC DISPLAY & most importantly for me, to a SPECIFIC FIELD.

```
/**
 * Implements template_preprocess_views_view_field().
 */
function my_template_preprocess_views_view_field(&$variables) {
  /** @var \Drupal\views\ViewExecutable $view */
  $view = $variables['view'];
  if ($view->id() === 'my_views_id' && $view->current_display === 'my_current_display' && $variables['field']->field === 'my_field') {
    $output = str_replace(',', '', $variables['output']);
    $variables['output'] = \Drupal\views\Render\ViewsRenderPipelineMarkup::create($output);
  }
}

```

---
Tags: views, 8, entities
---


# Question
Title: Clicking links to uploaded files shows bytecode
This issue just started occurring on our app. We allow users to upload files in our forms and we create links for those files like so;

```
$f = \Drupal::entityTypeManager()->getStorage('file')->load($file->value);
if ($f) {
  $fileLink = [
    'title' => $f->get('filename')->value,
    'link' => \Drupal::service('file_url_generator')->generateAbsoluteString($f->get('uri')->value),
  ];
  $fileLinks[] = $fileLink;
}

```

Nothing special.

Our default download method is "Public local files served by the webserver."

The issue is that as of last week all files, regardless of mime, display as bytecode and not the file.

The url to this file is direct with extension, so its not being served from Drupal, meaning no mime issues. I can open the file perfectly fine and if you right click and save as, the file downloads and opens fine.

Appreciate the help.

# Answer
> 0 votes
The issue was due to an implementation of `hook_file_download`.

We were returning a 1 in this hook to allow certain users access, but the hook needs to return the headers of the file when a user has access.

Interestingly, this code has not changed since mid 2020 so something else has caused this to be an issue.

```
return file_get_content_headers($file);

```

All fixed.

---
Tags: files, 9
---


title: Exclude fields from printing in Twig

text:
# Question
Title: Exclude fields from printing in Twig
I am overriding the fields `template views-view-fields--machine_name.html.twig`.

I want to render some Fields in a different div than the other fields. I do not want the fields to render twice.

```
<div class="foo">
  {{ fields.field_events_date_start.content }}
  {{ fields.field_events_date_start_1.content }}
</div>

{% for field in fields -%}
  {{ field.separator }}
  {%- if field.wrapper_element -%}
    <{{ field.wrapper_element }}{{ field.wrapper_attributes }}>
  {%- endif %}
  {%- if field.label -%}
    {%- if field.label_element -%}
      <{{ field.label_element }}{{ field.label_attributes }}>{{ field.label }}{{ field.label_suffix }}</{{ field.label_element }}>
    {%- else -%}
      {{ field.label }}{{ field.label_suffix }}
    {%- endif %}
  {%- endif %}
  {%- if field.element_type -%}
    <{{ field.element_type }}{{ field.element_attributes }}>{{ field.content }}</{{ field.element_type }}>
  {%- else -%}
    {{ field.content }}
  {%- endif %}
  {%- if field.wrapper_element -%}
    </{{ field.wrapper_element }}>
  {%- endif %}
{%- endfor %}

```

If I exclude those Fields from the display in Views it hides them both when they render before and in the normal content area.

```
{{ content|without('field_events_date_start', 'field_events_date_start_1') }}

```

...Does not work because I am rendering Fields, not content.

How do I get the fields to render before, but be excluded later?

# Answer
You would have to remove the two fields from `fields`.

```
<div class="foo">
  {{ fields.field_events_date_start.content }}
  {{ fields.field_events_date_start_1.content }}
</div>

{% for field in fields|without('field_events_date_start',  field_events_date_start_1') %}
  ...
{% endfor %}

```
> 11 votes

# Answer
Here is an example of this I did last week.

Filename `views-view-fields--view_name--display_id.html.twig` i.e. `views-view-fields--acquia-search--results.html.twig` in my case.

```
{{ fields.title.content }}
<p class="search-result__item-description">{{ fields.search_api_excerpt.content }}</p>
<ul class="search-result__item-meta">
  <li class="search-result__item-link"><span class="label">View More:</span> {{ fields.url.content }}</li>
  <li class="search-result__item-date"><span class="label">Date Modified:</span> {{ fields.changed.content }}</li>
</ul>

```

I am printing the fields at my discretion and providing my own markup.

If you install Twig XDebug, you can drop `{{ breakpoint() }}` into your template and see your variables.
> 0 votes

# Answer
Example: in variable 'content' was 10 elements (name, date, id,...) `{{ content }}` \- get all fields `{{ content|without('date') }}` get all fields(name, (((deleted - date))), id,...), except 'date'
> -2 votes

---
Tags: views, theming
---


title: CSS for specific pages

text:
# Question
Title: CSS for specific pages
How do I add CSS styles for a specific page?

For example, I want the `<body>` background color on a specific page to be different from the background color used on the front page.
I've looked into `hook_theme_preprocess()`, but I am confused on how I should implement it.

# Answer
> 8 votes
You can find totorial for adding specific CSS to specif page to the following links.

1. Drupal 8 Theming Fundamentals, Part 1, but it is describing how to add specific CSS to front page.
2. Drupal8 attaching libraries to specific pages, to add the specific CSS to specific node you need to follow tutorial on this page .

To give you example I am explaining with bartik theme for easy understanding.

I have created a css file cssfile.css and pasted at path `css/cssfile.css` Now this CSS file I want to use in one case to only front page and in otehr case to only specific node.

### Step 1: Adding a library to the theme

Add the following code to *bartik.libraries.yml*.

```
css-filling:
  css:
    theme:
      css/cssfile.css: {}

```

The library name I used is *css-filling*, but you can use other names.

### Step 2: Adding the CSS styles to a specific page

Step 2a: Adding CSS styles only to the front page

The following code in the *bartik.theme* adds the library to the front page.

```
function bartik_preprocess_page(&$variables) {
  if ($variables['is_front']) {
    $variables['#attached']['library'][] = 'bartik/css-filling';
  }
}

```
Step 2b: Adding CSS styles to a specific node

The following code adds the library only to a specific node.

```
function bartik_preprocess_node(&$variables) {
  $node = \Drupal::routeMatch()->getParameter('node');
  if ($node) {
    if ($node->id() == 3) {
      $variables['#attached']['library'][] = 'bartik/css-filling';
    }
  }
}

```

In the above code the important thing is path, *bartik* comes from the theme name and *css-filling* comes from step 1.

# Answer
> 4 votes
Most Drupal themes still provide enough classes on the body tag to allow you to target the front page separately from all others. Stable (the most basic of base-themes in Drupal 8 core) provides `front` on the front page and `not-front` on all others.

But you can load style sheets conditionally if that's important to your project. The complete details are available here, but the short version is that you can define a library in your theme and then attach the library in whatever html.twig file you need to ensure that libraries loads for:

```
{{ attach_library('mytheme/mylibrary') }}

```

# Answer
> 0 votes
To add custom style for a specific page. Here I'm adding it for login page, register page.

**File:- mytheme.theme**

```
function mytheme_preprocess_page(&$variables)
{
  // \Drupal::logger('mytheme')->error('Start');
    $route_name = \Drupal::routeMatch()->getRouteName();
    if (in_array($route_name, ['user.login', 'user.pass', 'user.register'])) {
        $variables['#attached']['library'][] = 'mytheme/login';
    }
}

```

Following content are same as the @CodeNext answer.

**File:- mytheme.info.yml**

**Doc:** https://www.drupal.org/docs/theming-drupal/adding-assets-css-js-to-a-drupal-theme-via-librariesyml

```
libraries:
  - mytheme/global-styling
  - bootstrap5/bootstrap5-js-latest
libraries-override:
  bootstrap5/global-styling: false

```

Note: I'm not adding *login library* in mytheme.info.yml

**File:- mytheme.libraries.yml**

```
login:
  css:
    theme:
      css/login.css: { minified: true }

```

# Answer
> -1 votes
In Drupal 7, there is a class like page-node-NID (with NID replaced by the node ID of the node being viewed) added to the tag so we can easily add CSS styles to specific nodes for example:

```
body.page-node-NID{
  background-color: red;
}

```

Drupal 8 is missing this core D7 functionality, but now there is a module for that, its called Body node ID class

---
Tags: theming, 8
---


# Question
Title: How do I restrict content access programmatically?
Something is baffling me. I have this view of streams to users. An admin may make a stream to themselves, a specific person or everyone. I also have this code in which a non-admin user may see only the streams made to everyone and that specific user, whereas an admin should be able to see all streams, including the ones made to themselves. I’ve edited my code many times, but no matter what I do, I can’t get the non-admin user to see the streams to themselves. Could you maybe take a look at it and point me in the right direction? Thanks a lot in advance :slightly\_smiling\_face:

```
function hajans_crm_views_pre_render(ViewExecutable $view) {
  if (isset($view) && $view->storage->id() == 'crm' && $view->current_display == 'streams_user_tab') {
    foreach ($view->result as $index => $value) {
      $current_user = User::load(Drupal::currentUser()->id());
      if (!$current_user->hasRole('administrator')) {
        $field_to = $value->_entity->field_to->value;
        if ($field_to != 'Everyone' && $field_to != 'Myself') {
          if ($current_user->id() !== $value->_entity->uid->target_id) {
            unset($view->result[$index]);
          }
        }
      }
    }
  }
}

```

# Answer
Trying to restrict access in `hook_views_pre_render()` isn't going to work because the view could be cached incorrectly and lots of other things could go wrong. In general, you never want to restrict access in the render pipeline, which includes the pre\_render() processing.

Instead, you should define a custom views access plugin as described by Badzilla here and Lullabot here.

In general, from Drupal 8 onward, if you're trying to restrict access, look for a plugin-based solution first and then, if you can't find one, an access hook solution.
> 1 votes

---
Tags: 8, views
---


# Question
Title: Form to upload and replace unmanaged file
I want to make a form where a user can upload a file that will be saved in a predefined path in the private filesystem, replacing whatever was there before.

E.g. the destination file path could be `'private://mymodule/config.yml'`.

The file, once uploaded, does not need to be a file entity, it can remain unmanaged. It just holds some global configuration or data.

Ideally there will be some validation of the file contents, before the destination file is overwritten.

## What I found so far

I have not really found a complete example for this, and it seems I need to use some non-obvious steps. It seems I need file\_save\_upload(), which is a relic from Drupal 7. But I could be wrong.

E.g. I found this How can I upload and read an unmanaged file? but it is not really the same.

I might even answer this myself if I can figure it out :)

# Answer
> 2 votes
Here we go.

## References

I did not come up with this myself, I just assembled ideas from elsewhere.

## Code example

In this example I make it about an image file instead of a config file.

### Create entry in mymodule.routing.yml

```
mymodule.acme_logo_form:
  path: '/admin/config/acme-logo'
  defaults:
    _form: '\Drupal\mymodule\Form\AcmeLogoForm'
    _title: 'Replace ACME logo'
  requirements:
    # This permission needs to be defined somewhere.
    _permission: 'manage acme logo'

```

### Create the form

```
<?php

namespace Drupal\mymodule\Form;

use Drupal\Core\Extension\ExtensionPathResolver;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\File\FileUrlGeneratorInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\file\Entity\File;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Form to upload a custom acme-logo.png file.
 */
class AcmeLogoForm extends FormBase {

  const CUSTOM_FILE_URI = 'private://path/to/acme-logo.png';

  /**
   * @var \Drupal\Core\File\FileUrlGeneratorInterface
   */
  private FileUrlGeneratorInterface $fileUrlGenerator;

  /**
   * @var \Drupal\Core\File\FileSystemInterface
   */
  private FileSystemInterface $fileSystem;

  /**
   * @var \Drupal\Core\Extension\ExtensionPathResolver
   */
  private ExtensionPathResolver $extensionPathResolver;

  /**
   * Constructor.
   *
   * @param \Drupal\Core\File\FileUrlGeneratorInterface $file_url_generator
   *   File url generator.
   * @param \Drupal\Core\File\FileSystemInterface $file_system
   *   File system.
   */
  public function __construct(
    // Depending on PHP version we could use constructor property promotion.
    FileUrlGeneratorInterface $file_url_generator,
    FileSystemInterface $file_system,
    ExtensionPathResolver $extension_path_resolver
  ) {
    $this->fileUrlGenerator = $file_url_generator;
    $this->fileSystem = $file_system;
    $this->extensionPathResolver = $extension_path_resolver;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('file_url_generator'),
      $container->get('file_system'),
      $container->get('extension.path.resolver')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'mymodule_acme_logo_form';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    $form['#_attributes'] = [
      'enctype' => 'multipart/form-data',
    ];

    // Show a link to the default file that is tracked in version control.
    $form['default_file_link'] = [
      'link' => [
        '#type' => 'link',
        '#url' => $this->fileUrlGenerator->generate($this->extensionPathResolver->getPath('module', 'mymodule') . '/acme-logo-default.png'),
        '#title' => 'default logo.png',
        '#attributes' => ['target' => '_blank'],
      ],
      '#theme_wrappers' => ['container'],
    ];

    // Show a download link for the custom file, if exists.
    if (is_file(self::CUSTOM_FILE_URI)) {
      $form['custom_file_link'] = [
        'link' => [
          '#type' => 'link',
          '#url' => $this->fileUrlGenerator->generate(self::CUSTOM_FILE_URI),
          '#title' => 'custom acme-logo.png',
          '#attributes' => ['target' => '_blank'],
        ],
        '#theme_wrappers' => ['container'],
      ];
    }

    $form['file'] = [
      '#title' => $this->t('New custom acme-logo.png'),
      '#type' => 'file',
    ];

    $form['submit'] = [
      '#type'  => 'submit',
      '#value' => $this->t('Upload'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state): void {
    parent::validateForm($form, $form_state);

    // Create a temporary file entity based on the file form element.
    // @todo file_save_upload() might soon be deprecated.
    // Unfortunately https://www.drupal.org/node/2244513 was closed without providing an alternative to file_save_upload().
    // @todo Catch errors from this operation.
    // @todo Find a way to avoid creating temporary file entities.
    $tmp_file_entity = file_save_upload(
      'file',
      [
        'file_validate_extensions' => ['png'],
      ],
      FALSE,
      0,
    );

    if (!$tmp_file_entity instanceof File) {
      $form_state->setErrorByName('file', t('Upload failed.'));
      return;
    }

    // @todo Validate file contents.

    // Keep the temporary file entity available for submit handler.
    $form_state->setValue('tmp_file', $tmp_file_entity);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $values = $form_state->getValues();

    /** @var \Drupal\file\Entity\File $tmp_file_entity */
    $tmp_file_entity = $values['tmp_file'];

    // Create parent directory, if it does not exist.
    // @todo Handle errors from this operation.
    $directory = dirname(self::CUSTOM_FILE_URI, 2);
    $this->fileSystem->prepareDirectory(
      $directory,
      FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);

    // Copy the file as an unmanaged file in the private filesystem.
    // @todo Handle errors from this operation.
    $this->fileSystem->copy(
      $tmp_file_entity->getFileUri(),
      self::CUSTOM_FILE_URI,
      FileSystemInterface::EXISTS_REPLACE);
  }

}

```

### Allow download access

Because this is in private filesystem, we need to grant download access explicitly.

```
/**
 * Implements hook_file_download().
 */
function mymodule_file_download(string $uri) {
  if ($uri !== AcmeLogoForm::CUSTOM_FILE_URI) {
    // This is not the file we care about.
    return NULL;
  }
  if (!\Drupal::currentUser()->hasPermission('view acme logo')) {
    // No access.
    return -1;
  }
  // Set some headers to tell Drupal that access is granted.
  return [
    'Content-Type' => 'image/png',
  ];
}

```

## Notes

The `file_save_upload()` always creates temporary file entities that "pollute" the database.

The same effect occurs when uploading logos or favicons in the core theme settings.

The `file_managed` database tables will fill up with entries for temporary files.

This seems to be just how it works, until a replacement for or alternative to `file_save_upload()` is found.

Perhaps `Drupal\file\Upload\FileUploadHandler` could be used directly, but this also creates file entities afaik.

---
Tags: forms, files, 9
---


# Question
Title: How should we configure Config link on custom module?
I need to create Config link while enabling module. In routing file, I have mention the path name of config form, but its not directly show in the Configuration page. Below is my routing code.

```
dm_user_timezone.user_timezone_settings:
path: '/admin/config/usertimezone/usertimezoneconfig'
defaults:
 _form: '\Drupal\dm_user_timezone\Form\UserTimezoneSettingForm'
 _title: 'User timezone page configuration'
requirements:
 _permission: 'access administration pages'
options:
 _admin_route: TRUE

```

My folder sructure looks like this. Need help what I missed here.

# Answer
Add `configure: dm_user_timezone.user_timezone_settings` to the `dm_user_timezone.info.yml` file. The `configure` option is documented on drupal.org.
> 3 votes

---
Tags: forms, 9, configuration
---


# Question
Title: How can I use a Twig if statement in a View rewrite
How can I add a Views field rewrite using Twig that will display the moderation state only if the node is in draft state or review state? I tried the code below but it prints all of the moderation states.

```
{{ title_1 }}
{% if field.moderation_state == 'draft' %}Draft{% endif %}

```

This is how my list of titles look:

```
page1 Draft
page2 Published
page3 Submitted

```

I want all of the page titles to always display. I never want Published to display. So I want to first check if the moderation state is equal to draft and review.

I also tried variations like this

```
{% if moderation_state__value == 'draft' %}

```

Below are the available replacement pattters

```
   {{ moderation_state }} == Moderation state
   {{ path }} == Link to Content
   {{ title_1 }} == Title
   {{ title_1__value }} == Raw value
   {{ arguments.nid }} == Content: ID title
   {{ raw_arguments.nid }} == Content: ID input

```

# Answer
> 1 votes
You don't need to strip HTML tags. This works for me:

```
{% if field_tags == "green" %}
   GREEN
{% else %}
   NOT GREEN
{% endif %}

```

where field\_tags is a taxonomy reference field with "Link label to the referenced entity" disabled.

# Answer
> 1 votes
Try to create an additional variable and use this for the conditions.

```
{% set my_var = field_tags|striptags|trim %}

{% if my_var == "green" %}
   GREEN
{% else %}
   NOT GREEN
{% endif %}

```

---
Tags: views, 8, theming
---


title: Different content, one database

text:
# Question
Title: Different content, one database
Is it possible to have a multi-site installation, where I have different content for each site, but using a single database?

# Answer
Yes it is possible. Use the Domain module. But if the sites will not share any data, no special modules are needed. Set a unique “Table name prefix” when installing Drupal on each site instance.
> 3 votes

---
Tags: multi-sites
---


# Question
Title: How can I attach a newly added paragraph to existing records?
While editing a form, I needed to delete some fields and add a new paragraph. The issue here is, the newly added paragraph is not initialized in the edit form and that makes sense because the old data don't have that field so I have to initialize it manually by clicking on "Add Paragraph", then Save otherwise I won't be able to access it programmatically, but I have hundreds of users and I can't do that.

How can I add a paragraph to existing records?

I'm unable to use Drush on this server.

# Answer
> 0 votes
You add newly created paragraphs (without saving them) to the node field:

```
$node->field_paragraph[] = Paragraph::create([
  'type' => 'paragraph_type',
  'field_foo' => 'bar',
]);

```

and save them later together with the node:

```
$node->save();

```

---
Tags: 8, paragraphs
---


# Question
Title: Add new column "Block description" on block layout page
I need to add a new column called **Block Short Description** on Block layout under /admin/structure/block.

Can anyone let me know how to achieve it?

I have Attached screenshot for reference.

# Answer
That's a form. Themed as table. So I managed to do what you want via `hook_form_FORM_ID_alter`.

Thing is, I can't find the block description or admin label inside the block entity. So that's left. I hope you can find a way or maybe you can specify what "Block Short Description" is supposed to be.

```
/**
 * Implements hook_form_FORM_ID_alter().
 */
function MYMODULE_form_block_admin_display_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

  // Add header column.
  array_splice($form['blocks']['#header'], 1, 0, 'Description');

  // Go through all blocks.
  foreach ($form['blocks'] as $bid => $block) {

    // Skip non-block elements (like '#header' or 'region-name').
    if ($bid[0] != '#' && !strpos($bid, '-')) {

      // Load block.
      $entity = \Drupal\block\Entity\Block::load($bid);

      // Load description.
      // ksm($entity);
      // Can't find one. Take the label for now. Let OP figure this out themselves.
      $description = $entity->label();

      // Add description column to row.
      // @see https://stackoverflow.com/a/3354804/2199525
      $array = $form['blocks'][$bid];
      $form['blocks'][$bid] = array_slice($array, 0, 2, TRUE) +
        ['description' => ['#markup' => $description]] +
        array_slice($array, 2, count($array) - 1, TRUE);
    }
  }
}

```

---

### Answer updated to display content type restrictions.

```
/**
 * Implements hook_form_FORM_ID_alter().
 */
function MYMODULE_form_block_admin_display_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

  // Add header column.
  array_splice($form['blocks']['#header'], 1, 0, 'Description');

  // Go through all blocks.
  foreach ($form['blocks'] as $bid => $block) {

    // Skip non-block elements (like '#header' or 'region-name').
    if ($bid[0] != '#' && !strpos($bid, '-')) {

      // Load block.
      $entity = \Drupal\block\Entity\Block::load($bid);

      // Load visibility settings.
      $conditions = $entity->getVisibilityConditions()->getConfiguration();

      // Load content types.
      $types = [];
      if ($node_types = isset($conditions['node_type']['bundles']) ? $conditions['node_type']['bundles'] : FALSE) {
        $node_types = Drupal\node\Entity\NodeType::loadMultiple($node_types);
        foreach ($node_types as $node_type) {
          $types[] = $node_type->label();
        }
      }

      // Set description.
      $description = 'Content types: ';
      if (!empty($types)) {
        $description .= implode(', ', $types);
      }
      else {
        $description = '- no content type restrictions -';
      }

      // Add description column to row.
      // @see https://stackoverflow.com/a/3354804/2199525
      $array = $form['blocks'][$bid];
      $form['blocks'][$bid] = array_slice($array, 0, 2, TRUE) +
        ['description' => ['#markup' => $description]] +
        array_slice($array, 2, count($array) - 1, TRUE);
    }
  }
}

```
> 3 votes

# Answer
**Some general method**

* Find a unique interface string in the page and look in the core
* Search for the URL of the page and find which routing.yml contains it. Then you will see which class handles the request

**In your case it's the second**

Route name: `block.admin_display`

Controller: `\Drupal\block\Controller\BlockListController`

which in the end is pointing to the Block entity list builder:

```
\Drupal\block\BlockListBuilder

```
> 2 votes

# Answer
In addition to @leymannx answer, if you want to display the block's admin label instead of the rendered label (which may be the same when you have many blocks), you can try:

```
/**
 * Implements hook_form_FORM_ID_alter().
 */
function mymodule_form_block_admin_display_form_alter(&$form, $form_state, $form_id) {
    array_splice($form['blocks']['#header'], 1, 0, 'Description');

    foreach ($form['blocks'] as $bid => $block) {
        if ($bid[0] != '#' && false === strpos($bid, '-')) {

            $entity = \Drupal\block\Entity\Block::load($bid);
            $description = $entity->getPlugin()->getPluginDefinition()['admin_label'];
            $array = $form['blocks'][$bid];
            $form['blocks'][$bid] = array_slice($array, 0, 2, TRUE) +
                ['description' => ['#markup' => $description]] +
                array_slice($array, 2, count($array) - 1, TRUE);
        }
    }
}

```
> 0 votes

---
Tags: 8, blocks
---


# Question
Title: Rendering an image field in page.html.twig with a custom image style
I'm trying to set up a slideshow that's unique to each page. The code for this needs to be in `page.html.twig`. I've got the slideshow mostly working, but I can only call the full image URL, not a custom image style of a specific size. How can I modify this code to call a specific image size?

```
{% for key, item in node.field_slides %}
{% if node.field_slides[key].entity %}
<figure class="swiper-slide">
    <img class="swiper-image" src="{{ file_url(node.field_slides[key].entity.uri.value) }}" alt="{{ node.field_slides[key].alt  }}" />

    {% if node.field_slides[key].title %}
    <figcaption class="swiper-caption">
        <div class="swiper-user-content user-content">
            {{ node.field_slides[key].title|striptags("<a>,<h1>,<h2>,<h3>,<h4>,<h5>,<h6>,<ol>,<p>,<table>,<ul>")|raw }}
        </div><!--/.swiper-user-content.user-content-->
    </figcaption><!--/.swiper-caption-->
    {% endif %}
</figure><!--/.swiper-slide-->
{% endif %}
{% endfor %}

```

The bit where I'm calling the URL is:

```
{{ file_url(node.field_slides[key].entity.uri.value) }}

```

I've tried doing `{{ dump(node.field_slides[key]) }}` to see if there was any data I could use, but every time I do that, I just get 500 error.

Any help would be greatly appreciated; I'm very new to Drupal, coming from WordPress. I think this is the last major hurdle before I can finish up this theme for my client.

# Answer
> 45 votes
Replace the image tag

```
<img class="swiper-image" src="{{ file_url(node.field_slides[key].entity.uri.value) }}" alt="{{ node.field_slides[key].alt  }}" />

```

with a render array for the image style:

```
{% set imagestyle = {
  '#theme':      'image_style',
  '#style_name': 'medium',
  '#uri':        node.field_slides[key].entity.uri.value,
  '#alt':        node.field_slides[key].alt,
  '#attributes': { class: 'swiper-image' },
} %}

{{ imagestyle }}

```

**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:

```
{{ node.field_slides[key].entity.uri.value | image_style('thumbnail') }}

```

# Answer
> 6 votes
Just an update for the *4k4* answer.

To print entity fields (eg. paragraph), we can use this:

`<img src="{{ item.entity.field_image.entity.uri.value | image_style('image_style') }}" alt="{{item.entity.field_image.alt}}"/>`

# Answer
> 5 votes
To print a responsive image style:

```
{% set responsiveimagestyle = {
    '#theme': 'responsive_image',
    '#responsive_image_style_id': 'responsive_image_style',
    '#uri': node.field_slides[key].entity.uri.value,
    '#attributes': { class: 'swiper-image', alt: 'text', title: 'text' },
} %}

{{ responsiveimagestyle }}

```

# Answer
> 2 votes
I recently needed this myself with the twist that I wanted to provide a default (svg) image when no image was uploaded. Twig Tweak makes this possible while still allowing me to control the output via Drupal's user interface.

In my case, I'm styling a comment, so I want to render the user picture, and I'd like to use the "thumbnail" image style. This is difficult because typically an entity field that's not the primary entity of your template can't just be rendered.

1. Install Twig Tweak module.
2. Create a new view mode for the user (I named my "compact").
3. Set the user\_picture field with whatever image style output you want to use in "Manage Display". For me that was "thumbnail", but it won't be visible in the code sample.
4. Override the comment.html.twig and add the following line where ever makes sense for your use case.

```
{{ comment.uid.entity.user_picture|view('compact') }}

```

Twig tweak provides this "view" method which will now render my user\_picture field with the "compact" view mode settings I've already defined in Drupal. If I want to change image styles later, I can do so through the user interface without needing to make any additional modifications to my twig templates. Also, this will support Drupal's "default image" settings as well without having to codify that into the twig or preprocess hooks in some other way.

# Answer
> 1 votes
If you need to access through a nested paragraph (field\_image is on parent paragraph) use this:

```
{% set paragraph_parent = paragraph.getParentEntity() %}

{% set responsiveimagestyle = {
    '#theme': 'responsive_image',
    '#responsive_image_style_id': 'hero_responsive',
    '#uri': paragraph_parent.field_image.entity.field_media_image.entity.fileuri,
    '#attributes': { class: 'swiper-image', alt: paragraph_parent.field_image.entity.field_media_image.alt },
} %}

```

# Answer
> 0 votes
Thanks to these replies , i used it, in combination with foundation grid classes , to toggle between two different responsive images for a carrousel item paragraph, depending on wether we wanna display a text panel or not ( the image dimensions being changed )

if it can help anyone :

```
{% set classes = [
  'paragraph',
  paragraph.bundle|clean_class,
  view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class,
  not paragraph.isPublished() ? 'paragraph--unpublished',
] %}

{% if  content.field_carrousel_item_title.0 or content.field_carrousel_item_text.0 %}
  {% set carrousel_structure="img+text" %}
  {# Changement du style d'image #}
  {% set image_uri =content.field_carrousel_item_image[0]['#media'].field_media_image_1|file_uri %}
  {% if image_uri is not null %}
    {% set image_alt =content.field_carrousel_item_image[0]['#media'].field_media_image_1.alt %}
    {% set image_w_style = {
      '#theme':      'responsive_image',
      '#responsive_image_style_id': 'carrousel--with-text-panel',
      '#uri':        image_uri,
      '#alt':        image_alt,
      '#attributes': { class: 'carrousel--with-text-panel' },
    } %}
  {% endif %}
{% endif %}

{% block paragraph %}
  <div{{ attributes.addClass(classes) }}>
    {% block content %}
      {% if  content.field_carrousel_item_link[0]['#url']|render %}
        {% set field_link = content.field_carrousel_item_link[0]['#url']|render %}
        <a class="carrousel-item__link stretched-link" href="{{ field_link }}"><span class="show-for-sr">lien vers le contenu associé</span></a>
      {% endif %}
      <div class="grid-x">
        {% if carrousel_structure=="img+text" %}
          <div class="cell carrousel-item__image large-8 medium-12">
            {{ image_w_style }}
          </div>
          <div class="cell carrousel-item__text large-4 medium-12">
            <div class="carrousel-item__title">
              {{ content.field_carrousel_item_title }}
            </div>
            {{ content.field_carrousel_item_text }}
          </div>
        {% else %}
          <div class="cell carrousel-item__image carrousel--image-full-width large-12 medium-12">
            {{ content.field_carrousel_item_image }}
          </div>
        {% endif %}
      </div>
    {% endblock %}
  </div>
{% endblock paragraph %}

```

# Answer
> 0 votes
Since the accepted answer, a new field formatter "URL to image" was added to Drupal.

You can just select it in display settings, and there will be no need to do it programmatically:

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


title: How to forbid acess to a page?

text:
# Question
Title: How to forbid acess to a page?
I want to show a "Access denied" (403) page with message "You are not authorized to access this page." for a given route. This will apply to all users in any case.

How to do it in the simplest way?

# Answer
> 0 votes
Just implement a route subscriber like this:

In MYMODULE/src/EventSubscriber/RouteSubscriber.php:

```
<?php

namespace Drupal\MYMODULE\EventSubscriber;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

class RouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  public function alterRoutes(RouteCollection $collection): void {
    // Remove access to page with route "given.route".
    if ($route = $collection->get('given.route')) {
      $route->setRequirement('_access', 'FALSE');
    }
  }
}

```

Please note the quotes around FALSE!

Of course the route subscriber needs to be declared in the services file of the custom module.

In MYMODULE/services.yml

```
services:
  MYMODULE.route_subscriber:
    class: Drupal\MYMODULE\EventSubscriber\RouteSubscriber
    tags:
      - { name: event_subscriber }

```

---
Tags: routes, 9
---


# Question
Title: Adding library charts.js to composer.json
I've installed module Moderation Dashboard, now I would like to install charts.js, which is needed by the module, locally by using composer. The readme of the module says:

*Add following code inside repositories section in your project's composer.json:*

```
"chart.js": { "type": "package", "package": { "name": "nnnick/chartjs", "version": "v3.9.1", "type": "drupal-library", "dist": { "url": "https://github.com/chartjs/Chart.js/releases/download/v3.9.1/chart.js-3.9.1.tgz", "type": "tar" } } }

```

Unfortunately, I don't know exactly how to add the code in my existing composer.json. The start looks like this:

```
{
    "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": {
        "composer/installers": "^1.9",
        "drupal/admin_toolbar": "^3.1",
        …

```

Could someone show me, where to put the snippet exactly?

# Answer
Your `composer.json` contains a repository section where the chart.js related definition has to be added like this:

```
...
"repositories": [
  {
    "type": "composer",
    "url": "https://packages.drupal.org/8"
  },
  {
    "type": "package",
    "package": {
      "name": "nnnick/chartjs",
      "version": "v3.9.1",
      "type": "drupal-library",
      "dist": {
        "url": "https://github.com/chartjs/Chart.js/releases/download/v3.9.1/chart.js-3.9.1.tgz",
        "type": "tar"
      }
    }
  },
],
...

```

An alternative suggested by leymannx is this, which allows to simply do `composer require npm-asset/FOOBAR` for any JS library that has an NPM release:

```
...
"repositories": [
  ...
  {
    "type": "composer",
    "url": "https://asset-packagist.org",
  },
  ...
],
...
"scripts": {
  ...
  "extras": {
    ...
    "installer-types": ["bower-asset", "npm-asset"],
    "installer-paths": {
      ...
      "web/libraries/{$name}": [
        "type:drupal-library",
        "type:bower-asset",
        "type:npm-asset"
      ],
      ...
    }
    ...
  }
  ...
}
...

```
> 4 votes

---
Tags: composer
---


# Question
Title: How to get the last updated time stamp of a field in field collection
How to get the last updated time stamp of a field in field collection.Is there any drupal built in function to get the timestamp

# Answer
There is no timestamp for field collection items. (Drupal 7)
> 0 votes

# Answer
To add "last updated time" on a post, use the *Timestamp* field. (I'm using Drupal 10)

This will not update past posts, but it will prompt the writer to select to update the stamp when editing (if you make it mandatory).

Here are the steps to implement this field (I'm using Drupal 10):

1. Structure
2. Content types
3. Select desired Content type
4. Add field
5. Select Timestamp and follow given instructions.
6. Label it "Last update" or anything you wish.

You may then rearrange where the field will show to a reader by going to Manage display (Structure/Content types/You content type/Manage display).
> 0 votes

---
Tags: entities, datetime
---


# Question
Title: How to properly downgrade an existing Drupal installation to a lower PHP version?
I've got a site smoothly running on Drupal 9.4.8 and PHP 8.1. Now I would like to enable APCu in PHP, but my provider unfortunately has installed APCu for PHP 8.0 only. If I simply switch to PHP 8.0, my Drupal installation gives me a an error message:

> Composer detected issues in your platform: Your Composer dependencies require a PHP version "\>= 8.1.0".

Which steps do I have to do, in order to make my site work in PHP 8.0?

# Answer
Assuming the platform on which you set dependencies is running a different version of PHP than 8.0, you do the following:

1. Ensure that if there is a direct `php` dependency in the `requires` section of `composer.json`, that it is `>=8.0` or similar.
2. Set a target platform version with `composer config platform.php 8.0.24`. The specific version you put here does not have to match the server platform's version exactly.
3. `composer update`.
> 3 votes

---
Tags: composer
---


# Question
Title: How can I send more than 5 emails per hour?
Drupal doesn't allow to send more than 5 emails per hour from a contact form.

Can this value of 5 be changed somewhere? I need to change it for testing.

# Answer
> 4 votes
As stated in the docs:

> There are hard-coded limits to how frequently contact forms can be submitted. In Drupal 8, a special drush command provides a way to configure flood control behavior: drush cedit contact.settings This lets you change the limit and time limit after which the flood restriction resets.
>
> You can view the default/current settings with:
>
> `drush config-get contact.settings`

When you execute `drush cedit contact.settings`, a text editor will appear (the details depend on your settings).

It will look something like this:

```
default_config_hash: abcdefg
langcode: en
default_form: feedback
flood:
  limit: 5
  interval: 3600
user_default_enabled: true

```

Change `limit` under `flood` to be the number of attempts you want per hour (defaults to `5`).

You can also change `interval` to adjust the number of seconds that the limit is imposed for (by default, `3600` seconds = 1 hour).

---
Tags: 9, emails
---


# Question
Title: How to make a Form that retrieve an entity and check if the form input matches with any part of the entity
*I'm using PHP 7.4 with Drupal 9.4.5*.

Hello, i'm new using Drupal programmatically and i'm trying to make a simple form that would allow me to insert an input and tell me if the inserted input exist, if it does, give me the name related to that input.

To make it clearer : I have an entity called **inscription** which are people with : name, email and a code. When entering the code on my form, i want to get the name related to that person.

My problem is, i can't manage to connect the form to my entity, i tried using Storage to do it.

```
$inscription = \Drupal::entityTypeManager()->getStorage('inscription')->loadByProperties(['code' => $form_state->getValue('code')]);
/** @var \Drupal\Mymodule\InscriptionInterface $inscription */
$inscription = $this->getEntity();

```

```
<?php

namespace Drupal\timeline_inscription\Form;

use Drupal\Core\Entity\ContentEntityConfirmFormBase;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\PageCache\ResponsePolicyInterface;
use Drupal\timeline_inscription\InscriptionInterface;
use Drupal\timeline_inscription\Entity\Inscription;
use Drupal\timeline_inscription\InscriptionManager;

/**
 * Provides a Mymodule form.
 */
class ControleForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'Mymodule_controle';
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {

    $form['code'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Controle Check'),
      '#required' => TRUE,
    ];

    $form['actions'] = [
      '#type' => 'actions',
    ];
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Send'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    if (mb_strlen($form_state->getValue('code')) < 12) {
      $form_state->setErrorByName('name', $this->t('Code must be at least 12 characters'));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // If the code exist in my entity .
    if ($form_state->getValue('code') == 'rcA4DEVNc1h9mukP') {
      $this->messenger()->addStatus($this->t('This code exist, name related to it :getValue('name') !'));
    }
    else {
      $this->messenger()->addStatus($this->t('This code doesn't exist'));
    }
    $form_state->setRedirect('timeline_inscription.controle');
  }
}

```

Or perhaps i need to use an EntityForm to do this ? I'm really confused.

Thanks a lot.

# Answer
> 0 votes
Alright, thanks to Kevin comments, i managed to do it using EntityQuery.

```
/**
 * {@inheritdoc}
 */
public function submitForm(array &$form, FormStateInterface $form_state) {
  $query = \Drupal::entityQuery('inscription');
  $query->condition('code', $form_state->getValue('code'));
  $uids = $query->execute();
  $users = \Drupal::entityTypeManager()->getStorage('inscription')->loadMultiple($uids);
  $details = array_map(function($user) {
    $name= $user->get('name')->value;
    $email= $user->get('email')->value;

    return 'Welcome, ' . $name . ' your email is : ' . $email. ' ';
  }, $users);

  if ($users) {
    $this->messenger()->addStatus($this->t('Code exists: ') . implode(" , ", $details));
  }
  else {
    $this->messenger()->addError($this->t('Code not found !'));
  }
}

```

---
Tags: entities, forms, 9
---


# Question
Title: Troubleshooting a Drupal HTTP 500 when there are no error log messages
I have reviewed some websites on how to troubleshoot HTTP 500 on a Drupal site and most often I have seen a PHP error by running drush ws in the console, however, I have been running into an oddity and I am not sure where to look to begin troubleshooting as this one doesn't throw HTTP 500.

I am not necessarily looking for someone to troubleshoot this bug specifically, and am not very good at writing/modifying any PHP, but it would be helpful to know how to identify the problem and fix it ... The problem only seems to occur when saving the field settings on a Taxonomy

Reproduction:

1. Have a Drupal site (latest core) with several modules installed (all up to date), and content types configured (not a fresh site). Running on Windows, IIS, MySQL, PHP 8.4 stack.
2. Create new content type (problem happens on existing too).

-- Define a name, but no other changes. I tried this with Boolean, text, taxonomy term ref - problem not isolated to one type.

-- Click save

-- Click save field settings

3. Receive HTTP 500

-- URL of the HTTP 500 after clicking Save Field Settings is /admin/structure/types/manage/test/fields/node.test.field\_testref/storage?destinations%5B0%5D%5Broute\_name%5D=entity.field\_config.node\_field\_edit\_form&destinations%5B0%5D%5Broute\_parameters%5D%5Bfield\_config%5D=node.test.field\_testref&destinations%5B0%5D%5Broute\_parameters%5D%5Bnode\_type%5D=test&destinations%5B1%5D%5Broute\_name%5D=entity.node.field\_ui\_fields&destinations%5B1%5D%5Broute\_parameters%5D%5Bfield\_config%5D=node.test.field\_testref&destinations%5B1%5D%5Broute\_parameters%5D%5Bnode\_type%5D=test&destinations%5B2%5D=/admin/structure/types/manage/test/fields/add-field

-- Only this URL is erroring out - the site itself is accessible. If I navigate using Admin Toolbar to Structure \> Content Types \> Test it also does not error out and I am able to edit/save that created field fine.

4. Refreshed page, ran drush ws - no errors but the page still throws HTTP 500
5. Ran drush cr/updb, error still occurs
6. Nothing errors/warnings in Status Report/recent log messages

-- I do have one "notice" in log, but didnt seem relevant. Module sliderwidget has an entry in the system.schema key/value storage, but is missing from your site.

# Answer
I assume, that you get 500 error with no information in your browser.

You can temporary activate display of all errors by adding the next lines in your `sites/default/settings.php` file:

```
// Show all errors.
$config['system.logging']['error_level'] = 'verbose';
error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);

```

This will give you a clue, where does the error happen.

In addition you can check server logs, as @cilefen commented.
> 0 votes

---
Tags: debugging, http-request, wsod
---


title: Menu items are displayed differently

text:
# Question
Title: Menu items are displayed differently
I have a multilingual page with the languages Spanish and English. When I edit the menu items in the backend, my default or original language is English. Now the menu links in this menu are always displayed in the language that is selected as the language path at the top of the browser bar. So I have something like https://stage-mydomaini.de/es/adminbereich/structure/menu/manage/main or https://stage-mydomaini.de/en/adminbereich/structure/menu/manage/main.

The menu links are displayed in the path language.
This kind of confuses me, because of course I always try to translate the Spanish link again. Isn't it not intended that the back-end always adapts to the path?

My settings in the speech recognition are the following.

>

>

>

Do any of you have an idea what this could be?

# Answer
The **Menu language** select box is for the original language of the menu configuration. In your case it seems the correct language should be German because of the label now assigned to it. After you have selected the original language and saved the menu config you can use the tab at the top *Translate Menu* to add a *Label* and *Menu Description* for other languages. This entire translation procedure is only for these two text fields.

Translating the menu items is a completely different process and is part of the content translation system where you need to enable translation of *Custom Menu Links* first. Then you can access the translate operation for each menu item.

Concerning the language detection, you have configured more language detection methods than normally necessary. For the start you need only one, the URL based method, which should also be at the top priority, only surpassed by *Account administration pages*, if you use this feature.
> 0 votes

---
Tags: i18n-l10n, navigation
---


# Question
Title: How to get total number of rows on a block of a view
On `hook_block_view_alter()` I need to get a total number of rows that this block displays.

For example, I have a view with the following block:

On `hook_block_view_alter()` I do the appropriate checks in order to weed out unnecessary blocks and get the one shown in the figure above.

```
function mymodule_block_view_alter(array &$build, \Drupal\Core\Block\BlockPluginInterface $block) {
  if (!preg_match('~^views_block:taxonomy_tag_list~', $block->getPluginId())) {
    return;
  }

  $view = $block->getViewExecutable();
  // Gets the number of rows
  $totalRows = $view->get_total_rows;
}

```

But for some reason, `$totalRows` contains `NULL`.

Here is the object of the current view:

Why can't I get the total number of rows? Maybe I'm using the wrong hook?

# Answer
> 3 votes
Use a `views_view_` hook, i.e. `views_view_unformatted`, `views_view_list` etc... I tried this with a PHP count for my views block and it worked great.

My function is:

```
function MYTHEME_preprocess_views_view_unformatted(&$vars) {
  $num_rows = $vars["rows"];
  $count = count($num_rows);
  echo '<h2>This view has ' . $count . ' rows</h2><br>';
}

```

This yielded the number of rows in the view.

Printed, I see:

# Answer
> 2 votes
No need for any hook.

Adding `{{ view.total_rows }}` in any views template, eg `views-view.html.twig` is enough

# Answer
> 1 votes
No need for any coding. Edit the view and under "Header" or "Footer" add a "Text area" (Category: Global) and see the available global token replacements.

To get the total number of rows add: `[view:total-rows]` and save the view.

---
Tags: views, 8, blocks
---


title: Redirect doesn't work for .pdf file

text:
# Question
Title: Redirect doesn't work for .pdf file
Is it possible to create a redirect for documents using the Redirect module? I can't seem to find a solid answer. Basically I'm just trying to create a redirect from https://www.example.com/default/files/2022-05/map.pdf to https://www.example.com/default/files/2022-10/map.pdf.

If this isn't possible, what would be a good recommendation other than modifying .htaccess as this is something that people without access or knowledge of .htaccess will need to use.

# Answer
> 2 votes
As @leymannx commented, the public file folder is not controlled by Drupal, it is delivered directly through the web server.

Move the file to the private file system. Then Drupal can control access to the file and also redirect if you want.

# Answer
> 1 votes
Using the private file system as described by @4uk4 is the correct way to secure the files and ensure only the correct users have access.

In addition to this, if you want to improve the convenience of managing files for site administrations (and perhaps users), you can use media entities.

This is more work for the developer to set up but it can standardize processes and make life easier for admins/users.

When you enable the core Media module, a **File** media entity type is created by default. You can customize this media type by adding additional fields, or you can just use the File media type as is.

When you do it this way:

* You need to create a **File** media entity for each file.
* To attach files to nodes, instead of a **File** field that stores the file directly, you use an **Entity Reference** field to the **File** media entity type.

As you can see, this adds some additional steps. But, then you get the following benefits:

* Each file has its own entity, so if you need the same file in multiple places, you can link it via entity reference instead of uploading it multiple times.
* You can easily sort files in Views and make views that show files based on various attributes.
* Media entities can store file metadata in fields, which can be filtered in views.
* The media entities can be themed and treated as "pages" (given URLs), so for example you could embed the pdf on the page or customize the download link to add whatever legal disclaimers you need.

---
Tags: files, 9, redirection
---


# Question
Title: How to automate the creation of product types?
I'm using Drupal 9 with Commerce 2. I have a large number of product types that need to be created. I have for each product type which fields need to be added. Let's say this information is stored in a json (I can vary this if the solution requires it). I was wondering if there is a way to create a module or something that iterates through this json file, and it creates all the product types. If there is, how would I go about implementing this?

I found some code examples with which I can create products programmatically here. I'm just not entirely sure how I would use this code inside a custom module.

I appreciate the help in advance!

# Answer
There is no way, just custom code all the way down. That said, it may be to your advantage *not* to have a proliferation of product types. They do create overhead on your site. Might be better simply to have optional fields on fewer, especially if their creation will be automated? Could always have a sub-type field on the product type itself that controls which fields are shown on the edit form via form states and even make various fields conditionally required.
> 1 votes

# Answer
I havent done this exactly with Commerce Entities, but I have done with custom entities using Migrate API.

What you can do is provide json or csv migrate source to migration and map those fields accordingly in `my_products_migration.yml` file , you can use contribute modules like, migrate\_plus, migrate\_source\_csv you can even refer migrate\_json\_example module from migrate\_plus which has a reference example for products migration.

You can refer commerce migrate documentation for additional details
> 1 votes

---
Tags: commerce
---


# Question
Title: Create alternate "View Modes" for Webform Submissions?
In a View of type "Webform Submissions", I have added a field called "Webform submission: Rendered entity". This displays the entire webform submission (content from all fields in the webform). My problem is that I have a few field elements in the webform that have create/view/update access permissions set to the Administrator role only. This is important because the webform is used by the Commerce Webform Order module to collect extended info for orders. The submitted results of those restricted fields are being displayed in the View.

The purpose of the View is to display the submitted contents of the webform in the Commerce receipt email. I do so with the following code in my order receipt template:

```
{{ drupal_view('my_view_name', 'block_1', order_entity.getOrderId) }}

```

As I stated, the restricted field results are being included in the Views output. In the "Webform submission: Rendered entity" field settings in the View, there is a selector called "View Mode" in which the only option is "Default". Is there a way to create a new View Mode for webform submissions, which would include only those fields that I choose? If so, I would be able to add the name, phone, etc fields and exclude the Admin-specific fields, and then select that alternate View Mode in the Views field settings. I have scoured the Webform settings in the back-end of the website, and I cannot find any opportunity to create that new View Mode for Webform Submissions.

# Answer
> 1 votes
`WebformSubmission` entities have only a few 'view modes', as defined in `\Drupal\webform\WebformSubmissionViewBuilder::buildComponents` method. Which means that if you want to have another one, you need to override `WebformSubmission` entity type view builder handler. These view modes are not exposed to views, so you need to provide your own views field handler as well.

---
Tags: webforms, 9
---


# Question
Title: Set conditional if statements based on field names in views-view-fields.html.twig
Is there a variable in views-view-fields.html.twig that contains the field machine name, or some other unique indicator? I am attempting something like this:

```
{% if field.[field_machine_name] == "my_field_machine_name" %}
   // Do stuff
{% endif %}

```

A massive workaround would be to create individual views.view.field--\[my\_view\]--\[my\_field\].html.twig templates for every field in the view, but it really seems like that shouldn't be necessary.

# Answer
I ended up accomplishing this through the views UI by setting all of my fields, except for the last one, to "hidden" and then rewriting the output of the last field to include the hidden fields, and including the markup that I want.
> 0 votes

# Answer
**How to Render Individual Fields in Views Templates: views-view-fields.html.twig**

I've created template for `views-view-fields.html.twig`.
For this I used some fields values as condition to set css classes and conditionally display div elements ect.

so I have set conditions via if statements almost the same as stated in createdbycocoon

`{% if fields.field_custom.content|striptags|trim is not empty %}` and it worked nicely but when i need get value of field and check its value (in my case it list text field type and i need the key of the list item) it won't work if you'll try to do it. like this sample

```
{% if (fields.uid.content|striptags) == 'John' %}

```

so I had my research and figure out how to do it

I did it like this:

```
{% set bg_type = row._entity.field_background_type.value|striptags|trim %}
{% if bg_type == 'KEY_VALUE' %}
...
{% endif %}

```

Basically *row.\_entity.field\_background\_type.value|striptags|trim* helped to get value and check it...

I hope it will help to some one ...
> 0 votes

---
Tags: views, theming
---


# Question
Title: Is there an equivalent of "drush dl pathauto --select" using "composer require module" name?
Coming from drush 7. I used to install modules using "drush dl module\_name --select" and I get a list of module versions I can select to download. Is there an equivalent for this for drupal 8/9 when using compose require to download modules? Currently I need to goto the module page name and copy the composure require line.

# Answer
> 3 votes
No.

But, you can use the "show" subcommand to show all available versions.

example:

```
composer show drupal/module_name --available

```

---
Tags: composer
---


title: How do I resolve these update errors?

text:
# Question
Title: How do I resolve these update errors?
Edit: I removed a couple modules that I thought might be causing the issue and uploaded the new error code. Edit 2: I cut some of the error code stuff to have the room to fit my composer.json file contents in. Edit 3: the composer require line was the wrong one, fixed that.

I am trying to update my site to drupal 9 following the Upgrading from Drupal 8 (or later) to a newer major version article on drupal.org. I just ran

```
composer require 'drupal/core-recommended:^9' 'drupal/core-composer-scaffold:^9' 'drupal/core-project-message:^9' --update-with-dependencies --no-update

```

and it worked, however when I tried to run

```
composer update

```

or

```
composer update -W

```

I got the following error both times

```
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - drupal/core-recommended 9.0.0-alpha1 requires composer/installers v1.7.0 -> found composer/installers[v1.7.0] but it conflicts with your root composer.json require (^1.9.0).
    - drupal/core-recommended[9.0.0-alpha2, ..., 9.0.0-beta2] require composer/installers v1.8.0 -> found composer/installers[v1.8.0] but it conflicts with your root composer.json require (^1.9.0).
    - drupal/core 8.0.0-beta6 requires doctrine/common dev-master#a45d110f71c323e29f41eb0696fa230e3fa1b1b5 -> found doctrine/common[dev-3.4.x-merge-up-into-3.5.x_WbajvUjT, 2.1.3, ..., 2.13.x-dev, 3.0.0, ..., 3.5.x-dev] but it does not match the constraint.
    - Root composer.json requires drupal/jcarousel ^4.0.0 -> satisfiable by drupal/jcarousel[4.0.0].
    - drupal/jcarousel 4.0.0 requires drupal/core ^8 -> satisfiable by drupal/core[8.0.0-beta6, ..., 8.9.x-dev].
    - You can only install one version of a package, so only one of these can be installed: drupal/core[8.0.0-beta6, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.5.x-dev, 10.0.0-alpha1, ..., 10.1.x-dev].
    - You can only install one version of a package, so only one of these can be installed: drupal/core[8.0.0-beta12, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.4.3, 10.0.0-alpha1].
    - You can only install one version of a package, so only one of these can be installed: drupal/core[8.0.0-rc3, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.4.3, 10.0.0-alpha1, ..., 10.0.0-alpha6].
    - You can only install one version of a package, so only one of these can be installed: drupal/core[8.4.0-alpha1, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.4.3, 10.0.0-alpha1, ..., 10.0.0-alpha6].
    - You can only install one version of a package, so only one of these can be installed: drupal/core[8.4.0-rc1, ..., 8.9.x-dev, 9.0.0-alpha1, ..., 9.4.3, 10.0.0-alpha1, ..., 10.0.0-alpha6].
    - drupal/core-recommended 9.0.x-dev requires drupal/core 9.0.x-dev -> satisfiable by drupal/core[9.0.x-dev].
    - Root composer.json requires drupal/core-recommended ^9 -> satisfiable by drupal/core-recommended[9.0.0-alpha1, ..., 9.5.x-dev].

Use the option --with-all-dependencies (-W) to allow upgrades, downgrades and removals for packages currently locked to specific versions.

```

It looks like this is a circular issue, but I cant see in there any indication on why the update failed and what I need to fix to be able to make the update work. Do any of y'all know what I need to do to make this drupal 9 composer update work?

Here is my composer.json file:

```
{
    "name": "my/project",
    "description": "Project template for Drupal 8 projects with composer",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "authors": [
        {
            "name": "",
            "role": ""
        }
    ],
    "repositories": {
        "drupal": {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        "asset-packagist": {
            "type": "composer",
            "url": "https://asset-packagist.org"
        }
    },
    "require": {
        "php": "^5.5.9|>=7.4.8",
        "composer/installers": "^1.9.0",
        "cweagans/composer-patches": "^1.6.5",
        "drupal/adminimal_admin_toolbar": "^1.7.0",
        "drupal/adminimal_theme": "^1.4.0",
        "drupal/adva": "^1.0.0-rc10",
        "drupal/allowed_formats": "^1.1.0",
        "drupal/background_image_formatter": "^1.3.0",
        "drupal/better_local_tasks": "^1.3.0",
        "drupal/bg_image_formatter": "^1.14.0",
        "drupal/blazy": "^2.5",
        "drupal/block_content_permissions": "^1.6.0",
        "drupal/block_field": "^1.0.0-rc2",
        "drupal/captcha": "^1.5",
        "drupal/ckeditor_iframe": "^2.0.0-beta1",
        "drupal/classy_paragraphs": "^1.0.0-beta3",
        "drupal/coffee": "^1.0.0-beta2",
        "drupal/color_field": "2.x-dev",
        "drupal/config_update": "^1.7.0",
        "drupal/contact_storage": "^1.0.0-beta9",
        "drupal/content_sync": "^3.0@beta",
        "drupal/contribute": "^5.0.0-beta3",
        "drupal/cookieconsent": "^1.3.0",
        "drupal/core-composer-scaffold": "^9",
        "drupal/core-project-message": "^9",
        "drupal/core-recommended": "^9",
        "drupal/ctools": "^3.9",
        "drupal/devel": "^4.2",
        "drupal/easy_breadcrumb": "^2.0",
        "drupal/eck": "^1.0.0-beta2",
        "drupal/entity": "^1.2.0",
        "drupal/entity_block": "^1.0.0-beta1",
        "drupal/entity_browser": "^2.6.0",
        "drupal/entity_reference_revisions": "^1.9.0",
        "drupal/eva": "^2.1.0",
        "drupal/facets": "^1.8.0",
        "drupal/fakeobjects": "^1.0.0",
        "drupal/fallback_formatter": "^1.2.0",
        "drupal/features": "^3.12.0",
        "drupal/field_group": "^3.3",
        "drupal/field_group_link": "^3.0.0-rc2",
        "drupal/field_name_prefix_remove": "^1.0.0",
        "drupal/field_permissions": "^1.2",
        "drupal/file_mdm": "^2.1.0",
        "drupal/flexslider": "^2.0.0-beta1",
        "drupal/fontyourface": "^3.2.0",
        "drupal/fpa": "^3.0",
        "drupal/google_analytics": "^3.1",
        "drupal/google_tag": "^1.4.0",
        "drupal/hreflang": "^1.0.0",
        "drupal/imagemagick": "^3.2.0",
        "drupal/jcarousel": "^4.0.0",
        "drupal/jquery_ui": "^1.4.0",
        "drupal/jquery_ui_accordion": "^1.1",
        "drupal/jquery_ui_draggable": "^1.2.0",
        "drupal/jquery_ui_droppable": "^1.2.0",
        "drupal/libraries": "^3.0.0-beta1",
        "drupal/link_target": "^1.4",
        "drupal/linked_field": "^1.1.0",
        "drupal/linkicon": "^1.7",
        "drupal/login_destination": "^2.0@beta",
        "drupal/maillog": "^1.0",
        "drupal/masonry": "^1.0.0-rc2",
        "drupal/masonry_views": "^1.0.0-rc1",
        "drupal/masquerade": "^2.0@RC",
        "drupal/media_entity_browser": "^2.0.0-alpha3",
        "drupal/menu_link_attributes": "^1.2.0",
        "drupal/migrate_file": "^2.0",
        "drupal/migrate_plus": "^5.1",
        "drupal/migrate_tools": "^5.0",
        "drupal/module_filter": "^3.2.0",
        "drupal/nodeaccess": "^1.0.0",
        "drupal/page_manager": "^4.0.0-beta6",
        "drupal/panelizer": "^4.1.0",
        "drupal/panels": "^4.6.0",
        "drupal/paragraphs": "^1.12.0",
        "drupal/paragraphs_access": "^2.0.0-rc1",
        "drupal/paragraphs_jquery_ui_accordion": "^1.4.0",
        "drupal/paragraphs_viewmode": "^1.0.0",
        "drupal/pathauto": "^1.8.0",
        "drupal/permissions_filter": "^1.2.0",
        "drupal/publishcontent": "^1.0.0",
        "drupal/purge_purger_http": "^1.0.0-beta4",
        "drupal/qa_accounts": "^1.0.0-alpha1",
        "drupal/rabbit_hole": "^1.0.0-beta4",
        "drupal/rebuild_cache_access": "^1.8",
        "drupal/recaptcha": "^3.1",
        "drupal/redirect": "^1.6.0",
        "drupal/responsive_menu": "^4.4",
        "drupal/robotstxt": "^1.2.0",
        "drupal/role_delegation": "^1.1.0",
        "drupal/rules": "^3.0.0-alpha6",
        "drupal/scheduler": "^1.0.0",
        "drupal/schemata": "^1.0.0-alpha3",
        "drupal/search_api": "^1.20.0",
        "drupal/search_api_autocomplete": "^1.5.0",
        "drupal/search_api_sort_priority": "^1.10",
        "drupal/seckit": "^2.0",
        "drupal/security_review": "^1.0",
        "drupal/sharethis": "^2.0.0-beta3",
        "drupal/simple_sitemap": "^3.10.0",
        "drupal/slick": "^2.6",
        "drupal/slick_views": "^2.6",
        "drupal/smart_trim": "^1.1.0",
        "drupal/social_media_links": "^2.8.0",
        "drupal/sophron": "^1.1.0",
        "drupal/svg_image": "^1.15.0",
        "drupal/title_field_for_manage_display": "^2.0.0",
        "drupal/token": "^1.9.0",
        "drupal/token_filter": "^1.0.0",
        "drupal/twig_tweak": "^2.1.0",
        "drupal/twig_vardumper": "^2.2.0",
        "drupal/twitter_block": "^3.0.0-alpha0",
        "drupal/typed_data": "^1.0.0-alpha5",
        "drupal/ultimate_cron": "^2.0.0-alpha4",
        "drupal/username_policy": "^2.0@beta",
        "drupal/vardumper": "^1.6.0",
        "drupal/video_embed_field": "^2.0.0",
        "drupal/views_slideshow": "^4.6.0",
        "drupal/webform": "^6.1",
        "drupal/weight": "^3.0.0",
        "drush/drush": "^10.0"
    },
    "config": {
        "sort-packages": true,
        "discard-changes": true,
        "allow-plugins": {
            "composer/installers": true,
            "cweagans/composer-patches": true,
            "drupal/core-composer-scaffold": true
        }
    },
    "conflict": {
        "drupal/drupal": "*"
    },
    "extra": {
        "enable-patching": true,
        "composer-exit-on-patch-failure": false,
        "patches": [],
        "drupal-scaffold": {
            "locations": {
                "web-root": "./docroot"
            }
        },
        "installer-types": [
            "bower-asset",
            "npm-asset"
        ],
        "installer-paths": {
            "drush/Commands/{$name}": [
                "type:drupal-drush"
            ],
            "docroot/core": [
                "type:drupal-core"
            ],
            "docroot/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "docroot/modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "docroot/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "docroot/profiles/custom/{$name}": [
                "type:drupal-custom-profile"
            ],
            "docroot/themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "docroot/themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ],
            "docroot/libraries/{$name}": [
                "type:drupal-library",
                "type:bower-asset",
                "type:npm-asset"
            ]
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}

```

# Answer
You must update drupal/jcarousel to a version that is compatible with Drupal 9. Its current ^4.0.0 constraint does not allow that to occur.
> 1 votes

---
Tags: 9, composer
---


# Question
Title: What is the template code for order date and telephone number
In our invoice that is printed, the date of the order and the telephone of the customer is missing. How can I print those into the template?

# Answer
Using `{{ invoice_entity.orders.0 }}` you get access to the order.

So if you're looking to print the order completed time you'd need something like:

`{{ invoice_entity.orders.0.getCompletedTime }}` which is a timestamp. You'd need getPlacedTime in case you need access to the placed timestamp.

For the telephone, where is that stored? On the profile itself?

```
{{ invoice_entity.getBillingProfile.(your phone field name here I suppose) }}

```
> 1 votes

---
Tags: commerce
---


# Question
Title: How can I have my own custom invoice number pattern?
Hi Im trying to make different pattern for the invoice in Drupal 9. I have products with two kind of price one is for particular and the other one is for profesional.

i would like to have two pattern number for the invoice, for particular 22-ES-00001 and for profesional 22-ES-P-00001. I already create the two kind of pattern number and i have two kind of invoice type and also asign each pattern number to the invoice type.

I just need to associate the invoice type to the role. But dont know the way of how to do it any one have any idea about how can i do it?

Thanks in advance.

# Answer
> 1 votes
The invoice number is generated from `Invoice::presave();`, using the following code:

```
if ($this->getState()->getId() != 'draft' && empty($this->getInvoiceNumber())) {
  /** @var \Drupal\commerce_number_pattern\Entity\NumberPatternInterface $number_pattern */
  $number_pattern = $invoice_type->getNumberPattern();
  if ($number_pattern) {
    $invoice_number = $number_pattern->getPlugin()->generate($this);
    $this->setInvoiceNumber($invoice_number);
  }
}

```

What I'd do if I were you, in order for this code to be bypassed is that I'd set a "fake" temporary invoice number on invoice creation (by reacting to the `InvoiceEvents::INVOICE_CREATE` event.

Then from the same event subscriber reacting to `InvoiceEvents::INVOICE_PRESAVE` I'd add my own logic to invoice the right number pattern plugin.

Setting an invoice number on invoice creation would help bypassing the comemrce\_invoice code, and you could have your own logic running on invoice presave.

Here's the documentation around event subscribers in case you need help with that.

---
Tags: commerce
---


title: How to get last X contents

text:
# Question
Title: How to get last X contents
I want to write a function inside a module that will return last 20 contents of type X . is there any drupal ready function ? or shall i use queries ?

THanks

# Answer
> 2 votes
You'll want to make use of the `db_query_range()` and `node_load_multiple()` functions:

```
$args = array(':type' => $content_type);
$sql = 'SELECT nid FROM {node} WHERE status = 1 AND type  = :type ORDER BY created DESC';
$nids = db_query_range($sql, 0, 20, $args)->fetchCol();

$nodes = node_load_multiple($nids);
foreach ($nodes as $node) {
  // ...
}

```

# Answer
> 2 votes
You can use views to get that.

Make sure you sort items descending and limit the result number to be 20.

# Answer
> 0 votes
There is no special function for that, so you have to use the query.
This will fetch you last 20 published NIDs of a specific content type, which you can after load as node objects.

```
$last_20_nodes = db_query("SELECT `nid` FROM {node} WHERE `type` = :content_type AND `status` = 1 ORDER BY `created` DESC LIMIT 0, 20", array(':content_type' => 'YOUR CONTENT TYPE'));
foreach ($last_20_nodes as $last_node) {
  // Load the node object.
  $node = node_load($last_node->nid);
  // Continue with your process.
  // To see available properties and values, do a dpm($node).
}

```

Update: as Clive noted below, this might result in a lot of queries to possibly get just a few fields. Depending on your exact needs, it might be better to fetch only fields you need, rather than loading the nodes.

# Answer
> 0 votes
For **Drupal** 8 or 9 you can make use of entityQuery, as seen in the following code.

```
$query = \Drupal::entityQuery('node');
$query->condition('status', 1)
  ->condition('type', 'content_type')
  ->range(0,20)
  ->sort('created','DESC');
$entity_ids = $query->execute();

```

---
Tags: nodes
---


# Question
Title: show "My billing information is the same as my shipping information." option when creating order from admin
I am using Drupal version 9.3.14. Option "My billing information is the same as my shipping information." gets available on checkout page automatically. But when creating order from Admin side this option is not available resulting into filling same address twice in shipping and billing address.

How can I make this option available on admin side also?

# Answer
> 2 votes
It's roughly supported but not a great experience. Essentially, you would have to create the order without any billing details then create a shipment for the order. After doing so, when you go back to the order edit screen and click the button to add a billing address, it will default to copying the address from the shipment.

Ideally, the shipment add form would have a similar option to copy from the billing address instead, since the order management flow is different from the checkout flow. I'm going to file that as a feature request for the Commerce Shipping module.

---
Tags: commerce
---


# Question
Title: Problem with refreshing the access token
I am building an app which uses Drupal (9.4.8) as the API. I am using the Simple OAuth module to authorise the client. I have got almost everything working fine, I am receiving the Access Token and the Refresh Token as expected. But, after a lot of searching, I still can't find out which path I need to refresh the tokens.

According to this video tokens can be refreshed on the path "/simple-oauth/refresh". But that path doesn't exist and I guess the video refers to an old version of the module...

Can anyone shed any light on this?

# Answer
> 2 votes
I have got it working with the following steps:

In the Auth strategy in nuxt.config.js

* Set the refresh path to **/oauth/token** (I also added a query string, ?refresh to distinguish out from the login path)
* Add this to the header **'Content-Type': 'application/x-www-form-urlencoded'**

Here's the code:

```
    refresh: {
     url: '/oauth/token?refresh',
     method: 'post',
     headers: { 'Accept': '*/*','Content-Type': 'application/x-www-form-urlencoded' },
    },

```

I still had problems sending the body in the x-www-form-urlencoded format, so I then created an Axios interceptor plugin to alter the request. This plugin (~/plugins/axios.js) intercepts request made to /oauth/token?refresh and puts the **grant type**, the **refresh token** and the **client id** in the correct format.

Here's the plugin:

```
var qs = require('qs');

export default function ({ $axios, redirect }) {
  $axios.onRequest(config => {
    if (config.url == '/oauth/token?refresh') {
      const params = new URLSearchParams(config.data);
      const refreshToken params.get('refresh_token');
      config.data = qs.stringify({'grant_type': 'refresh_token', 'refresh_token': refreshToken,'client_id':'xxxxx-your-client-id-XXXX'})
    }
  })
}

```

---
Tags: 9, authentication-authorization
---


# Question
Title: How to display entity reference field in User Profile Twig
I asked this over on the Drupal.org forum, but I thought I'd give it a try here too.

I am using an taxonomy entity reference field to display author names on our site. I added a 'published\_name' field and referenced it to the Author taxonomy. What I'd like to do is make a custom user profile twig that shows that entity reference field value on the author's profile page, including it's link, so when the displayed name is clicked, it shows all the books connected to that author. I made two different profile types using the Profile Module. Everyone gets a Public Profile, and the authors get a second one just for their custom information. The Writer Profile (machine name writer\_profile) is the one with the field 'field\_published\_name'.

On the writer's profile page, In the manage display of admin/config/people/profile-types/manage/writer\_profile, I added the Published name field, I set it as Format: Label; Link to the referenced entity. The field does show, and work when clicked on the User page, but I can't control where, and how, it looks without using a twig. I want to customize when, where, and how it would be displayed on the page.

I have tried in the user.html.twig:

```
{% for item in items %}
  {{ item.content['#user'].field_published_name.value }}
{% endfor %}

```

Also:

```
<article{{ attributes.addClass('profile') }}>
  {% if content %}
    {{- content.field_published_name -}}
  {% endif %}
</article>

```

On admin/config/people/accounts/display I have it set to show the 'Public Profile profiles' and 'Writer Profile profiles' format as Rendered entity.

So far it just comes up empty while showing the rest of the user's info on their profile page.

# Answer
> 0 votes
The question is not really clear, at least for me.

If it is: "how I customize the display of an entity referenced via a entity reference field" you have at least two ways:

1. On the child entity - taxonomy term - configure a view mode in the way you want. On the parent entity display mode choose "Rendered entity" as display mode of the field, and choose the display set up above.  If necessary, you may override the twig of that "child entity" display to fine grain the customization
2. In the twig of the parent entity you can access the "child" entity either with

```
{% set child_entity = content.field_reference.entity %}
{% set child_entity = drupal_entity('entity_type', entity_id') %} // using twig tweak module

```

---
Tags: entities
---


# Question
Title: How do you build up a LIKE condition in a db_select() query?
How do you build up a `LIKE` condition in a `db_select()` query?

I know how to do this with a `db_query()` API call, but is there a special syntax / method for doing this with `db_select()`?

# Answer
> 22 votes
After digging through Drupal Documentation found a solution in db\_like API documentation page and SelectQuery:condition handler doc page..

For example

```
$result = db_select('field_data_field_name', 'f')->fields('f', array(
    'entity_id',
    'field_name_value'
))
->condition('entity_type', 'user')
->condition('bundle', 'user')
->condition('deleted', 0)
->condition('field_name_value', '%' . db_like($last_item) . '%', 'LIKE')
->distinct()
->range(0, 10)
->execute();

```

Condition to use for like query is

```
->condition('field_name_value', '%' . db_like($last_item) . '%', 'LIKE')

```

# Answer
> 4 votes
In Drupal 8 and higher versions, you need to use `Drupal\Core\Database\Database`, as in the following code.

```
$database = Database::getConnection();
$query = $database->select('TABLE NAME', 'u')
    ->fields('u', array('column1','column2'));
$query->condition('column1', '%'.$database->escapeLike($search_phrase) . '%', 'LIKE');

```

Alternatively, you can use this code.

```
$db_or = $query->orConditionGroup()
 ->condition('column1', '%' . $database->escapeLike($search_phrase) . '%', 'LIKE')
 ->condition('column2', $database->escapeLike($search_phrase) . '%', 'LIKE')
 ->condition('column1', '%' . $database->escapeLike($search_phrase), 'LIKE');
$query->condition($db_or);
$result = $query->execute();

```

# Answer
> 1 votes
For using "like" in `db_select` is as below and worked for me...

```
$search_value = "testvalue@xmail.com";
$query = db_select('TABLE NAME', 'u');
$query->fields('u', ['ROW1', 'ROW2']);
$query->condition('ROW1', '%' . db_like($search_value) . '%', 'LIKE');
$result = $query->execute();

```

Here exact value in ROW1 is "testvalue@xmail.com" and by using `LIKE` condition in `db_select` I got the output as "testvalue@xmail.com".

# Answer
> 1 votes
The following code works in Drupal 8.x, but it won't work in Drupal 9.x, as `db_like()` has been removed.

```
$connection = \Drupal::database();
$query = $connection ->select('node', 'n');
$query->fields('n');
$query->condition('nid', '%'.db_like($exp), 'LIKE');
$records = $query->execute();

```

# Answer
> 0 votes
Since db\_like() is deprecated in Drupal 8.x and removed in Drupal 9.x, the documentation suggests to use Connection::escapeLike() instead.

The following code works in Drupal 8 and 9.

```
$connection = Database::getConnection();
$query = $connection->select('your_table_name', 'table_alias')
  ->fields('table_alias', ['whatever_field', 'other_field'])
  ->condition('my_field_name', '%' . $connection->escapeLike($yourSearchString) . '%', 'LIKE');

$result = $query->execute()->fetchAll();

```

# Answer
> 0 votes
For code that injected the *database* service in `$this->database`. the following is the code I would use in Drupal 9.x.

```
$escaped = $this->database->escapeLike($input);
$query = $this->database->select('zipcodes', 'z');
$query->fields('z', ['city', 'zip', 'state']);
$orGroup = $query->orConditionGroup()
  ->condition('city', '%' . $escaped . '%', 'LIKE')
  ->condition('z.zip', '%' . $escaped . '%', 'LIKE');

$query->condition($orGroup);
$query->range(0, 10);
$result = $query->execute();
if (!empty($result)) {
  foreach ($result as $record) {
    $string = $record->city . ' ' .$record->state. ' - ' .$record->zip;
    $value_string = $record->city. '~' .$record->state. '~' .$record->zip;
    $data[] = [
      'label' => $string,
      'value' => $value_string,
    ];
  }
}

```

---
Tags: database
---


title: drupalTranslations is not defined

text:
# Question
Title: drupalTranslations is not defined
I'm an Angular front-end developer. I work with a team that uses Drupal for content.

The scenario is that we use `Drupal.t()` to translate the strings.

When I translate the word from the back-office, it works, but I can't see the change on my page. So I tested it with another laptop from a colleague, and it works.

My colleague has `drupalTranslations()`, which gives him the translated strings.

When I run this function in my browser, it doesn't work. `drupalTranslations()` is not defined while `Drupal` and `drupalSettings` work.

>

Do I have to install something?

FYI: We run the project with Docker (Drupal 9.x).

# Answer
> 0 votes
I'm able to replicate the issue on Drupal 9 with a simple javscript file

```
console.log(Drupal.t('Comments'))
console.log(Drupal.drupalTranslations('Comments'))

コメント
TypeError: Drupal.drupalTranslations is not a function

```

There appears to be an open issue (Text in Drupal.t() on some pages is not translated after installing a module \[library cache problem\]) related to this marked active but without progress since 2018. The issue relates to a caching bug.

I also found drupal-8-react-i18n-and-typescript which might help you along, but if you're using the same code as your colleague, I'm inclined to thing it is the cache bug.

---
Tags: javascript, 9
---


# Question
Title: How can I append a field to the body field?
I have a content type (*Press releases*) with three fields: *field\_date*, *field\_location*, and *body*.

I am trying to create a template override for this content type based on this design.

>

As you can see in the image, the date and location fields are appended to the body field.

I have tried adding all the fields in a single `<div>` and setting its `display` property to `inline`, but nothing has happened.

This is the code from the template override.

```
<div class="press-releases-body">
  {{content.field_release_date}}
  {{content.field_location}}
  {{ content.body }}
</div>

```

# Answer
For a formatted text field I would append the field data in a preprocess hook so that you can add the text within the enclosing field template and also remove the `<p>` tag Ckeditor adds automatically to the content of the field:

```
function mytheme_preprocess_node__press_releases(&$variables) {
  /** @var \Drupal\node\NodeInterface $node */
  $node = $variables['node'];
  if (isset($variables['content']['body'][0])) {
    $body = $variables['content']['body'][0]['#text'];
    $body = preg_replace(['#^<p>#', '#</p>$#'], '', $body);
    $date = $node->field_date->date ? $node->field_date->date->format('Y-m-d H:i:s') : '';
    $location = $node->field_location->value;
    $body = $date . ' - ' . $location . ' - ' . $body;
    $variables['content']['body'][0]['#text'] = $body;
  }
}

```

Then you don't need to configure the two appended fields in the display settings and it's not necessary to change the twig template.
> 3 votes

# Answer
Patrick Kenny is, most probably, right about templates "down the chain".

Copy `your_site_directory/sites/default/default.services.yml`

as `your_site_directory/sites/default/services.yml`

and modify it to enable twig debug:

```
parameters:
  twig.config:
    debug: true

```

Clear the caches and inspect what templates you should target.
> 1 votes

---
Tags: theming, 9
---


# Question
Title: How can I remove preview button from contact form?
How to turn off preview in contact form in Drupal 8.1.x

##

# Answer
A custom module can utilize `hook_form_alter()` to strip out the preview button form element in any form:

```
/**
 * Implements hook_form_alter().
 */
function MYMODULE_form_alter(&$form, $form_state, $form_id) {

  // Look for any form provided by the contact module.
  // If you want to target a specific form you'll use the whole form ID
  // (e.g. Website feedback = 'contact_message_feedback_form').
  if (strpos($form_id, 'contact_message_') !== FALSE) {
    $form['actions']['preview']['#access'] = FALSE;
  }
}

```
> 15 votes

# Answer
It's works for me The best way to do that Add this code your YOURPROFILENAME.profile file

```
/**
 * Implements hook_form_alter().
 */
function YOURPROFILENAME_form_alter(&$form, $form_state, $form_id) {
   if (strpos($form_id, 'contact_message_') !== FALSE) {
    $form['actions']['preview']['#access'] = FALSE;
  }
}

```
> 1 votes

# Answer
There are patches under work and testing but no commits yet https://www.drupal.org/project/drupal/issues/2960353. Patches work on latest D8 to date, but until a patch has been committed, suggest to use Hide Preview Button module https://www.drupal.org/project/hide\_preview works well for other form pages, too. In case, this helps those not comfortable with working with hooks and patches.
> 1 votes

# Answer
I support the answer suggesting to remove the "Preview" button via the "Manage Form Display":

> You can go to Manage Form Display for the desired contact form and move the "Preview sender message" to "Disabled".

But, you need to **clear cache** before it takes effect.

For me, it is the simplest solution.
> 0 votes

# Answer
Starting Drupal version 9.1, you can go to Manage Form Display for the desired contact form and move the "Preview sender message" to "Disabled". That hides the preview button in the form.
> -1 votes

---
Tags: 8, emails
---


# Question
Title: How can I get the field value from preprocess_field?
I would like to get the content of the field with is formatted text to manipulate it a bit (strip from HTML tags and limit) and display it as another variable in twig.

How can I get the value of the field?

This is what I've written so far, and I tried to output the value in the "if statement", but no luck so far:

```
function bootstrap4grow_preprocess_field(&$variables) {
  if ($variables['field_name'] == 'field_training_seo') {
  }
}

```

# Answer
> 4 votes
It's all in the `$variables`. Consider using Xdebug to find out yourself.

```
/**
 * Implements template_preprocess_field().
 */
function MYTHEME_preprocess_field(&$variables) {
  if ($variables['element']['#field_name'] === 'field_MYFIELD') {
    /** @var \Drupal\Core\Field\FieldItemList $items */
    $items = $variables['element']['#items'];
    foreach ($items->getValue() as $delta => $item) {
      // Depending on the field type you find the value in $item['value'],
      // $item['target_id'] etc.
      $value = $item['value'];
      // ....
    }
  }
}

```

---
Tags: theming, 9
---


title: Oauth/Saml for particular pages

text:
# Question
Title: Oauth/Saml for particular pages
I see several modules that allow oauth2/oicd/saml login to the Drupal website (my id provider allows any of the above). I am looking for different setup, I would like to configure the site so that only specific routes are protected by the oauth2/oicd/saml, not using it for general authentication, but specific paths and routes. How can I set this up in Drupal 9? Is there a module that supports this functionality?

Desired Scenario Faculty member wants to access a particular form on the website, they go to /secure/webformXYZ and are directed to authenticate with the campus security system and then returned to the page, **NO ACCOUNT IS CREATED FOR THE PERSON**, but they have access to that page because the returned attributes indicate that are a faculty member (and optionally, the values returned from the authentication are used to prefill the form). People who access anywhere else on the site are not encumbered by needing to login, nor is our system crowded with unneeded accounts from the faculty who did access one of those many forms.

# Answer
> 0 votes
Use the SimpleSAMLphp Auth module. In its settings select "Allow authentication with local Drupal accounts" and in the "Automatic role population from simpleSAMLphp attributes" configuration use any of the attributes sent by the identity provider to assign a role or roles to the authenticated users.

Now that the users have distinguishing roles use a role-based access control on the content, like Content Access.

# Answer
> 0 votes
For anyone facing a similar situation, I was unable to find a way to make this work without writing a custom module, I was however able to use Apache's mod\_auth\_openidc to secure the paths in question.

---
Tags: authentication-authorization
---


# Question
Title: html.html.twig Template Name for content type
https://www.drupal.org/docs/theming-drupal/twig-in-drupal/twig-template-naming-conventions gives the example of html--node--\[nodeid\].html.twig for an individual node - what template name can I use for html.html.twig for a content type such as Article?

# Answer
You can create your own theme suggestions. If you want to create a custom suggestion for `html.html.twig`, you need to use the hook `hook_theme_suggestion_html_alter`.

in your `theme_name.theme` file add the following function:

```
function theme_name_theme_suggestion_html_alter(array &$suggestions, array $variables) {
  if ($node = \Drupal::routeMatch()->getParameter('node')) {
    $suggestions[] = 'html__' . $node->bundle();
}

```
> 0 votes

---
Tags: theming
---


# Question
Title: entityQuery filter by content moderation state
I need to filter a node by moderation state. I am using the Drupal 8 content moderation module.

I basically want to get NIDs of all nodes in draft state. Something similar to this.

```
$nids = \Drupal::entityQuery('node')
      ->condition('moderation_state', 'draft')
      ->execute();

```

# Answer
> 5 votes
An additional workaround to this is you can add a tag to the entity query and then alter it in a separate `hook_query_TAG_alter` hook. It's an extra step but it gets the job done and gives you direct access to the SQL query for you to modify. So you can generate the entity query like you normally would, and any extra SQL that it does not support you can modify as needed.

Entity query:

```
/** @var \Drupal\node\NodeStorage $storage */
$storage = \Drupal::entityTypeManager()->getStorage('node');
$query = $storage->getQuery()
  ->addTag('archive_press_releases')
  ->currentRevision()
  ->condition('type', ['post_page', 'story_page'], 'IN')
  ->condition('field_date', $formatted, '<=')
  ->sort('field_date');
$result = $query->execute();

```

hook\_query\_TAG\_alter example:

```
/**
 * Implements hook_query_TAG_alter().
 */
function bax_archiving_query_archive_press_releases_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
  $query->addJoin('LEFT', 'content_moderation_state_field_data', 'md', 'md.content_entity_revision_id = base_table.vid');
  $query->condition('md.moderation_state', 'archived', '<>');
}

```

# Answer
> 3 votes
You try the code :

```
$query = \Drupal::database()->select('content_moderation_state_field_data', 'ms');
    $query->join('node_field_revision', 'nf', 'nf.nid=ms.content_entity_id AND nf.vid=ms.content_entity_revision_id AND nf.langcode=ms.langcode');
    $query->fields('ms');
    $query->condition('ms.moderation_state','draft');
    $results = $query->execute()->fetchAllAssoc('content_entity_id');

```

Because `entityQuery` not filter content moderation

# Answer
> 1 votes
Posting a link to the d.o issue queue where as of this week a *potential patch* to core to allow `EntityQuery` to recognize Workflow moderation state that @Santiago cited above: https://www.drupal.org/project/drupal/issues/3025164#comment-13221005 Without this patch or a similar core hack, EntityQuery can not query Drupal 8 Workflow moderation state.

# Answer
> 1 votes
The answer by Lester Peabody almost worked for me.

However, it could gives unwanted results, depending the logic you expect.

1. `archived` state by default settings is a *default revision* state, therefore querying for `currentRevision()` nodes will count also the ones which have another not-default moderation state. E.g.:a node has been `archived` and later moved again in `draft` With that query that node *will be counted*. In the case this is not wanted, it's better to query against nodes' latest revision.
2. It doesn't consider the case the eventual translation.

If 1. and 2. are legit cases then the coode is:

```
function example() {
    $query = \Drupal::entityTypeManager()->getStorage('node')->getQuery();

    return $query->addTag('example_tag')
      ->latestRevision()
      ->condition('type', 'node_type')
      ->condition('langcode', 'en')
      ->execute();
}

/**
 * Implements hook_query_TAG_alter().
 */
function hook_query_example_tag_alter(Drupal\Core\Database\Query\AlterableInterface $query) {
  $query->addJoin('LEFT', 'content_moderation_state_field_revision', 'md', 'md.content_entity_revision_id = base_table.vid AND md.langcode = base_table.langcode');
  $query->condition('md.moderation_state', 'archived', '<>');
}

```

---
Tags: 8, nodes
---