# Question
Title: drush configuration import export order of the yml
I recently upgraded some minor versions of modules and upgraded Drupal core-recommended to 9.3.3 from 9.2.9. I followed the usual drush updatedb, drush cim -y drush cr and everything looks fine.

In my local env, everything is fine. However, in my dev environment in platform.sh, drush cim keeps importing ALL 860 config files. It doesn't matter how many times you run drush updatedb, drush cim -y and drush cr, it ALWAYS keeps importing the same files.

Running import through the gui yields the same result.

When running drush cim --diff I can see that the yml are the same but in different order, example:

```
    @@ -47,10 +47,10 @@ type_settings:
       weight: 3
     publish:
       label: Publish
-      from:
-        - draft
       to: published
       weight: 1
+      from:
+        - draft
     reject:
       label: Reject
       from:

```

Any ideas are welcome. I will try exporting from the server and importing in local to see if this fixes the issue.

Thanks!

# Answer
> 1 votes
I Downloaded my configuration from the server and imported it in local. Then did drush cex from local and pushed it to the server. This solved the issue.

---
Tags: drush, configuration, importing-exporting
---


# Question
Title: How can I override the node template for one multi-site instance?
I have several Drupal 9 sites on multi-site setup. currently all these sub sites use one theme placed in /themes/MyTheme folder.

now i need to theme few nodes on site A and site B and this is only difference between all sites. if i use `page--node--x.html.twig` convention to change layout of node x on site A, it changes layout of node x on all sites.

what is easiest way to apply `page--node--x.html.twig` only to site A but not site B?

is it possible to have theme on themes/MyTheme/ folder but copy only `page--node--x.html.twig` to sites/siteA/themes/custom folder to overwrite this layout only for site A?

# Answer
> 5 votes
I once had a question on how to get current multi-site instance name. You can use the accepted answer's code to add another template suggestion based on the name then:

```
/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function MYTHEME_theme_suggestions_node_alter(array &$suggestions, array $variables) {
  $site_path = \Drupal\Core\DrupalKernel::findSitePath(\Drupal::request());
  $site_path = explode('/', $site_path);
  $site_name = $site_path[1];
  $site_specific_suggestions = [];
  foreach ($suggestions as $suggestion) {
    $site_specific_suggestions[] = $suggestion . '__site_' . $site_name;
  }
  $suggestions = array_merge($suggestions, $site_specific_suggestions);
}

```

Before:

```
<!-- FILE NAME SUGGESTIONS:
   * node--236--full.html.twig
   * node--236.html.twig
   x node--page--full.html.twig
   * node--page.html.twig
   * node--full.html.twig
   * node.html.twig
-->

```

After:

```
<!-- FILE NAME SUGGESTIONS:
   * node--236--full--site-default.html.twig
   * node--236--site-default.html.twig
   * node--page--full--site-default.html.twig
   * node--page--site-default.html.twig
   * node--full--site-default.html.twig
   * node--236--full.html.twig
   * node--236.html.twig
   x node--page--full.html.twig
   * node--page.html.twig
   * node--full.html.twig
   * node.html.twig
-->

```

---
Tags: theming, 9, multi-sites
---


# Question
Title: How to send a contact form via JSON:API?
What are the requirements for submitting the contact form using JSON:API?

I enabled the core Contacts module and set up a custom site-wide contact form. I gave permission to anon + auth users to submit the form.

Next, I enabled JSON:API. I can see the contact form at `/jsonapi/contact_form/contact_form`:

```
"data":[
   {
      "type":"contact_form--contact_form",
      "id":"d97e73f1-7d06-4bf0-b05b-1c654a659dfc",
      "links":{
         "self":{
            "href":"https://example.lndo.site/jsonapi/contact_form/contact_form/d97e73f1-7d06-4bf0-b05b-1c654a659dfc"
         }
      },
      "langcode":"ja",
      "status":true,
      "dependencies":[

      ],
      "drupal_internal__id":"example_support",
      "label":"Example Support",
      "recipients":[
         "support@example.com"
      ],
      "reply":"",
      "weight":0,
      "message":"Thank you for submitting.",
      "redirect":""
   }
],

```

But, what is the endpoint I need to POST to in order to submit this form?

I found this issue about emails not getting sent when a contact form is submitted via REST.

That issue suggests that the `/entity/contact_message` REST endpoint must be enabled to submit the contact form-- is this also true for JSON:API?

I'm confused because using JSON:API, I can submit nodes without enabling any REST endpoints by POSTing to `/jsonapi/node/content_type`.

# Answer
> 2 votes
It seems a REST endpoint is required in this case because although contact forms are entities, contact form submissions are not entities unless you use the Contact Storage module.

However, given the core issue with notifications not being sent and the large number of RTBC and "Needs review" issues in the Contact Storage issue queue as of January 30, 2022, I decided to take a different approach. If a user is upset and reaches out for support, it's especially terrible to have some bug cause their submission to go missing or the response to be late.

So I solved this using the Webform REST module:

1. Install the module.
2. Enable the **Webform submit** REST resource using REST UI module.
3. Create the webform.
4. Add code to the frontend app to submit the form.

I got this working in about an hour, and the only additional change I have had to make so far is to patch Webform REST so that I can uninstall REST UI after enabling the endpoint.

---
Tags: entities, 9
---


# Question
Title: How set html 'lang' to match node 'langcode'?
I would like to change a node's html 'lang' from site's default to the node's 'langcode'.

For example, if I create a node and while creating I select French as the language, I would like the page's html 'lang' to "fr"

So far I have this:

```
  /** @var \Drupal\Core\Template\Attribute $html_attribute */
  $html_attribute = $variables['html_attributes'];
  $node_langcode = $node->get('langcode')->value;
  if ($html_attribute->hasAttribute("lang")) {
    $html_attribute->removeAttribute('lang');
    $html_attribute->setAttribute('lang', $node_langcode);
  }

```

# Answer
This code worked properly

```
if(!empty($node) && $node instanceof NodeInterface) {
    /** @var \Drupal\Core\Template\Attribute $html_attribute */
    $html_attribute = $variables['html_attributes'];
    $node_langcode = $node->get('langcode')->value;
    if ($html_attribute->hasAttribute("lang")) {
      $html_attribute->removeAttribute('lang');
      $html_attribute->setAttribute('lang', $node_langcode);
    }
  }

```
> 0 votes

---
Tags: i18n-l10n
---


# Question
Title: How to override facets checkbox theme and style checkboxes checked state?
I'm having trouble to style Drupal 9 facets checkbox in checked state. I have tried to override the theme by theme\_preprocess\_checkboxes with no effect.

here is my code :

```
 function mytheme_preprocess_checkboxes($variables) {

  $element = $variables['element'];
  $element['#attributes']['type'] = 'checkbox';
  element_set_attributes($element, array('id', 'name', '#return_value' => 'value'));

  // Unchecked checkbox has #value of integer 0.
  if (!empty($element['#checked'])) {
      $element['#attributes']['checked'] = 'checked';
  }
  _form_set_class($element, array('form-checkbox'));

  return '<input' . drupal_attributes($element['#attributes']) . ' /><span></span>';
}

```

I guess i'm not getting facets checkboxes with it. Any suggestions how do i style facets and override their templates.

I'm using bootstrap 3 subtheme on drupal 9

# Answer
> 1 votes
The checkboxes are created in JS, not PHP, so you won't be able to manipulate them from the backend (see `Drupal.facets.makeCheckbox` in facets/js/checkbox-widget.js for the code).

It does mean you can just use some simple JS yourself, though; for example assuming you need to append an empty span you'd, probably just need to add something like this to a custom behavior:

```
$('.facets-checkbox').after($('<span />'))

```

(that's just a minimal example, you should use `once` or a similar mechanism to make sure it isn't executed multiple times for the same element).

---
Tags: theming, 9
---


# Question
Title: "There have been more than 5 failed login attempts for this account. It is temporarily blocked." and the flood table is empty
When I try to log in as an admin user, I am getting the following error:

> There have been more than 5 failed login attempts for this account. It is temporarily blocked. Try again later or request a new password.

This answer explains that this can usually be cleared up by truncating the flood table in the database.

However, when I checked my flood table in the database with PHPMyAdmin, it was empty.

I did some further troubleshooting:

* I can log in as other users, just not the suspended user.
* I am viewing the correct database; when I registered a new user, I could see the new user's data in the database.

The user in question is an admin user account that I use to log in with for behat tests; the behat tests failed on my cloud site, so I pulled the database into my local dev environment (lando) and am now trying to give myself access to that admin account.

# Answer
> 4 votes
When you have installed Redis the database content for caching, flooding, locking and queuing will be stored in the in-memory database and you have to look there to find this data.

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


# Question
Title: Block doesn't show up in the entity reference UI
I have an Entity Reference field, whose "type of item to reference" is **block**.

I have a View that creates a block called *staff list* but when I edit content that uses that field, I can't get it to present *staff list* as an option?

Why is this block not selectable? Surely all 'blocks' should be reference-able this way?

# Answer
> 1 votes
Your field is referencing block config entities. Those exists only for blocks placed in the block layout. If Views creates a block then this is a derivative of a views block plugin and not yet a configured block. You could place the block in block layout, then it shows up in the entity reference select UI. But this is not a good idea. This will cause an error if you remove the configuration and still have references in content.

So better use a different field type. You can place block plugins directly in node fields. See Display custom module block in page content. Or the View directly in a node field, without using a block display. There are a few modules for this:

https://www.drupal.org/project/eva

https://www.drupal.org/project/viewfield

---
Tags: blocks, 9, views
---


# Question
Title: Page not found when viewing Group entities
I'm using the Group module and I've defined an "Organization" group type.

When I create an entity of that type by going to `/group/add` and hit save, I get Page Not Found for the url `/group/1`.

If I go to the entity list view at `/admin/group` I see my group, and the title is linked to `/group/1`. Clicking on it gives me Page Not Found.

`/group/1/edit` works, as do other urls like `group/1/delete`, but group/1 404s.

What am I missing here and how can I debug this? `/group/{group}` seems to be the canonical link for the Group entity as defined in `group/src/Entity/Group.php`. I'm logged in as admin.

# Answer
> 0 votes
Tracked this down to a route collision with another entity in our codebase that was using the same route.

Debugged by adding devel\_debug calls to RouteProvider.php

---
Tags: 9, group
---


title: Reverse Translation Function?

text:
# Question
Title: Reverse Translation Function?
As you know **t()** function in Drupal is translation function.

**t('base value')** returns translated expression for current language.

I want to know, is there any function in Drupal that takes translated expression as a parameter and returns base value ?

```
$translated = t('base');
$base_value = reverse_translation ($translated)

```

I am searching for **reverse\_translation** function

# Answer
> 2 votes
according to t() documentation you can get translate the string it in any langcode,it is mean you can have reverse translation

my suggestion is

```
t($string,  array(), array('langcode'=>'en'));

```

and as example stack dont let me use persian character(I write in Fenglish but you read it persian :) )

`t('Chetori mehrdad', array(), array('langcode'=>'en'));`

return equal of string ('Chetori mehrdad') in english if you translate it before form English to persian (`How are you mehrdad`), this mean 'Chetori mehrdad\`(persian) =\> 'How are you Mehrdad'(english) :)

I hope this is useful at this time ,sometimes the answers is after you need :(

# Answer
> 0 votes
If someone is looking for version Drupal 8/9, in this case we can use:

```
$locale_string = \Drupal::service('locale.storage')->findTranslation([
    'translation' => 'Ciao',
    'language' => 'it',
]);

```

---
Tags: 7, i18n-l10n
---


# Question
Title: Drupal 7 taxonomy term fields not handling content filters
**Image Resize Filter** doesn't work with taxonomy term description. Resizing works fine in nodes and blocks, but not in views for taxonomy term.

I'm loading term in my view template. And render its description(also tried custom) field.

```
$term = taxonomy_term_load($term_id);
print render($term->description);

```

I've tried to render with field\_get\_items and field\_view\_field.

Then i've figured out that html **content filter doesn't work with taxonomy terms fields** either.

Does anyone know *how to apply content filters to taxonomy term fields*(include description)?

Drupal core 7.5/7.81

Thanks for the replies.

# Answer
> 0 votes
The solution is to use `check_markup` function. So, in my case, it was `print check_markup($current->description, 'filtered_html');` to output textfield with content filters.

---
Tags: 7, views, theming, taxonomy-terms
---


title: HTML in webform labels

text:
# Question
Title: HTML in webform labels
I need to insert HTML markup (spans, classes, h2 tags). However, webform appears to be filtering out all markup from labels. Has anybody succeeded in inserting html markup in labels, and how did you do that?

# Answer
> 1 votes
You won't be able to use HTML markup within the label inputs within the Webform module itself, as it most likely cleans out all HTML markup before displaying to the user to prevent XSS attacks etc.

Most likely you'll need to write a small custom module which implements **hook\_form\_alter**, which will allow you to change the markup used for the labels.

I'm not actually sure if Drupal will allow markup within the **#title** attribute of your form elements, so you might need to use the **#prefix** property instead to add your custom HTML replacement labels.

If this is all Greek to you then you'll probably need to checkout these tutorials:

Creating modules - a tutorial: Drupal 7.x

Hook snippets: hook\_form\_alter

# Answer
> 2 votes
I added the following to the bottom of my settings.php page. I read it somewhere... works like a charm. :)

```
$conf['webform_allowed_tags'] = array('a', 'em', 'strong', 'code', 'img', 'ul', 'li', 'u', 'span style="font-style:italic', 'span' , 'a', 'i', 'italic');

```

# Answer
> 0 votes
the "Options with Markup" module allows HTML formatting of labels for radio button/checkbox.https://www.drupal.org/project/webform\_optionsmarkup

# Answer
> 0 votes
In D8+, you can do this via copying the twig template that generated the `label` markup.

Copy `core/modules/system/templates/form-element-label.html.twig` to your theme and change as needed. Just ensure the markup you add is valid HTML.

In my case, I had to add a `span` if the field was required:

```
 {%
  set classes = [
    title_display == 'after' ? 'option',
    title_display == 'invisible' ? 'visually-hidden',
    required ? 'js-form-required',
    required ? 'form-required',
  ]
%}
{% if title is not empty or required -%}
  {% if required %}
    <label{{ attributes.addClass(classes) }}>{{ title }}<span class="sr-only"> required</label>
  {% else %}
    <label{{ attributes.addClass(classes) }}>{{ title }}</label>
  {% endif %}
{%- endif %}

```

I originally tried modifying the `label` via `hook_form_alter()`, but webforms seem not to spit out the same elements to alter i.e. `$form['FIELD_NAME']['widget'][0]['value']['#title']`.

---
Tags: webforms, theming
---


title: Adding fields to Flag Lists

text:
# Question
Title: Adding fields to Flag Lists
I'm using the Flag Lists module to manage user wish lists. I need to add additional fields to the lists such as "body" I go to `/admin/structure/flags/manage/fl_template/fields` add the required fields, save, rebuild flag lists, flush caches and attempt to edit existing flag lists or create new ones and I still only see the "title template."

# Answer
When configuring flag(s) (using the Flag module), you can indeed attach fields to them. However when doing so, make sure to also be aware about (and do) what is described in Attaching fields to flags, i.e.:

> By default, Flags use the "JavaScript toggle" link-type. While this allows entities to be flagged without reloading the page, users cannot set any field values with the Flag. In order for users to set a Flag's field values, you must use the "Form" link type.
>
> Navigate to `Administration > Structure > Flags` page. Click the Edit link for the Flag. Scroll down to the Display Options box and select the Confirmation Form radio button.

If the above doesn't help (or if you've already configured your flag using a Confirmation Form), then you may want to look at Comment nr 1 in issue nr 2539868, which points to 2 more related issues.
> 0 votes

# Answer
I guess I missed something, I could not add a new field to a flag as suggested above. I'm using **Drupal 9.3** with **Flag 8.x-4.0-beta3** and **Flag List 4.0.0-rc2**

I'm trying to add a new field "**Description**" after "Name". Any reference link or suggestion is appreciated.

Alternative thought, do we have to write a custom module to add a new field on the form, extending the 'Flags' module
> 0 votes

---
Tags: entities, flags
---


# Question
Title: Custom validation constraints multi value paragraphs : how to get weight value
I am validating a multi value paragraph field using constraints.

```
/**
 * Implements hook_entity_bundle_field_info_alter().
 */
function cnfpt_internet_entity_bundle_field_info_alter(&$fields, \Drupal\Core\Entity\EntityTypeInterface $entity_type, $bundle) {
  if ($bundle === 'manifestation') {
    if (isset($fields['field_occurence'])) {
      // Add a validation.
      $fields['field_occurence']->addConstraint('Occurrence', []);
    }
  }
}

```

```
/**
 * Checks the mandatory fields of an occurence and ordere of the occurrences.
 *
 * @Constraint(
 *   id = "Occurrence",
 *   label = @Translation("Champ obligatoire par type d'occurence", context = "Validation"),
 *   type = "item"
 * )
 */
class OccurrenceConstraint extends Constraint {

  // Modalité requise pour occurrence distante.
  public $modaliteRequise = 'Le champ Modalité est requis';

  // Ville requise pour occurrence presentiel.
  public $villeRequise = 'Le champ Ville est requis';

  // Order of occurence
  public $ordreOccurrence = 'Les occurrences doivent être placées dans l\'ordre chronologique';

  // First occurence needs a contact.
  public $premiereOccurrenceContact = 'Un contact est obligatoire pour la première occurence';
}

```

`field_occurence` ist the paragraph field

My validate method starts like

```
 * Validates the Occurrence constraint.
 */
class OccurrenceConstraintValidator extends ConstraintValidator {
  /**
   * {@inheritdoc}
   */
  public function validate($items, Constraint $constraint) {

```

I have to make a validation taking into account the order of the paragraphs. If the paragraph is ordered with drag&drop there is no issue, I can take the delta value of items.

But if the weight is modified manually, I don't see how to get the modified weight value.

Any idea how to get the manually modified weight value?

Thanks Rainer

# Answer
In the meantime i found this tutorial https://philfrilling.com/blog/2018-09/custom-validation-multiple-dependent-entity-fields-drupal-8 that would have solved my problem. Making a restriction on the whole entity instead of the field only gives access to the info I needed.
> 0 votes

---
Tags: forms, 9, paragraphs
---


# Question
Title: Unable to retrieve uploaded file in submit handler
I'm creating a custom form with a file upload field that will have its contents read, processed then sent to an external API. The problem is whenever I upload the file the field for it appears to be empty in the submit handler and I cannot see why.

In this example I'm using it as an unmanaged file as I only need to process it then remove it but I have tried it as a managed file which does upload (I can see it in the directory) and has the file added to the file\_managed database table. I'm not sure where unmanaged file are meant to go to check for their upload.

```
public function buildForm(array $form, FormStateInterface $form_state) {
    $form = [
      '#attributes' => ['enctype' => 'multipart/form-data'],
    ];

    $form['file_upload_details'] = [
      '#markup' => "<strong>" . $this->t('The KML File') . "</strong>",
    ];

    $form['my_file'] = [
      '#type' => 'file',
      '#description' => $this->t('KML format only'),
      '#upload_location' => 'public://my_files/',
      '#upload_validators' => [
        'file_validate_extensions' => ['kml'],
      ],
    ];

    $form_build = parent::buildForm($form, $form_state);

    return $form_build;
  }

```

```
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $messenger = parent::messenger();

var_dump(
  $form_state->getStorage(), // Empty array
  $form_state->getValue('my_file') // Empty string
);
  }

```

# Answer
All what `'#type' => 'file'` form elements do is to provide a bare `<input type="file">` element. You get a prompt to select a file from your machine and on form submit the browser sends a request to your server, server forwards it to PHP, PHP extracts the file from the request, PHP stores it to the server's temp dir and when the script ends it deletes it again. Not much Drupal involved.

If you need to handle the file somehow and be it just the filename you need to take care of it yourself. And that's what `file_save_upload()` is for. It expects the `$form_field_name` as first parameter. And it will return you the file information. When scanning core for `'#type' => 'file'` you will often see this function being used in the form validation handler. Where the return value is being passed back to `$form_state`. For example in `\Drupal\system\Form\ThemeSettingsForm::validateForm()`. Just this time the function is wrapped from `_file_save_upload_from_form()` to allow correct error handling in forms.

> ```
> // Check for a new uploaded logo.
> if (isset($form['logo'])) {
>   $file = _file_save_upload_from_form($form['logo']['settings']['logo_upload'], $form_state, 0);
>   if ($file) {
>     // Put the temporary file in form_values so we can save it on submit.
>     $form_state->setValue('logo_upload', $file);
>   }
> }
>
> ```
> 2 votes

# Answer
I have a custom module to import CSV. This works for me.

```
$form['#attributes'] = [
  'enctype' => 'multipart/form-data',
  'class' => ['csv-import-form', 'mb-50'],
];

$form['csv_file'] = [
  '#type' => 'file',
  '#title' => t('CSV File'),
  '#description' => $this->t('Upload file here.'),
  '#element_validate' => ['::csv_import_validate_file_upload'],
];

```

---

```
public static function csv_import_validate_file_upload(&$element, FormStateInterface $form_state, &$complete_form) {

$validators = [
  'file_validate_extensions' => ['csv CSV'],
];

if ($file = file_save_upload('csv_file', $validators, FALSE, 0, \Drupal\Core\File\FileSystemInterface::EXISTS_REPLACE)) {

  $csv_dir          = 'public://my_files/';
  $directory_exists = \Drupal::service('file_system')->prepareDirectory($csv_dir);

  if(!$directory_exists){
    \Drupal::service('file_system')->prepareDirectory($csv_dir, \Drupal\Core\File\FileSystemInterface::CREATE_DIRECTORY);
  }

  if ($directory_exists) {
    $destination = $csv_dir . '/' . $file->getFilename();

    if (file_copy($file, $destination, \Drupal\Core\File\FileSystemInterface::EXISTS_REPLACE)) {
      $form_state->setValue('csv_file', $destination);
    }
    else {
      $form_state->setErrorByName('csv_file', t('Unable to copy upload file to @dest', ['@dest' => $destination]));
    }
  }
}}

public function submitForm(array &$form, FormStateInterface $form_state) {
    $csv_uri = $form_state->getValue('csv_upload', FALSE);

if ($csv_uri) {
  $csv_data = processCsv($csv_uri);

  if (count($csv_data)) {
    $batch = $this->generateBatchImport($csv_data);
    batch_set($batch);

    $form_state->setRedirect('view.users.page_1');
  }
}}

```
> 1 votes

# Answer
I'm using Drupal 9.3.3
I came up with this same problem, while using custom form in a Block. Check this.

```
/**
 * Provides an 'CareerJobs' List Block
 * @Block (
 *   id = "careerjobs_block",
 *   admin_label=@Translation("CareerJobs Block")
 *   )
 */
class CareerjobsBlock extends BlockBase {

  /**
   * @inheritDoc
   */
  public function build() {
    // return \Drupal::formBuilder()->getForm('Drupal\careerjobs\Form\CareerjobsForm');
    $node = \Drupal::request()->attributes->get('node');
    return [\Drupal::formBuilder()->getForm('Drupal\careerjobs\Form\CareerjobsForm', $node, 'careerjobs_block')];
  }
}

```

For handling the file.

```
class CareerjobsForm extends FormBase {

  protected static array $file_ext = ['pdf doc docx'];

  protected static int $file_size = 2048000000;

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state);
    ...
    // buildForm
    $form['resume_upload'] = [
      '#title' => t('Upload your Resume file'),
      '#type' => 'file',
      '#description' => t('Allowed extensions: pdf doc docx. <br> Filesize <= 2MB'),
      '#element_validate' => ['::fz_import_validate_file_upload'],
    ];
    ...
    return $form;
  }

  // You can do this in submitForm method also.
  public static function fz_import_validate_file_upload(&$element, FormStateInterface $form_state, &$complete_form) {

    $validators = [
      'file_validate_extensions' => self::$file_ext,
      'file_validate_size' => [self::$file_size],
    ];

    if ($file = file_save_upload('resume_upload', $validators, FALSE, 0, \Drupal\Core\File\FileSystemInterface::EXISTS_REPLACE)) {

      $csv_dir = 'public://careerjobs/resume/x';
      $directory_exists = \Drupal::service('file_system')
        ->prepareDirectory($csv_dir);

      if (!$directory_exists) {
        \Drupal::service('file_system')
          ->prepareDirectory($csv_dir, \Drupal\Core\File\FileSystemInterface::CREATE_DIRECTORY);
      }

      if ($directory_exists) {
        $destination = $csv_dir . '/' . $file->getFilename();

        if (\Drupal::service('file.repository')->move($file, $destination, \Drupal\Core\File\FileSystemInterface::EXISTS_REPLACE)) {
          $form_state->setValue('resume_upload', $destination);
        }
        else {
          $form_state->setErrorByName('resume_upload', t('Unable to copy upload file to @dest', ['@dest' => $destination]));
        }
      }
    }
  }
}

```

My form is too big to paste here. Only the required part is here.
> 1 votes

---
Tags: 8, forms, files
---


# Question
Title: How to extend core block class SystemBrandingBlock
Please advice how we can extend the core block class Drupal\system\Plugin\Block\SystemBrandingBlock to add custom method.

In my case, I want to include function buildToArray() to get the block data in array format rather than rendered array.

Existing build() method:

```
public function build() {
    $build = [];
    $site_config = $this->configFactory->get('system.site');

    $build['site_logo'] = [
      '#theme' => 'image',
      '#uri' => theme_get_setting('logo.url'),
      '#alt' => $this->t('Home'),
      '#access' => $this->configuration['use_site_logo'],
    ];

    $build['site_name'] = [
      '#markup' => $site_config->get('name'),
      '#access' => $this->configuration['use_site_name'],
    ];

    $build['site_slogan'] = [
      '#markup' => $site_config->get('slogan'),
      '#access' => $this->configuration['use_site_slogan'],
    ];

    return $build;
}

```

Required method to add:

```
public function buildToArray() {
    $site_config = $this->configFactory->get('system.site');

    return [
      'site_logo' => theme_get_setting('logo.url'),
      'site_name' => $site_config->get('name'),
      'site_slogan' => $this->configuration['use_site_slogan'],
    ];
}

```

# Answer
> 0 votes
If you are using Drupal 9 and don't want to create a block duplication here is the simplest way to override a block class: To override Block class you can use hook\_block\_alter like this.

```
/**
 * Implements hook_block_alter().
 */
function [MODULE]_block_alter(&$definitions) {
  foreach ($definitions as $id => $definition) {
    // Check on your plugin Id here.
    if ($id === 'system_branding_block') {
      // Set your new class here.
      $definitions[$id]['class'] = 'Drupal\MODULE\Plugin\Block\SystemBrandingBlockAlter';
    }
  }
}

```

And then create your new class **SystemBrandingBlockAlter** in ***MODULE/src/Plugin/Block*** like this:

```
<?php

namespace Drupal\MODULE\Plugin\Block;

use Drupal\system\Plugin\Block\SystemBrandingBlock;

class  SystemBrandingBlockAlter extends SystemBrandingBlock {

  public function build() {
    $site_config = $this->configFactory->get('system.site');
    return [
      'site_logo'   => theme_get_setting('logo.url'),
      'site_name'   => $site_config->get('name'),
      'site_slogan' => $this->configuration['use_site_slogan'],
    ];
  }

}

```

Now the responsible class for your block is ***Drupal\MODULE\Plugin\Block\SystemBrandingBlockAlter*** and not ***Drupal\system\Plugin\Block\SystemBrandingBlock***

# Answer
> 0 votes
## Extending a Block

To extend the block, you'll define a new block, as described in the following tutorial, except that you would extend the class `Drupal\system\Plugin\Block\SystemBrandingBlock`, instead of the class `Drupal\Core\Block\BlockBase`. You can then add your custom method to the newly defined block.

https://www.valuebound.com/resources/blog/drupal-8-how-to-create-a-custom-block-programatically

## Alternative consideration

If what you need from `SystemBrandingBlock` is just the *data*, and not necessarily an actual block, I would advise to instead define a service that provides the data from your `buildToArray()` method.

## Comment Responses

It is true that this will create a new block type, in addition to the `SystemBrandingBlock`. Blocks are managed, organized and retrieved by the Block Plugin Manager. You could write a decorator for this service and override the `getDefinitions()` method in order to prevent the original `SystemBrandingBlock` from being available as a plugin definition, achieving the effect of replacing the original `SystemBrandingBlock` with your new block.

It still sounds to me like a service is what you need. By examining the code in the original `SystemBrandingBlock` class definition, we see that `SystemBrandingBlock` only relies on one service, `config.factory`. So your service only needs to inject the `config.factory` service in order to retrieve the information that you need for the `buildToArray()` method (which might be better renamed as something like `getBrandingInfo()`). Defining a service in this way means that you won't need to worry about implementing or deploying a block (which doesn't seem to be what you need, anyway), or needing to write a service decorator.

Bear in mind, also, that the SystemBrandingBlock is not the original source of the data, but rather a plugin for displaying those data in a rendered format. The block is completely irrelevant if all you want are the data.

Finally, speaking in broader terms, Drupal is organized largely around plugins, services and dependency injection, and becoming familiar with these concepts will give you the tools to systematically solve many problems in Drupal.

---
Tags: 8, blocks
---


title: Restful permission is required

text:
# Question
Title: Restful permission is required
I've created a @RestResource plugin to provide a REST endpoint to get some data, but when I try a GET from Postman it shows this error:

> { "message": "The 'restful get ez\_share\_document\_resource' permission is required." }

I thought it was because I need to add something else, so I decided to enable the Watchdog database log REST resource to prove it, but I got the same error:

> "message": "The 'restful get dblog' permission is required."

Rest module has set bc\_entity\_resource\_permissions as false.

This is the annotation of the plugin.

```
/**
 * Provides a resource to get view modes by entity and bundle.
 *
 * @RestResource(
 *   id = "ez_share_document_resource",
 *   label = @Translation("Ez share document resource"),
 *   uri_paths = {
 *     "canonical" = "/ezshare/{ezshare_id}"
 *   }
 * )
 */
class EzShareDocumentResource extends ResourceBase {

```

And this is my get method:

```
public function get($ezshare_id = NULL) {
    if ($ezshare_id) {
      $record = ['It Works!!'];
      if (!empty($record)) {
        return new ResourceResponse($record, 200);
      }

      throw new NotFoundHttpException($this->t('EzShare doc with ID @id was not found', ['@id' => $ezshare_id]));
    }

    throw new BadRequestHttpException($this->t('No EzShare doc ID was provided'));
  }

```

Drupal core is recently updated to 8.8.1.

# Answer
Finally, I was able to solve this issue adding the method *permission* to the RestResource plugin like so:

```
public function permissions() {
  return [];
}

```
> 6 votes

# Answer
The default permissions() method creates a permission per method

In ResourceBase

```
/**
* Implements ResourceInterface::permissions().
*
* Every plugin operation method gets its own user permission. Example:
* "restful delete entity:node" with the title "Access DELETE on Node
* resource".
*/

```

Shown in *admin/people/permissions*

Everything else being equal anonymous can be given access (or a specific role).

Clearing permissions doesn't open access.

Check the REST configuration. Either via configuration synchronisation or REST UI. Install the Rest UI module and check that an authentication provider is installed (OP Basic Auth). The permissions can be configured from the Rest UI interface

Some authentication methods also require access. Check in the network monitor in the browser. With JWT for example, a request for an expired token is required first. If this is denied, or fails it is a problem with the authentication provider.
> 1 votes

---
Tags: plugins
---


# Question
Title: Resetting/reverting a custom module's update 'N value'
In my custom module's install file I have a `hook_update_N` function. Let's say it's `mymodule_update_7100`. However, I've noticed that I've done it wrong and I want to change a line of code within this function. Seeing as I've already run `updb`/`update.php` the changes won't be picked up and I'd have to rename it to either `mymodule_update_7101` or create a new function after it with that name. I'd really rather not have to do this, so I was wondering if there's a variable that tells Drupal exactly what "version number" a module is currently at and whether I can reset it to trick it into allowing me to run the update script again.

The actual effect the function has had on the database isn't important because it's just generating a taxonomy term that I can easily delete through the front-end afterwards.

# Answer
> 18 votes
The `schema_version` column in the `system` table contains the version of the last successful update. Manipulate that value and you can re-test your update.

The `name` column is the machine name of the module, same as the info file is named.

This query will do the trick for you.

```
UPDATE system SET schema_version = XXXX WHERE name = 'name_of_module';

```

# Answer
> 2 votes
Drupal 7 core's install.inc has the function `drupal_set_installed_schema_version($module, $version)`

# Answer
> 1 votes
On drupal 8 it's in the table `key_value` under `value` where `name` is the name of your module.

# Answer
> 1 votes
For Drupal 9 UpdateHookRegistry service (*update.update\_hook\_registry*) replaced functions in schema.inc according to New UpdateHookRegistry replaces functions in schema.inc

so now instead of `drupal_set_installed_schema_version($module, $version)` you can use `\Drupal::service('update.update_hook_registry')->setInstalledVersion($module, $version)`

Example using Drush:

```
drush eval '\Drupal::service("update.update_hook_registry")->setInstalledVersion("MODULE", "930N");

```

# Answer
> 0 votes
Following on from the comment by @wranvaud for Ddrupal 8, the actual statement/command is `db_update('key_value')->fields(array('value' => serialize(nnn)))->condition('collection', 'system.schema', '=')->condition('name', 'your_module', '=')->execute();` where nnnn is the schema version you want to revert to. The important bit is `serialize` because the value is a blob/binary field. This can be executed in a Devel module php form

---
Tags: updating
---


title: Dynamic language links from menu?

text:
# Question
Title: Dynamic language links from menu?
I am trying to find a way to do the following:

* Add languages to Drupal 9 menu items
* Translate content/menu links
* Provide (from the Main Navigation) a list of languages *the current page is translated in*

I was able to complete the first two, but I cannot see how to get a menu to list links that output the available language options for the current entity. I see that there is a Language Switcher block from core, but is there a way to make this appear baked into a Drupal menu itself?

# Answer
You put the static infos in \*.links.menu.yml where you also define dynamic menu link plugins, which provide the infos you can't put in a static yml. And the deriver to produce a plugin for each language. The local task example was just an example for the translation stuff.

A working static example:

*mymodule.links.menu.yml*

```
mymodule.language.top:
  title: 'EN'
  menu_name: main
  route_name: '<none>'
  expanded: true
  # Plugin class to override the title dynamically:
  # class: Drupal\mymodule\Plugin\Menu\TranslatedNodeTop
mymodule.language.item:
  title: 'Node 8 spanish'
  parent: mymodule.language.top
  route_name: entity.node.canonical
  route_parameters: { node: '8' }
  menu_name: main
  options:
    attributes:
      class:
        - foo-class
        - bar-class
  # deriver for installed languages
  deriver: Drupal\mymodule\Plugin\Derivative\TranslatedNodeTabDeriver
  # Plugin class extending MenuLinkDefault overriding static properties dynamically,
  # the route parameter from the current route match, the language from the deriver
  # the title from both and link attributes added for the current language:
  # class: Drupal\mymodule\Plugin\Menu\TranslatedNodeItem

```

You need to add the two dynamic plugins extending MenuLinkDefault. I've recycled the TranslatedNodeTabDeriver from How to get links of translated node edit page in the secondary tabs.
> 0 votes

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


# Question
Title: Change a node's type/bundle keep the old type/bundle in field tables
I need to change the bundle/type of some nodes. I tried https://www.drupal.org/project/convert\_bundles but there was no way to select just a few nodes and change the bundle/type so I tried the very simple way:

```
  $node = Node::load(123);
  $node->set('type', 'new_type_name');
  $node->save();

```

This seems to work: the content type of the node changed. But when I look at the field's database tables there is still the old type/bundle name in the column "bundle" for each field of this node. This only changes when I actually change the field in the node edit form and save it.

My question: does somebody know if there are any sideeffects when there are fields connected to a node where in the field's table is the wrong bundle name stored?

# Answer
As commented by @johnSmith, purging is the problem here, but there are two different purging processes. The first one is triggered when the field storage is removed and the entire table is marked as deleted and purged in cron runs, this should still work. The second one is triggered when a field is removed only from a bundle. Then the affected field items are marked as deleted and purged. This doesn't work any longer. But even if this doesn't bother you and you don't notice other side effects, I still would recommend to update every field table and leave the entity tables in a consistent state as described in the latest comment.
> 0 votes

---
Tags: database, entities
---


# Question
Title: How can make a string used by a view translatable?
I have a *Events* view that is added from the Fullcalendar View module. Is there a way to translate specific strings used from that view?

# Answer
In the Full calendar view dispaly, in "Format" section, there is "Settings" link. The modal window will open and you will see "Style options". Under "Display" accordion, there is setting called "Default Language" where you can select default language.

Also check if other translations settings are set correctly.
> 0 votes

---
Tags: views, i18n-l10n
---


# Question
Title: Where did my commerce token go after an update to 7.87
My Drupal 7 commerce setup sends out a couple of emails after an order is placed. It uses this token:

```
[commerce-order:commerce-customer-shipping:commerce_customer_address]

```

After updating to Drupal 7.87 (from 7.82), that token started going out as is, not being evaluated.

How do I fix this issue?

# Answer
In case anyone else has something similar, here's my solution and debugging methodology:

1. I made a copy of my site and edited the rules governing the checkout to send me all the emails (I could have used mailhog, but this was easier).
2. I used the 'simulate checkout completion' link at the top of a sample order after editing it to use my email address. A++ to whoever invented that feature!
3. I used trial and error to see what happens with different tokens that seemed most likely.

The counter-intuitive solution was:

```
[commerce_order:commerce_customer_shipping]

```

Note that none of the combinations that used hyphens instead of underscores worked.

Also note that the hyphen vs underscore issue isn't universal - some of the hyphen ones work and some don't.

And I have no clue why or how this was related to a Drupal update - it seems like that was the only thing that triggered the change.
> 0 votes

---
Tags: 7, commerce
---


# Question
Title: How does one add a Total(s) row to Views results?
After doing some research, it seems like the best way to get a Total(s) row added to a Views table is via the Views Aggregator Plus module. (Is there an easier/better way?)

As can be seen below, I'm trying to list a bunch of nodes grouped by the first column (the taxonomy term "Type"), with the second column containing the number of each.

I'd like to add an additional row to the bottom:

> Total | 6

...but no matter what I try, the additional row doesn't show up in spite of what the module documentation, various videos, and blog posts are telling me.

In the view Format, I'm using "Table with aggregation options", and the settings are as can be seen here:

Under Column Aggregation, I should be able to check "Apply column function" and select Sum (I think), but this has no effect on the live preview. I tried this on both fields (and even both together), and it made no difference.

I'd like to make the Total row part of the table, rather than a hacky solution where I calculate it in the view header or footer. How can this be done? What am I missing?

# Answer
> 0 votes
> I'd like to make the Total row part of the table, rather than a hacky solution where I calculate it in the view header or footer. How can this be done?

I've never used that module, but alternatively, you could do the template file solution.

Since you want this to work in the View's preview, which uses core's admin theme and since you should never hack core, this cannot be solved via theme. Therefore, must be solved via custom module.

Example:

* View ID: content
* View Display ID: page\_1

/mymodule/**mymodule.module**

```
/*
 * Implements template_preprocess_views_view_table()
 */
function mymodule_preprocess_views_view_table(&$variables) {
  $view = $variables['view'];
  if ($view->id() == 'content' && $view->current_display == 'page_1') {
    $variables['total_rows'] = $view->total_rows; // pass custom var to template
  }
}

/*
 * Implements hook_theme()
 */
function mymodule_theme() {
  return array(
    'views_view_table__content__page_1' => [
      'template' => 'views-view-table--content--page-1',
      'base hook' => 'view',
    ],
  );
}

```

/mymodule/templates/**views-view-table--content--page-1.html.twig**

Copy the code of views-view-table.html.twig and paste into this file and just change the last 3 lines to:

```
  {% endfor %}
  <tr>
    <td>{{ 'Total'|t ~ ' | ' ~ total_rows }}</td>
  </tr>
  </tbody>
</table>

```

# Answer
> 0 votes
For "Content: type" select only "Group and compress" as Group aggregation function. For Content: title" - leave it as it is for Group aggregation, click on "Apply column function" in "Column aggregation" next to it, select "Sum" in the appearing dropdown menu.

---
Tags: views, 8
---


title: Alter views results in a hook

text:
# Question
Title: Alter views results in a hook
When I use contextual filters in a view, I can select an option to display a summary when the argument is not present. If I do it, it shows a list of node IDs instead of titles. For example, I get the following output, where the first number is the node ID, and the second number is the count of nodes.

* 1256 (12)
* 4323 (723)
* 5643 (34)

I want is to rewrite the output and replace the node ID with its title. `ViewExecutable` has a `$args` property I can check to know when the argument is not present.

How could I achieve this in a hook? In Drupal 7 I could use `hook_views_post_execute()`. I modified `$view->result` and changed it on my own.

I tried to do the same with Drupal 8 and the same hook, but `hook_views_pre_render()` gets a `ViewExecutable` object, and I don't know how to change it. I used the following code.

```
function MYMODULE_views_pre_render(ViewExecutable $view) {
  if ($view->id() == 'myidoftheview') {
    $results = $view->result;
    foreach ($results as $result) {
      \Drupal::logger('myview')->notice('<pre>'.print_r($result,TRUE).'</pre>');
      // What code should I write here?
    }
  }
}

```

# Answer
> 5 votes
I was able to alter results just setting the view result property within `hook_views_pre_render`. My code looks something like:

```
$results = $view->result;
$filteredResults = [];

foreach ($results as $result) {
  if ($result->_entity->field_somefield->value === 'somevalue') {
    $filteredResults[] = $result;
  }
}

$view->result = $filteredResults;
$view->total_rows = count($filteredResults);

```

# Answer
> 1 votes
View hooks like `hook_views_pre_render()` should be placed in an execution.inc file within the module directory: `mymodule.views_execusion.inc`

The execution order of View hooks is as follows:

1. hook\_views\_pre\_view
2. hook\_views\_pre\_build
3. hook\_views\_post\_build
4. hook\_views\_pre\_execute
5. hook\_views\_post\_execute
6. hook\_views\_pre\_render
7. hook\_views\_post\_render

Read what these hooks do here

The following is a good example for Drupal 8.x|9.x. Your goal is to create a new result set of entities and set it to `$view->result`. It is important to set the index property so the results will render properly.

Slightly altered from @rosemarystanley

```
/**
 * Implements hook_views_pre_render().
 */
function HOOK_views_pre_render(ViewExecutable $view) {

  $results = $view->result;
  $filteredResults = [];

  foreach ($results as $result) {
    if ($result->_entity->field_name->value === 'fieldValue') {
      $filteredResults[] = $result;
    }
  }

  // Important to set index values for view results rendering
  foreach ($filteredResults as $key => $row) {
    $row->index = $key;
  }

  $view->result = $filteredResults;
  $view->total_rows = count($filteredResults);
}

```

# Answer
> 0 votes
It depends on what your result stores. It can be like entity with relation or just field:

1) `$result->_entity->set('field_Name', 'xxxxxxxxxxx');`

2) `$value->node__field_Name = 'xxxxxxxxxxx';`

---
Tags: views, 8, hooks
---


title: How do I find services?

text:
# Question
Title: How do I find services?
What is the best way to find right service for dependency injection? Googling is not efficient yet. For example I spent quite long time figuring out that if I need current request passed to constructor by DI I have too use:

```
$container->get('request_stack')->getCurrentRequest()
```

Full code example:

```
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
        $configuration,
        $plugin_id,
        $plugin_definition,
        $container->getParameter('serializer.formats'),
        $container->get('logger.factory')->get('job_market'),
        $container->get('current_user'),
        $container->get('request_stack')->getCurrentRequest()
    );
}

```

And I've found above example in drupal class Documentation

Before that I've just found this services list but there is no description, no examples, nothing. Just a list with possibility to search.

How do you search for right service provider?

# Answer
> 2 votes
A better way to accomplish this is to use the Drupal Console's `container:debug` command. This command outputs a list of Drupal service ID's and its corresponding namespace & class.

```
$drupal container:debug

 Service ID                 Class Name
 class_loader               Symfony\Component\ClassLoader\ApcClassLoader
 kernel                     Drupal\Core\DrupalKernel
 service_container          Drupal\Core\DependencyInjection\Container
 cache_context.ip           Drupal\Core\Cache\Context\IpCacheContext
 cache_context.headers      Drupal\Core\Cache\Context\HeadersCacheContext
 cache_context.cookies      Drupal\Core\Cache\Context\CookiesCacheContext
 ...

```

This command can be employed along with grep to search for a specific class name or service ID. For example: `drupal container:debug | ag 'DatabaseStorage'` to find a DatabaseStorage class.

Also of interest is the PhpStorm / IntelliJ Drupal Symfony Bridge plugin if you use PHPStorm.

# Answer
> 0 votes
If you are using drush and the devel module, you can also use 'drush devel:services'.

For example:

```
# drush dcs datab
- cache.backend.database
- database
- database.replica
- database.replica_kill_switch
- database_driver_uninstall_validator
- drupal.proxy_original_service.database_driver_uninstall_validator
- keyvalue.database
- keyvalue.expirable.database
- queue.database

```

It's not as cool as the console command because it doesn't give you the class name.

More ways to do it are also on this later question Get the list of available services

---
Tags: 8, dependency-injection
---


# Question
Title: Custom constraints validation of multi value paragraphs: highlighting missing field
I am using constraint for the validation my multi value paragraph field.

I can correctly implement the different validation rules but I haven't found out how to highlight only the erroneous field(s).

Here is my violation declaration

```
      $this->context
       ->buildViolation($constraint->modaliteRequise)
       ->atPath((string) $delta . 'subform.field_modalite.0')
       ->addViolation();

```

This highlights all fields of all paragraphs.

How can I only highlight the missing field in the affected paragraph?

Thanks Rainer

# Answer
> 0 votes
Ok, I finally found it thanks to https://www.drupal.org/project/paragraphs/issues/2994660#comment-12740155

With following path I can correctly target the field

```
->atPath((string) $delta . '.subform.field_modalite.widget')

```

If you want to target a paragraph field from inside another paragraph field you need a path as follows

```
->atPath((string) '0.subform.TARGET_FIELD.widget.0.subform')

```

---
Tags: forms, 9, paragraphs
---


title: How to place facet blocks

text:
# Question
Title: How to place facet blocks
I got Search API and Facets configured, built a View Source, and connected the Facet to that source. Now I'm stuck with how to present that widget!

With D7 Facets, it configured Blocks that I could place. That isn't the case with D9. Anyone have a helpful hint?

# Answer
Nothing special really. You need to set up each facet individually so that it will become available as a block. Go to `admin/config/search/facets` and click on "Add facet".

The available facet can then be found in the block managements "Place block" dialog by searching for the name of the facet.
> 1 votes

---
Tags: blocks, search, 9
---


# Question
Title: Storing data / session for anonymous user
I am working on a shop, and for the cart, i need to store items before payment.

```
  $tempstore = \Drupal::service('user.private_tempstore')->get('boutique');
  $tempstore->set('poids', $form_state->getValue('poids'));

```

I take a look on the user service for :

> pivate\_tempstore and shared\_tempstore

But that work only for authenticates users.

What can I use for store data ? $\_SESSION ? or Drupal 8 has a service for that ?

# Answer
In Drupal 8 the session variables can be accessed off the request:

```
$session = \Drupal::request()->getSession();

```

If you want to set something in the session, you can do the following:

```
$profile = 'Person';
$session->set('profile', $profile);

```

Or to retrieve a session variable:

```
$details = $session->get('profile');

```
> 15 votes

# Answer
Late answering, but it's worth mentioning that you *can* use private tempstore for anonymous users, as long as the tempstore has access to an active session. To do so, you need to inject your class with services for the temp store, session, and current user, like so:

```
public function __construct(PrivateTempStoreFactory $temp_store_factory, SessionManagerInterface $session_manager, AccountInterface $current_user) {
    $this->tempStoreFactory = $temp_store_factory;
    $this->sessionManager = $session_manager;
    $this->currentUser = $current_user;

    $this->store = $this->tempStoreFactory->get('myclass.storename');
}

public static function create(ContainerInterface $container) {
    return new static(
        $container->get('user.private_tempstore'),
        $container->get('session_manager'),
        $container->get('current_user')
    );
}

```

Then you just need to ensure you start the session manager if the user is anonymous, before you need to put anything in the temp store:

```
if ($this->currentUser->isAnonymous() && !isset($_SESSION['session_started'])) {
    $_SESSION['session_started'] = true;
    $this->sessionManager->start();
}

```

You might find this approach preferable because it means that you can use a single system for temporary storage, regardless of whether a user is logged in.

(My code examples are lifted more-or-less verbatim from this excellent tutorial on building multi-step forms.)
> 22 votes

# Answer
A session can be anonymous (uid=0). You can simply use $\_SESSION and drupal will take care of this.

Store session data:

```
$_SESSION['mymodule']['variablename'] = $tempdata;

```

Get session data:

```
$tempdata = $_SESSION['mymodule']['variablename'];

```

---

**Update 1: Session Object**

While there is still work going on in D8 core, see this issue Convert uses of $\_SESSION to symfony session retrieved from the request, you can use the session object in the request to store session data. But don't mix it, data you store with one of these methods is not available in the other. See this answer for more details Drupal 8 and Session Management:

```
class MymoduleSessionCounter {
  function increment(Request $request) {
    $session = $request->getSession();
    $value = $session->get('mymodule_count', 0);
    $session->set('mymodule_count', $value + 1);

    return $value;
  }
}

```

**Update 2: TempStore**

The TempStore seems to be very popular in D8. But it's too complicated to store some values like in this question. It is intended for big chunks of data like for example preview data or unsaved Views. Here are the official change records:

Access session data through the Request object

TempStore API added for persistent, expirable storage of non-cache data
> 6 votes

# Answer
The `$this->sessionManager->start();` was not working anymore for me because of the last update. I changed it in to `$this->sessionManager->regenerate();`
> 3 votes

# Answer
I wrote this module to solve this problem in a generic way. https://www.drupal.org/project/anonymoussession

use this code before using the session, and you application works for both known and unknown visitors.

```
$anonymousSession = \Drupal::service('anonymoussession');
$anonymousSession->apply();

$_SESSION[....

```
> 2 votes

# Answer
Since the Saving to the private tempstore doesn't start a session for anonymous users has been resolved in Drupal core, the private tempstore now works for anonymous users.
> 0 votes

---
Tags: 8, sessions, files
---


# Question
Title: How can i programmatically get the value of a views exposed filter after the user submits the form?
I've searched and cant find an answer to this specific question.

If I have a view and an exposed filter for that view in a block, when the user clicks submit on the exposed filter form, how can I get the values of the exposed filters in order to use the value elsewhere for a different purpose? For example saving the value of one of the exposed filters into private temp store for use later.

What hook can i use that is called when the user clicks submit on the exposed filter form? The only information I can find is regarding hooks that are called when the view is being built.

Or am i approcahing this wrong and should I be looking into the form submit function for the exposed filters form?

# Answer
> 3 votes
You want to add a submit handler to your exposed form

```
function HOOK_form_views_exposed_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

    array_unshift($form['#submit'], '_my_exposed_form_submit');
}

function _my_exposed_form_submit(&$form,
   \Drupal\Core\Form\FormStateInterface $form_state) {

   $values = $form_state->getValues();

```

---
Tags: views
---


# Question
Title: Specify the view mode when the node is displayed on modal window (ajax)
Is possible to specify the view mode using the default modal Ajax functionality?

I'm using this and it works, but I need to theme the node in a different way inside the modal

```
<a class="use-ajax" data-dialog-type="modal" href="/node/NID">Open Modal</a>

```

# Answer
> 1 votes
The way you are doing it will always show the full view mode, as you are linking to the canonical entity page - which is the page to see the full view mode. If you want to show a different view mode, then I would suggest creating a custom route (or path if you're using D7), and in the callback, generate the output programmatically with the view mode you want. I'd probably use the following for the path:

```
node/[NID]/teaser

```

And in there I would output the teaser view mode.

# Answer
> 1 votes
In Drupal 8/9, you can do this quickly by creating a routing entry.

For example, if i have a content type Program and i wish to load it with the view mode Dialog, i will create a `program.routing.yml` in my custom module `program` like this :

```
program.view:
  path: '/program/{node}'
  defaults:
    _entity_view: 'node.dialog'
  requirements:
    _permission: 'access content'

```

Then in my template, i will add this link :

```
<a class="use-ajax" data-dialog-type="modal" href="/program/[nid]">Open Modal</a>

```

---
Tags: 8, ajax
---


# Question
Title: store user entered mail id to separate table
Have a requirement to develop drupal 9 custom module to get the mail id from the user registration form and store it separate table. I tried the hook\_user\_presave function to get the mail id but was not able to get it. Hereby sharing the code

```
function save_mail_user_presave(UserInterface $user)
 {

     try{
                $conn = Database::getConnection();
                $fields["mail"] = $user->get('mail')->value;
            $conn->insert('save_email')
                           ->fields($fields)->execute();
                  \Drupal::messenger()->addMessage($this->t(' Thank you !! Your>

        } catch(Exception $ex){
                \Drupal::logger('save_email')->error($ex->getMessage());
        }

}

```

Anybody helps me figure out the problem

# Answer
Drupal 9 already stores the email address upon registration in the `init` column of the `users_field_data` table. This is the "email address from the user registration form"; it is different from the user's account email address, which is stored in the `mail` column of the same table.

So, there's no need for a custom module for this; you can use the `column` that Drupal already provides.
> 0 votes

---
Tags: users, 9
---


# Question
Title: Iterate over bundles to create entity bundle class for each
I'm curious if anyone has a way to produce an entity bundle class for several bundles at once. For example:

```
function MYMODULE_entity_bundle_info_alter(&$bundles) {

  // My array of different content types.
  $target_bundles = ['page', 'article'];

  // Iterate over the content types.
  foreach($target_bundle as $bundle) {

    $Bundle = ucfirst($bundle); // page to Page
    $bundles['node'][$bundle]['class'] = $Bundle::class; // Page::class

  }
}

```

The problem I'm running into is the `$Bundle::class` part doesn't work. Is this possible?

# Answer
After some poking around, I realized the error I was getting:
**Fatal error:** Cannot use ::class with dynamic class name

Long story short, my problem was I didn't understand that `::class` simply returns the full namespace of the class itself. Once I added in the full namespace to my `$Bundle` variable, everything worked nicely. The code below provides an efficient way to assign multiple entity bundles to their respective classes.

```
function mymodule_entity_bundle_info_alter(&$bundles) {

  // Array of content type machine names.
  $target_bundles = ['page', 'article'];

  // Iterate over the content types.
  foreach($target_bundle as $bundle) {

    // Turn 'page' to 'Page' and add the full namespace.
    $Bundle = 'Drupal\mymodule\Entity\' . ucfirst($bundle);

    $bundles['node'][$bundle]['class'] = $Bundle;
  }
}

```
> 1 votes

---
Tags: entities, 9
---


# Question
Title: Does the built-in PHP web server have disadvantages over other local development alternatives?
When watching Install Drupal for Local Development, I leant that Drupal 8 and Drupal 9 come with a built-in PHP web server that can be set up quickly by cloning the core and running `php -S localhost:8000`. However, the official Local Development Guide does not mention this and instead advises to use DDEV for local development.

If the built-in PHP web server is so quick to set up, why should I be using DDEV or any other alternatives for local development (e.g., WAMP/MAMP/XAMPP, Docker, Acquia's Cloud IDEs, etc.)? Do these alternatives have features that the built-in PHP web server does not, for example?

# Answer
Drupal 8 and 9 do **not** come with a built-in webserver.

`php -S` is **PHP**'s bare bones webserver for limited testing. Read more in the PHP manual.

The PHP built-in server is not good for local development because you want your local development environment to match your production/live environment as much as possible, so it's good to run the same server locally that you use in production.

DDEV, lando, and other docker-based local dev solutions will let you closely simulate your actual webserver and catch problems before you push your code to the production server.

Also, the PHP built-in server has this specific problem:

> The web server runs only one single-threaded process, so PHP applications will stall if a request is blocked.

Basically all webservers the world over are multithreaded, but the PHP built-in server is so bare bones it will choke if you do anything complicated.

So I wouldn't even try to use the built-in PHP server for anything except the most basic of tests.
> 8 votes

# Answer
App like DDEV do more than just serve a website. They can also manage the database, and cache services or add helpful commands to quickly backup data.

But by using Docker, they handle these in isolation. I can run PHP 8.0 on my main PC, spin up a dev project using PHP 7.4/MySQL, test a different project in PHP 8.1/Postgres, and fix an urgent support request for a legacy PHP 7.2 app.

Juggling multiple PHP versions, their extensions, and support services becomes as easy as "DDEV start" / "DDEV stop"
> 3 votes

---
Tags: 9
---


# Question
Title: Return two values from views exposed filter - filtered value and a default value
Is it possible to return two values when user chooses a value from a defined list? The values I wish to return are the value that a user chose AND a default value if it exists.

I have a taxonomy list of values (example: 10%, 20%, 25%, 100%, Any%). This list is exposed to the user as a dropdown filter on form.

I have a content type with an entity reference field referring to these values. Some or all of these values may be referenced in this field.

If the user chooses, for example 10% then the returned results should show products that have 10% set but I also want it to return Any%, if that is referenced in the product. So Any% should be shown alongside the product always, if it is referenced on that product.

Is this possible within views UI or do I need a query alter?

Default view before a choice is made

| Product 1 | Percent Available |
| --- | --- |
|  | 10% |
|  | 20% |
|  | 30% |
|  | 45% |
|  | Any% |

Example 1: User has chosen 10% from exposed filter:

| Product 1 | Percent Available |
| --- | --- |
|  | 10% |
|  | Any% |

Example 2: User has chosen Any% from exposed filter:

| Product 1 | Percent Available |
| --- | --- |
|  | Any% |

# Answer
You can do this by splitting it up into two filters:

The exposed one, as you described it above. Then add 2nd, non-exposed filter on the same field, and the field value must be `Any%`. Then, in the views UI, create a filter group, move both filters in there, and set the group condition to `OR`.
> 0 votes

---
Tags: views
---


# Question
Title: Not able to access "Updates" page logged in as admin user
I am running a site on Acquia's dev cloud, using Acquia's Dev Desktop and sometime in the last few months something has changed to prevent access to the Update tab inside admin/modules/update. I'm logged in as the drupal admin, but when i try to access that page i get:

> You are not authorized to access this page.

Also on that page, cron had stopped running regularly. When I tried running manually, it would give me the same error

# Answer
This is the code for access to 'admin/modules/update', in 'update\_manager\_access':

```
  return variable_get('allow_authorize_operations', TRUE) && user_access('administer software updates');

```

So there are 2 reasons you wouldn't be able to access this page:

1. You don't have the `administer software updates` permission
2. The `allow_authorize_operations` variable is set to FALSE

The second is probably your problem. This is a "global killswitch in settings.php" - the admin/modules/update path allows people to pull and upgrade modules without having actual server access, and Acquia may have disabled that for security.

For those experiencing this and not hosted on Acquia, some of my sites were returning NULL for `allow_authorize_operations` even though it's FALSE in settings.php. Rebuilding permissions did not resolve this so I used `variable_set` in a PHP global field in a view.

References:
> 2 votes

# Answer
What worked for me was rebuilding permissions under "/admin/reports/status/rebuild" (Make sure to take a db backup).

Right after rebuilding, I saw all the available updates.

Thought this might be of help to someone.
> 1 votes

# Answer
In my case (for Drupal 8 / 9 in contrast to the other anwser) the reason was

```
$settings['allow_authorize_operations'] = FALSE;

```

was set in settings.php. The current Drupal default is TRUE.

Down the path this leads to access denied for all paths from update.routing.yml with these requirements:

```
  requirements:
    _permission: 'administer software updates'
    _access_update_manager: 'TRUE'

```

Drupal simply returns Access Denied even for admins, but doesn't explain the reason.

See https://www.drupal.org/project/drupal/issues/2055185#comment-14240814 for details and help to improve the situation.

So you should check if $settings\['allow\_authorize\_operations'\] = TRUE; could be appropriate for you or if it's disabled for security reasons.
> 1 votes

# Answer
## Problem

In Drupal 9.3.5 this message was found in the dblog:

```
Path: /admin/reports/updates/check.
Drupal\Core\Http\Exception\CacheableAccessDeniedHttpException:
'csrf_token' URL query argument is missing.
in Drupal\Core\Routing\AccessAwareRouter->checkAccess()
(line 118 of
/var/www/site.com/web/core/lib/Drupal/Core/Routing/AccessAwareRouter.php
).

```

## Fix

Fixed with clearing/rebuilding caches with drush:

```
drush cr

```

This was on a local Ubuntu development machine.

## Trigger - maybe

I remember visiting some page that did not work with a token in the URL parameter. I removed the token and tried again. After that, the access was denied to the Updates page, as an administrator.

I also ran some cli commands to tighten up file permissions prior to this happening.
> 0 votes

---
Tags: 8
---


# Question
Title: How can I alter the login form in the login block but not in the login page?
How should I use `hook_form_alter()` to modify the user login block but not the user login form page? Everything I've tried either modifies both entities or doesn't work, not even using the following hooks.

```
function mymodule_form_user_login_block_form_alter(&$form, &$form_state, $form_id) {
  // …
}

```

```
function mymodule_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'user_login_block') {
    // …
  }
}

```

# Answer
> 2 votes
It really depends on what you're trying to accomplish. The user login form has a form ID of `user_login_form`. That form, with that form ID, may be shown either in the user login block or on the `/user` page. It is not show twice on the same page - if you're on `/user` then the block will not be shown. To me, if you want to change that login form, you definitely should be changing it in both places that it appears. For that case, use `hook_form_FORM_ID_alter()` which in this case is `hook_form_user_login_form_alter()`.

If you simply want to style your block differently, you can use CSS and target the `#block-userlogin` element or more specifically the `#block-userlogin #user-login-form` element.

Or, you can alter the block plugin using `hook_block_alter()`.

Or, you can create your own custom block to show your own custom login form.

Or ...

Again, it really depends on what you're trying to do by altering just the block.

# Answer
> 1 votes
The form used in the login form and in the login page is the one implemented by the `Drupal\\user\\Form\\UserLoginForm` class. This means that the form ID to check in `hook_form_alter()` or `hook_form_FORM_ID_alter()` is the same in both the cases.

Implementing `hook_block_view_BASE_BLOCK_ID_alter()`, it's possible to alter the rendering output for a block, including the login block.

```
function mymodule_block_view_user_login_block_alter(array &$build, \Drupal\Core\Block\BlockPluginInterface $block) {
  // Alter the login form, which is stored in $build['user_login_form'].
  // This example changes the size of the name and password fields.
  $build['user_login_form']['name']['#size'] = 18;
  $build['user_login_form']['pass']['#size'] = 18;
}

```

The plugin ID for the login block is given in the annotation for the UserLoginBlock class. The content of the `$build` array is returned from `UserLoginBlock::build()`.

```
  $form = \Drupal::formBuilder()->getForm('Drupal\\user\\Form\\UserLoginForm');
  unset($form['name']['#attributes']['autofocus']);

  unset($form['name']['#description']);
  unset($form['name']['#attributes']['aria-describedby']);
  unset($form['pass']['#description']);
  unset($form['pass']['#attributes']['aria-describedby']);
  $form['name']['#size'] = 15;
  $form['pass']['#size'] = 15;

  $placeholder = 'form_action_p_4r8ITd22yaUvXM6SzwrSe9rnQWe48hz9k1Sxto3pBvE';
  $form['#attached']['placeholders'][$placeholder] = [
    '#lazy_builder' => [
      '\\Drupal\\user\\Plugin\\Block\\UserLoginBlock::renderPlaceholderFormAction',
      [],
    ],
  ];
  $form['#action'] = $placeholder;

  $items = [];
  if (\Drupal::config('user.settings')->get('register') != UserInterface::REGISTER_ADMINISTRATORS_ONLY) {
    $items['create_account'] = [
      '#type' => 'link',
      '#title' => $this->t('Create new account'),
      '#url' => Url::fromRoute('user.register', [], [
        'attributes' => [
          'title' => $this->t('Create a new user account.'),
          'class' => [
            'create-account-link',
          ],
        ],
      ]),
    ];
  }
  $items['request_password'] = [
    '#type' => 'link',
    '#title' => $this->t('Reset your password'),
    '#url' => Url::fromRoute('user.pass', [], [
      'attributes' => [
        'title' => $this->t('Send password reset instructions via email.'),
        'class' => [
          'request-password-link',
        ],
      ],
    ]),
  ];
  return [
    'user_login_form' => $form,
    'user_links' => [
      '#theme' => 'item_list',
      '#items' => $items,
    ],
  ];

```

---
Tags: 8, forms
---


title: Use deriver in Drupal Migration yml

text:
# Question
Title: Use deriver in Drupal Migration yml
I am trying to use the deriver key in a migration yml to have dynamically build migrations for each bundle of an Entity Type (Drupal 9).

I read this and I am trying to use the deriver key to point to a Deriver class in my migration. However it seems that the deriver key is just ignored.

Is there something else that I need to do beside using the deriver key and create a deriver class that inherits from Drupal\Component\Plugin\Derivative\DeriverBase?

This is the migration yml:

```
id: person_roles
label: Import
deriver: Drupal\my_module\PersonRoleImportDeriver
migration_group: my_group
source:
  plugin: url
  data_fetcher_plugin: http
  data_parser_plugin: xml
  urls: public://this.xml
  fields:
    -
      name: position_name
      label: person role name
      selector: funktion
  ids:
    position_name:
      type: string
destination:
  plugin: 'entity:my_entity'
process:
  name:
    -
      plugin: skip_on_empty
      method: row
      source: position_name
      message: 'Empty source person role'
    -
      plugin: make_unique_entity_field
      entity_type: my_entity
      migrated: true
      field: name

```

# Answer
> 1 votes
It's a plugin, so you need to respect the plugin directory structure and namespace.

Your class should be in `my_module/src/Plugin/migrate` and have the namespace `Drupal\my_module\Plugin\migrate`.

---
Tags: migrations, 9, plugins
---


# Question
Title: Remove an item from $form_state in an ajax callback
I'm using this form api example: AjaxAddMore. I want to add a "remove button" for each indiviaul element, in order to remove an item but not the latest. Thouse are my changes:

```
...
  $form['names_fieldset'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('People coming to picnic'),
      '#prefix' => '<div id="names-fieldset-wrapper">',
      '#suffix' => '</div>',
      '#attributes' => array('class'=>array('container-inline')),
    ];

    for ($i = 0; $i < $num_names; $i++) {

      $form['names_fieldset']['fields'][$i] = [
        '#type' => 'fieldset',
        '#name' => 'id_'.$i
      ];

      $form['names_fieldset']['fields'][$i]['ids'] = [
        '#type' => 'textfield',
        '#title' => $this->t('ID'),
        '#default_value' => $i,
        '#name' => 'id_'.$i
      ];

      $form['names_fieldset']['fields'][$i]['name'] = [
        '#type' => 'textfield',
        '#title' => $this->t('Name')
      ];

      $form['names_fieldset']['fields'][$i]['remove'] = [
        '#type' => 'submit',
        '#name' => 'remove_'.$i,
        '#value' => $this->t('Remove this'),
        '#submit' => ['::removethisCallback'],
        '#ajax' => [
          'callback' => '::addmoreCallback',
          'wrapper' => 'names-fieldset-wrapper',
        ],
      ];
    }
....

```

It works good and I can add several records. But I can't remove an item other than the latest one. This is my callback function where I've tried to unset the item I want to remove:

```
public function removethisCallback(array &$form, FormStateInterface $form_state) {
    $button_clicked = $form_state->getTriggeringElement()['#name'];
    $id = substr($button_clicked,7);
    $values = $form_state->getValue(['names_fieldset']);
    unset($values[$id]);
    $form_state->setValues(['names_fieldset'], array_values($values));

    $name_field = $form_state->get('num_names');
    if ($name_field > 1) {
        $remove_button = $name_field - 1;
        $form_state->set('num_names', $remove_button);
    }
    $form_state->setRebuild();
}

```

But It doesn't work. How could I remove or update an item from $form\_state?

# Answer
> $form\_state-\>setValues(\['names\_fieldset'\], array\_values($values));

**setValues(array $values)** only has 1 parameter

For 2 params, you need to use **setValue($key, $value)** without the "s"

```
$form_state->setValue('name', array_values($values));

```

---

Alternatively, you could do

```
$values = $form_state->getValues();
$values['name'] = array_values($values);
$form_state->setValues($values);

```
> 1 votes

# Answer
I have same problem, and I think I have a working solution (D9).

```
public function buildForm(array $form, FormStateInterface $form_state): array {
  // $form_state contains all values. Add a new item for init.
  $values = $form_state->getValues();

  if (!isset($values['persons'])) {
    $values['persons'][] = [
      'name' => '',
      'birthdate' => '',
      'btn_text' => 'remove person',
    ];
  }
}

```

An example from the `$form` build:

```
foreach ($values['persons'] as $k => $v) {
  $form['persons'][$k]['name'] = [
    '#type' => 'textfield',
    '#title' => 'Person name',
  ];
}

```

Remove btn. `#indx` is the person id param.

```
$form['persons'][$k]['remove_person'] = [
  '#type' => 'submit',
  '#value' => 'remove person',
  '#submit' => ['::removePerson'],
  '#name' => 'reove_person_' . $k,
  '#indx' => 'indx' . $k,
  '#ajax' => [
    'callback' => '::personCallback',
    'wrapper' => 'persons',
  ],
  '#suffix' => '<hr>',
];

```

Remove person callback get the person index (`#indx`), remove the item, and rebuild the `$form_state`:

```
public function removePerson(array &$form, FormStateInterface $form_state): void {
  $values = $form_state->getValues();
  $element = $form_state->getTriggeringElement();

  if (!isset($element['#indx'])) {
    return;
  }

  $i = preg_replace('~\D~', '', $element['#indx']);

  if (isset($values['persons'][$i])) {
    unset($values['persons'][$i]);
  }

  $form_state->setValues($values);
  $form_state->setRebuild();
}

```

person callback rebuild the form:

```
public function personCallback(array &$form, FormStateInterface $form_state): array {
  return $form['persons'];
}

```
> 0 votes

---
Tags: 8, forms
---


# Question
Title: How to determine if view has translations and which ones
I have a view

```
$view = \Drupal\views\Views::getView($view_id);

```

How to determine if it has been translated into other available languages and which ones

# Answer
> 0 votes
I have been fighting with this lately, and can answer part of the question. If you have the `$viewId` and `$displayId`, then the following seems to indicate whether a translation of the view label, title, and/or view menu entry exists in any language (but does not indicate the language):

```
$viewConfig = \Drupal::configFactory()->get("views.view.$viewId");
$hasTranslation = $viewConfig && ($viewConfig->hasOverrides('label') ||
  $viewConfig->hasOverrides("display.$displayId.display_options.menu.title") ||
  $viewConfig->hasOverrides('display.default.display_options.title'));

```

# Answer
> 0 votes
Since we need to manually add path aliases for translated views, a set alias does provide an indirect opportunity to see if a translation exists.

You could check with `->lookupBySystemPath($path, $langcode)` to see if a view has a path alias for a given language.

```
// Set route match.
$routeMatch = \Drupal::routeMatch();

// Get route object.
$routeObject = $routeMatch->getRouteObject();

// Check if route object.
if ($routeObject) {

  // Get view id and display id from route.
  $view_id = $routeObject->getDefault('view_id');
  $display_id = $routeObject->getDefault('display_id');

  // Check if view.
  if (!empty($view_id) && !empty($display_id)) {

    // Get current path.
    $currentPath = \Drupal::service('path.current')->getPath();

    // Get path alias repository.
    $pathAliasRepository = \Drupal::service('path_alias.repository');

    // Check if system path has Spanish alias.
    if ($pathAliasRepository->lookupBySystemPath($currentPath, 'es')) {

      // Do stuff...
    }
  }
}

```

---
Tags: views, 8, i18n-l10n
---


# Question
Title: hook_init() equivalent for console command
I have a module which subscribes to the kernel.request event to set some environment variables for use with LDAP. E.g. setting the LDAP\_CACERT environment variable. I'm using it to replace hook\_init() as recommended at https://www.drupal.org/node/2013014. However, I've noticed that it does not seem to set the environment variables at the start of Drush commands. E.g. I'd want the environment variables set in a PHP console or a cron run. This is part of a re-useable module so just adding it to settings.php is suboptimal.

**What's the best way to execute code before any arbitrary Drush command runs?**

I've found the console.command event which says:

> The COMMAND event allows you to attach listeners before any command is executed by the console. It also allows you to modify the command, input and output before they are handled to the command.

I had hoped that would work with Drush 9. I've added it to my subscriber like so:

```
/**
  * {@inheritdoc}
  */
public static function getSubscribedEvents() {
  $events['kernel.request'] = ['setLdapEnvVariablesWeb'];
  $events['console.command'] = ['setLdapEnvVariablesCli'];
  return $events;
}

public function setLdapEnvVariablesCli(ConsoleCommandEvent $event) {
  $this->setLdapEnvVariables();
}

```

but unfortunately it never seems to be hit, even though I can see from drupal debug:event console.command that Drupal does recognize I am subscribed to it.

It would be nice if I could handle this in the same subscriber as for web requests but I am not set on it.

# Answer
I've found out what's going on with this. It appears that Drush uses its own event dispatcher separate from Drupal's and that's where the console command event is actually dispatched. That means I need to manually add a listener to Drush's event dispatcher like so:

```
\Drush\Drush::service('eventDispatcher')->addListener('console.command', 'Drupal\mymodule\EventSubscriber\DefaultSubscriber::setLdapEnvVariablesCli');

```

Unfortunately there's still a problem: I need to add that subscriber somewhere that's called before the start of the command in order to be able to call things before the start of the command.

I ended up having to actually subscribe to the Drush event dispatcher event in settings.php:

```
if (function_exists('drush_main') && method_exists('Drush\Drush', 'service')) {
  \Drush\Drush::service('eventDispatcher')->addListener('console.command', 'Drupal\mymodule\EventSubscriber\DefaultSubscriber::setLdapEnvVariablesCli');
}

```

This isn't ideal but it does at least let me keep most of the actual logic in the subscriber.

then I made the CLI callback method and the common method static:

```
public static function setLdapEnvVariablesCli(ConsoleCommandEvent $event) {
  self::setLdapEnvVariables();
}

protected static function setLdapEnvVariables() {
  // ...
}

```

It's a bit ugly but it works. I'll just have to document that a settings.php change is needed in the module README.
> 1 votes

# Answer
I had a similar requirement to load environment variables for the request (vault) but the `console.command` event didn't seem to dispatch in drush (v10) so I just did this, as an alternative:

```
/**
 * Load environment variables for drush CLI
 */
if(PHP_SAPI === 'cli') {
  \Drupal\my_module\EventSubscriber\EnvironmentVariable::load();
}

```

with a static function in the event listener similar to:

```
public static function load() {
  // Load vault variables
  self::loadVault();
}

```

**edit**: here's another way to add an init hook for current drush, using `@hook` in the Drush command file

```
<?php
namespace Drupal\my_module\Commands;

use Consolidation\AnnotatedCommand\AnnotationData;
use Symfony\Component\Console\Input\InputInterface;
use Drupal\my_module\EventSubscriber\EnvironmentVariable;

class MyModuleDrushCommands extends DrushCommands {

  /**
   * @hook init *
   */
  public function loadEnvironmentVariables(InputInterface $input, AnnotationData $annotationData) {
    EnvironmentVariable::load();
  }

  // ..
}

```

More info: https://github.com/consolidation/annotated-command#initialize-hook
> 1 votes

---
Tags: 8, drush, event-subscribers
---


# Question
Title: How can I pass more variables/trigger preprocess to plugin block?
The block opigno\_documents\_last\_group\_block is located in opigno\_learning\_path/src/Plugin/Block/DocumentsLastGroupBlock.php, which looks like this:

```
<?php

namespace Drupal\opigno_learning_path\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Url;

/**
 * Provides a documentslastgroupblock block.
 *
 * @Block(
 *   id = "opigno_documents_last_group_block",
 *   admin_label = @Translation("DocumentsLastGroupBlock"),
 *   category = @Translation("Custom")
 * )
 */
class DocumentsLastGroupBlock extends BlockBase {

  /**
   * @var \Drupal\Component\Plugin\Context\ContextInterface[]|mixed
   */
  protected $groupId;

  /**
   * {@inheritdoc}
   */
  public function build() {
    $this->groupId = $gid = $this->configuration["group"];
    $tid = _tft_get_group_tid($gid);
    $content = _tft_folder_content($tid, FALSE, $gid);
    $content = array_slice($content ?: [], 0, 4);
    foreach ($content as $index => $item) {
      $content[$index] = [
        '#theme' => 'opigno_documents_last_group_item',
        '#type' => $item["type"] == 'file' ? 'file' : 'folder',
        '#item' => $item,
        '#label' => $item["name"],
        '#link' => $this->itemLink($item),
      ];
    }
    $build['content'] = [
      '#theme' => 'opigno_documents_last_group_block',
      'content' => $content,
    ];
    return $build;
  }
(...)

```

and is attached in LearningPathController in this module:

```
 /**
  * Training document block.
  */
  public function trainingContentDocuments(&$content, $group) {

    // $TFTController = new TFTController();
    // $listGroup = $TFTController->listGroup($group->id());
    $tft_url = Url::fromRoute('tft.group', ['group' =>    $group->id()])->toString();

    $content['tabs'][] = $tft_url = [
     '#markup' => '<div class="see-all see-all-files"><a href="' . $tft_url . '">' . $this->t('See all') . '</a></div>',
    ];

    $block_render =    $this->attachBlock('opigno_documents_last_group_block', ['group' => $group->id()]);
   $block_render["content"]['link'] = $tft_url;
    $content['tab_content']['documents'] = (isset($block_render["content"]["content"]) && !empty($block_render["content"]["content"])) ? [
      '#type' => 'container',
      '#attributes' => [
        'id' => 'documents',
      ],
      'block' => [
        'content' => $block_render["content"],
      ],
    ] : [];

  }

```

I tried to extend it in custom module: web/modules/custom/npx\_files/src/Plugin/Block/NpxFilesDocumentsLastGroupBlock.php:

```
<?php

namespace Drupal\npx_files\Plugin\Block;

use Drupal\opigno_learning_path\Plugin\Block;

```

The block opigno\_documents\_last\_group\_block is located in opigno\_learning\_path/src/Plugin/Block/DocumentsLastGroupBlock.php, which looks like this:

```
<?php

namespace Drupal\opigno_learning_path\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Url;

/**
 * Provides a documentslastgroupblock block.
 *
 * @Block(
 *   id = "opigno_documents_last_group_block",
 *   admin_label = @Translation("DocumentsLastGroupBlock"),
 *   category = @Translation("Custom")
 * )
 */
class DocumentsLastGroupBlock extends BlockBase {

  /**
   * @var \Drupal\Component\Plugin\Context\ContextInterface[]|mixed
   */
  protected $groupId;

  /**
   * {@inheritdoc}
   */
  public function build() {
    $this->groupId = $gid = $this->configuration["group"];
    $tid = _tft_get_group_tid($gid);
    $content = _tft_folder_content($tid, FALSE, $gid);
    $content = array_slice($content ?: [], 0, 4);
    foreach ($content as $index => $item) {
      $content[$index] = [
        '#theme' => 'opigno_documents_last_group_item',
        '#type' => $item["type"] == 'file' ? 'file' : 'folder',
        '#item' => $item,
        '#label' => $item["name"],
        '#link' => $this->itemLink($item),
      ];
    }
    $build['content'] = [
      '#theme' => 'opigno_documents_last_group_block',
      'content' => $content,
    ];
    return $build;
  }
(...)

```

and is attached in LearningPathController in this module:

```
 /**
  * Training document block.
  */
  public function trainingContentDocuments(&$content, $group) {

    // $TFTController = new TFTController();
    // $listGroup = $TFTController->listGroup($group->id());
    $tft_url = Url::fromRoute('tft.group', ['group' =>    $group->id()])->toString();

    $content['tabs'][] = $tft_url = [
     '#markup' => '<div class="see-all see-all-files"><a href="' . $tft_url . '">' . $this->t('See all') . '</a></div>',
    ];

    $block_render =    $this->attachBlock('opigno_documents_last_group_block', ['group' => $group->id()]);
   $block_render["content"]['link'] = $tft_url;
    $content['tab_content']['documents'] = (isset($block_render["content"]["content"]) && !empty($block_render["content"]["content"])) ? [
      '#type' => 'container',
      '#attributes' => [
        'id' => 'documents',
      ],
      'block' => [
        'content' => $block_render["content"],
      ],
    ] : [];

  }

```

I tried to extend it in custom module: web/modules/custom/npx\_files/src/Plugin/Block/NpxFilesDocumentsLastGroupBlock.php, but it doesn't really get triggered (I am not sure if I can even extend this this way):

```
<?php

namespace Drupal\npx_files\Plugin\Block;

use Drupal\opigno_learning_path\Plugin\Block;
/**
 * Provides a documentslastgroupblock block.
 *
 * @Block(
 *   id = "opigno_documents_last_group_block",
 *   admin_label = @Translation("DocumentsLastGroupBlock"),
 *   category = @Translation("Custom")
 * )
 */

class NpxFilesDocumentsLastGroupBlock extends DocumentsLastGroupBlock {

  public function build(){
    return [
      '#markup' => $this->t('Hello, World!'),
    ];
  }

}

```

However, it doesn't trigger the block, what is the good way to extend this? Cache cleared&module turned on of course.

```
class NpxFilesDocumentsLastGroupBlock extends DocumentsLastGroupBlock {

  public function build(){
    return [
      '#markup' => $this->t('Hello, World!'),
    ];
  }

}

```

Cache cleared&module turned on of course.' I tried to preprocess this plugin block by hook\_preprocess\_block, but it doesn't get triggered by this hook, only its 'parent' block does. Also hook\_block\_build\_alter doesn't get triggered by this block (only its parent). I am able to get to this block by hook\_block\_alter, but it doesn't really help, as I am not able to put some extra variables there, I think.

Could anybody point me in the right direction? I would like to either add extra variables to this block or point it to display some other block or unset it/disable programatically before rendering. I spent plenty of time trying to learn about it and trying different hooks, but no luck so far.

# Answer
> 0 votes
Thanks for ignoring my question and downvotes! ;) I totally don't understand you people. However, I managed to understand how to solve my problem and pass variables:

```
function npx_main_theme() {
  return [
    'opigno_documents_last_group_block' => [
      'variables' => [
        'param1' => 'texttest'
      ]
    ]
  ];
}

```

---
Tags: blocks, hooks, 9
---


# Question
Title: Render custom region into node twig template
My code used for D8 doesn't work anymore for D9. Custom region twig template for region into node twig template

I get thise error and WSOD:

```
Error : Call to undefined function entity_load_multiple_by_properties() dans themex_add_regions_to_node() (/home/xx/www/pfdev/multid9/recommended-project/web/themes/custom/themex/themex.theme ligne 145)

```

I notice that the condition on the region doesn't work too but I can render the content region with twig tweak syntax (outside the if condition):

```
{% if region_Zone_1 is not empty %}
  <div {{ noderegion_attribute.addClass(noderegion_classes).setAttribute('id', 'region-zone-1') }}>
    {{ region_Zone_1 }}
    {# Avec le module twig_tweak #}
    {{ drupal_region('region_Zone_1') }}
  </div>
  <!-- /#region-zone_1 -->
{% endif %}

```

So, what's the way to do the same thing or fix it for D9 ?

Thanks

EDIT: is this could fix my issue ? `$blocks = entity_load_multiple_by_properties('block', array('theme' => $theme, 'region' => $region));` replaced by:

```
$blocks = \Drupal::entityTypeManager()
        ->getStorage('block')
        ->loadByProperties(['theme' => $theme, 'region' => $region)]);

```

# Answer
here you have example, how it was patched in contrib module:

```
diff --git a/modules/webform_submission_export_import   /webform_submission_export_import.module b/modules/webform_submission_export_import/webform_submission_export_import.module
index 69267d2a5..fd4e8b4ba 100644
--- a/modules/webform_submission_export_import/webform_submission_export_import.module
+++ b/modules/webform_submission_export_import/webform_submission_export_import.module
@@ -236,7 +236,9 @@ function _webform_submission_export_import_file_save_upload_single(\SplFileInfo
   // @todo Do not create a new entity in order to update it. See
   //   https://www.drupal.org/node/2241865.
   if ($replace == FileSystemInterface::EXISTS_REPLACE) {
-    $existing_files = entity_load_multiple_by_properties('file', ['uri' => $file->getFileUri()]);
+    $existing_files = \Drupal::entityTypeManager()
+      ->getStorage('file')
+      ->loadByProperties(['uri' => $file->getFileUri()]);
     if (count($existing_files)) {
       $existing = reset($existing_files);
       $file->fid = $existing->id();

```

Also there are helpful modules that takes care of this kinds of problems by creating patches or even changing the code automatically (you should use them on your D8 version of website). I used them to switch to D9 and it saved me a lot of time:
> 0 votes

---
Tags: theming, 9
---


# Question
Title: Why isn't config for Views plugin module translatable?
I am trying to write up a patch for this module: https://www.drupal.org/project/readmore. There is a patch for it: https://www.drupal.org/project/readmore/issues/3055200 which adds configurable text for the "read more" and "read less" links provided by this field formatter. But the configuration for these new settings are not translatable.

I noticed that the readmore.schema.yml did not include entries for these new fields (although the new configuration options do work). I added this:

```
readmore_text:
  type: string
  label: 'Read more link text'
readless_text:
  type: string
  label: 'Read less link text'

```

To the .schema file but it doesn't help.

What is missing to trigger translation of this view to show these new configuration options?

# Answer
> 1 votes
First of all, for translatable strings you need `type: label`. Then the Views entity field schema

*views.field.schema.yml:*

```
views.field.field:
  type: views_field
  label: 'Views entity field handler'
  mapping:
    click_sort_column:
      type: string
      label: 'Column used for click sorting'
    type:
      type: string
      label: 'Formatter'
    settings:
      label: 'Settings'
      type: field.formatter.settings.[%parent.type]

```

expects a field formatter schema with this structure:

```
field.formatter.settings.daterange_default:
  type: field.formatter.settings.datetime_default
  label: 'Date range default display format settings'
  mapping:
    separator:
      type: label
      label: 'Separator'
      translation context: 'Date range separator'

```

This example is extending a base class and so it is also extending the schema. Otherwise you can replace the type reference to the parent formatter with `type: mapping`. See also Language specific settings for field formatters

---
Tags: views, 9, configuration
---