# Question
Title: hook_node_presave get original of translated node
I'm using a hook\_node\_presave and I want to detect which field is updated when the translated node is updated. Here is my code :

```
function hook_import_node_presave(\Drupal\node\NodeInterface $node) {
  if (!$node->isNew()){
    $entityFieldManager = \Drupal::service('entity_field.manager');
    $fields = $entityFieldManager->getFieldDefinitions('node', 'article');
    foreach($fields as $field_name => $field_definition) {
      foreach ($node->getTranslationLanguages() as $langcode => $langcode_value) {
        $node = $node->getTranslation($langcode);
        if ($node->get($field_name)->getValue() != $node->original->get($field_name)->getValue()) {
          // do something
        }
      }
    }
  }
}

```

However,

```
$node = $node->getTranslation($langcode);
$node->original->get($field_name)->getValue()

```

even after "getTranslation()", "original" is still pointing to the default language. I want to get the "original" language of the translated node.

# Answer
```
$node = $node->getTranslation($langcode);

```

This is changing the translation of the node object passed by reference. Better use a different variable:

```
$node_translated = $node->getTranslation($langcode);

```

---

```
$node->original->get($field_name)->getValue()

```

`original` is a separate node object and has to be translated separately:

```
$node->original->getTranslation($langcode)->get($field_name)->getValue()

```
> 1 votes

---
Tags: hooks
---


# Question
Title: How to access entity from EntityReferenceItem?
I have the attached array below and need help figuring out how to access the 'entity' attribute that is under the protected "properties" array (see screenshot).

I am using the Viewfield module

background: field\_name is an entity reference field. I need to get the EntityReference so that I can call getTarget() to get the EntityAdapter and then call EntityAdapter-\>getValue().

I have tried the following but they all give errors. The idea is to get the EntityReference which is the 'entity' value. How can i do this?

```
mytheme_preprocess_viewfield_item(&vars) {

  $element = $vars['element'];
  $results = $element['#content']['#view']->result;

  foreach($results as $row) {
    $entity = $row->_entity
    $offset = $entity->get('field_name')->offsetGet(0)

kint($entity->get($video_field_name)) /* result of screenshot */

    $entityReference = $offset->get('entity') /* failed */
    $entityReference = $offset->getProperties() /* failed */
    $entityReference = $offset->getEntity() /* failed */
    $entityReference = $offset->getValue() /* failed */
  }//end foreach
}//end theme_preprocesss

```

The error message is: replace getValue() with any of the above

Call to a member function getValue() on null

# Answer
> 3 votes
If `entity` in the foreach loop is not empty you should be able to do

```
$entity->field_name->entity
//or perhaps
$entity->field_name->referencedEntities();

```

# Answer
> 0 votes
In case you have an EntityReferenceItem you can get the entity with `getEntity()`

```
$item->getEntity();

```

And if you have an EntityReferenceItemList:

```
$list = $itemList->get(field_name);
foreach ($list as $item) {
  $entity = $item->getEntity();
}
// or
$itemList->get(field_name)->referencedEntities();

```

---
Tags: 8, entities, hooks
---


title: How to debug permission problems

text:
# Question
Title: How to debug permission problems
I already found answers for older versions here and here but as far as I can tell none of it directly translates into drupal 9.

The matter in practice: I don't have a huge experience but I was very surprised when in the not so complicated setup I'm building I could see the page of a taxonomy term but none of the items in it under the introductory text when viewing the page as anonymous user. Viewing one of the nodes by direct url results in "Access Denied".

Not much at play, all items are published, permissions look good and I already rebuilt permissions and caches so I'm looking for something like raw printing yay/nay permissions being applied and so on. Even looking directly in the database would be ok if applicable.

# Answer
> 0 votes
In the end it was all my fault, and very simple: I had not yet defined the default domain in the **Domain Access** module. The question still stands however, as I could not find ways to debug permissions applicable to Drupal 9. So this is my answer to the original problem but not an answer to the more generic task.

---
Tags: 9
---


# Question
Title: Validation for radio inputs don't work for me
I'm building a form with the drupal forms api. Validation works well for all my other fields. But I've started to try and work with radio buttons too now. It doesn't matter if I click on a radio option, the validation returns always 'color is required'.

```
// Form build method code
$form['birthdate'] = [
  '#type' => 'date',
  '#title' => $this->t('Your date of birth'),
  '#date_date_format' => 'd-m-Y',
];

$form['color_select'] = [
  '#type' => 'radios',
  '#title' => $this->t('Pick a color'),
  '#options' => [
    'blue' => $this->t('Blue'),
    'white' => $this->t('White'),
    'black' => $this->t('Black'),
    // 'other' => $this->t('Other'),
  ],
  '#attributes' => [
    'id' => 'color_select',
    'name' => 'field_color_select',
  ],
  '#states' => [
    'enabled' => [
      ':input[name="field_custom_color"]' => ['value' => ''],
    ],
  ],
];

// Form validator method code
if ($form_state->getValue('birthdate') == '') {
  $form_state->setErrorByName('birthdate', $this->t('Date of birth is required'));
}
if ($form_state->getValue('color_select') == '') {
  $form_state->setErrorByName('color_select', $this->t('Color is required'));
}

```

I thought that the getValue(name) and setErrorByname(name) have to the same as $form\[name\] =\[\]; to make it work, but for the radio buttons field, it doesn't.

# Answer
> 0 votes
I managed to get it working like this:

```
$form['color_select'] = [
  '#type' => 'radios',
  '#title' => $this->t('Pick a color'),
  '#options' => [
    'blue' => $this->t('Blue'),
    'white' => $this->t('White'),
    'black' => $this->t('Black'),
    // 'other' => $this->t('Other'),
  ],
  '#attributes' => [
    'id' => 'color_select',
    'name' => 'color_select',
  ],
  '#states' => [
    'checked' => [
      ':input[name="color_select"]' => [
        ['value' => 'blue'],
        'or',
        ['value' => 'white'],
        'or',
        ['value' => 'black'],
      ],
    ],
  ],
];

```

Although I'm not sure how it works now. Does it actually set the radio button on checked when the value is one of the given value ones?

---
Tags: forms, 9
---


# Question
Title: Migrating date into drupal datetime field
i am having the xml selector

```
<starting_date><![CDATA[ 2017-01-01 22:34:56 +0100 ]]></starting_date>

```

this migration process fails :

```
process:
  field_job_starting_date:
    plugin: format_date
    source: starting_date
    from_format: 'Y-m-j H:i:s Z'
    to_format: 'Y-m-d\TH:i:s'
    to_timezone: 'Europe/Paris'

```

How can i fix it ?

# Answer
it was to import into a drupal datetime field

```
process:
  field_job_starting_date:
    plugin: format_date
    from_format: 'Y-m-d H:i:s O'
    to_format: 'Y-m-d\TH:i:s'
    to_timezone: 'UTC'
    source: starting_date

```

https://understanddrupal.com/articles/migrating-dates-drupal

The dates are stored in drupal as UTC
> 0 votes

---
Tags: migrations, datetime
---


title: Formatting date field with the Form API

text:
# Question
Title: Formatting date field with the Form API
Hi there I'm using drupal 9.x and the forms api to generate a dynamic form. Altough I'm living in the Netherlands where the date format standard is 'dd/mm/yyyy'. I've looked around on the internet for recent ways to modify that format in the html input. But all ways seems to be deprecated cause they don't seem to work for me. I've tried stuff like:

```
$form['birthdate'] = [
  '#type' => 'date',
  '#title' => $this->t('Your date of birth'),
  '#date_date_format' => 'd-m-Y',
  // and
  '#dateformat' => 'd-m-Y',
];

```

But none of those seems to work. All other ways that I've found are from 2017 and below. Which seems to deprecated for me.

# Answer
> 2 votes
I think you can say it is deprecated. Since Datetime is a core module you can use its form element `datetime`:

```
$form = [
  '#type' => 'datetime',
  '#default_value' => new DrupalDateTime('2000-01-01 00:00:00'),
  '#date_date_element' => 'date',
  '#date_time_element' => 'none',
  '#date_year_range' => '2010:+3',
  '#date_timezone' => 'Asia/Kolkata',
];

```

Drupal is using HTML5 forms and the localization is mostly client-side.

The datetime form element is very well documented. I took the example from this API page, which by the way is exactly your use case of a date only field.

---
Tags: forms, 9
---


# Question
Title: How to add css class on click of CKeditor table button?
We are using the CKEditor module provided from Drupal 8 (v8.6.2). There is a need to add a `css` class to the table when it is added to the `Body` field (text formatted, long) after someone clicks on the table button without having to modify the table via `Source` button.

**How would we add a css class to the table after clicking the CKEditor table button?**

The goal is to be able to do this without a module. If it comes down to it, we can review the module, but prefer to use any out of the box functionality. Another goal is to be able to do this on D8.

# Answer
> 1 votes
You can add copies of: ckeditor.styles.js ckeditor.config.js to your theme directory

You can add a class using jQuery addClass

Be sure to set custom JS path under directory CKEDITOR profile settings.

\*This was method under D7

**D8** Option 1: You use this editor\_js\_settings hook to adjust ckeditor settings. A full list of settings can be found \[here\]\[3\]

Option 2: Target item using jQuery addClass in the themes or custom module sites scripts.js file

Option 3: Create a custom module based on a copy of CKEDITOR module with a class added where you need it, or create a patch for the module to add your class. Classes to buttons are added here core/modules/ckeditor/ckeditor.admin.inc (be sure not to edit this core file)

# Answer
> 0 votes
This can be done using a filter plugin. I have written one that does something similar here: https://www.drupal.org/project/wxt/issues/3247278

You can just copy the file that the patch creates and place it in your custom module under /src/Plugin/Filter/WxTAddTableAttributeFilter.php. Then modify the namespace to replace wxt\_ext\_editor with your module's name. Finally, enable the filter in your text format to take effect.

This filter adds another attribute that you probably don't want, so just remove the code as needed.

This link provides more details on CKEditor filter plugins: https://www.lullabot.com/articles/creating-a-custom-filter-in-drupal-8

---
Tags: 8, hooks, wysiwyg
---


# Question
Title: Attempting to return region in theme suggestions for the book module book tree block
Editing question based on information from @NoSssweat

The book module uses the same hook for the book tree block and the rendered index view in the book page.

I have used the below code to return file name suggestions, so that I can override the html output for the book tree block in a specific region - "sidebar-first". I expected the below code would spit out something like `book-tree--book-toc-180--sidebar-first.html.twig`. Instead, it just spits out a file name suggestion that is already being suggested:

```
<!-- FILE NAME SUGGESTIONS:
   * book-tree--book-toc-180.html.twig
   * book-tree--book-toc-180.html.twig
   x book-tree.html.twig
-->

```

This file name suggestion is the same for the main content on the book page. How can I target any book tree blocks within the `sidebar-first` region?

```
// Add a region variable to a block.
// http://kristiankaa.dk/article/drupal8-region-specific-menu-theme-hook-suggestion
function uswds_subtheme_preprocess_book_tree__book_toc_180(&$variables) {
    if (isset($variables["elements"]["#id"])) {
        $block_id = $variables["elements"]["#id"];
        $block = \Drupal\block\Entity\Block::load($block_id);

        if ($block) {
            $variables["content"]["#attributes"]["region"] = $block->getRegion();
        }
    }
}

// add a template suggestion based on region name
// http://kristiankaa.dk/article/drupal8-region-specific-menu-theme-hook-suggestion
function uswds_subtheme_theme_suggestions_book_tree__book_toc_180_alter(array &$suggestions, array $variables) {
    if (isset($variables["attributes"]["region"])) {
        $suggestions[] = $variables["theme_hook_original"] . "__" . $variables["attributes"]["region"];
    }
}

```

---

**2nd attempt** I did the below, and it works but it only works for the book module default block, although any other book module block plugin all mostly use `book-tree.html.twig`

```
// Add a region variable to a block.
function uswds_subtheme_preprocess_block(&$variables) {
  if (isset($variables["elements"]["#id"])) {
    $block_id = $variables["elements"]["#id"];
    $block = \Drupal\block\Entity\Block::load($block_id);

    if ($block) {
      $variables["content"]["#attributes"]["region"] = $block->getRegion();
    }
  }
}

// add a template suggestion based on region name
function uswds_subtheme_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  if (isset($variables["attributes"]["region"])) {
    $suggestions[] = $variables["theme_hook_original"] . "__" . $variables["attributes"]["region"];
  }
}

```

# Answer
> or how can I do something in twig, like `{% if region == 'sidebar-first' %}` and just override book-tree.html.twig

```
// Adds a region attribute to a block.
function uswds_subtheme_preprocess_block(&$variables) {
  if (isset($variables["elements"]["#id"])) {
    $block_id = $variables["elements"]["#id"];
    $block = \Drupal\block\Entity\Block::load($block_id);
    if ($block) {
      $variables["content"]["#attributes"]["region"] = $block->getRegion();
    }
  }
}

/**
 * Implements hook_preprocess_HOOK().
 *
 * Creates region variable
 *
 * Gets rid of the region attribute added in uswds_subtheme_preprocess_block() as it's
 * not a valid HTML attribute.
 */
function uswds_subtheme_preprocess_book_tree(&$variables) {
  if (isset($variables['attributes']['region'])) {
    // creates region variable for book-tree.html.twig
    $variables['region'] = $variables['attributes']['region'];
    // unset invalid html attribute.
    unset($variables['attributes']['region']);
  }
}

```
> 3 votes

# Answer
Nice try, since this is a book and not menu, the process is similar, but not exactly the same. I was hoping you would figure it out.

But anyways, here you go:

```
/**
 * Implements hook_preprocess_HOOK().
 *
 * Pass block region value to content so this can be used in
 * uswds_subtheme_theme_suggestions_menu_alter() since $variables['elements']
 * is not available there.
 */
function uswds_subtheme_preprocess_block(&$variables) {
  if (isset($variables['elements']['#id']) && $variables['base_plugin_id'] === 'book_navigation') {
    $region = \Drupal\block\Entity\Block::load($variables['elements']['#id'])->getRegion();
    $content = $variables['content'];
    foreach ($content as $content_key => $content_info) {
      if (is_numeric($content_key)) {
        $variables['content'][$content_key]['#attributes']['region'] = $region;
      }
    }
  }
}

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 *
 * Provide region based book suggestions.
 */
function uswds_subtheme_theme_suggestions_book_tree_alter(&$suggestions, array $variables) {
  if (isset($variables['attributes']['region'])) {
    $suggestion = 'book__' . $variables['theme_hook_original'] . '__' . $variables['attributes']['region'];
    $suggestion = str_replace('-', '_', $suggestion);
    $suggestions[] = $suggestion;
  }
}

/**
 * Implements hook_preprocess_HOOK().
 *
 * Get rid of the region attribute added in uswds_subtheme_preprocess_block() as it's
 * not a valid HTML attribute.
 */
function uswds_subtheme_preprocess_book_tree(&$variables) {
  if (isset($variables['attributes']['region'])) {
    unset($variables['attributes']['region']);
  }
}

```
> 1 votes

# Answer
Using all of the help from @NoSssweat and I was able get this working:

```
// Add a region variable to a block.
function uswds_subtheme_preprocess_block(&$variables) {
  if (isset($variables["elements"]["#id"])) {
    $block_id = $variables["elements"]["#id"];
    $block = \Drupal\block\Entity\Block::load($block_id);

    if ($block) {
      $variables["content"]["#attributes"]["region"] = $block->getRegion();
    }
  }
}

// add a template suggestion based on region name
function uswds_subtheme_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  if (isset($variables["attributes"]["region"])) {
    $suggestions[] = $variables["theme_hook_original"] . "__" . $variables["attributes"]["region"];
  }
}

```

Which outputs (the second suggestion including the region):

```
<!-- FILE NAME SUGGESTIONS:
   * book-tree--book-toc-180.html.twig
   * book-tree--book-toc-180--sidebar-first.html.twig
   x book-tree.html.twig
-->

```

---

**Update to working version:**

```
<?php
// Add a region variable to a block. Only applies to some versions of plugins that use book-tree.html.twig
function uswds_subtheme_preprocess_block(&$variables) {
    if (isset($variables["elements"]["#id"])) {
      $block_id = $variables["elements"]["#id"];
      $block = \Drupal\block\Entity\Block::load($block_id);

      if ($block) {
        $variables["content"]["#attributes"]["region"] = $block->getRegion();
      }
    }
  }

// Adds template suggestion to blocks. Seems to work everywhere, but doesn't target the book tree
function uswds_subtheme_theme_suggestions_block_alter(array &$suggestions, array $variables){
    if (!empty($variables['elements']['#id'])) {
        $block = \Drupal\block\Entity\Block::load($variables['elements']['#id']);
        $region = $block->getRegion();
        // adds suggestion with region and block id
        $suggestions[] = 'block__' . $region . '__' . $variables['elements']['#id'];
        // adds suggestion with region id
        $suggestions[] = 'block__' . $region;
    }
}

// add a template suggestion based on region name
function uswds_subtheme_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  if (isset($variables["attributes"]["region"])) {
    $suggestions[] = $variables["theme_hook_original"] . "__" . $variables["attributes"]["region"];
  }
}

```
> 1 votes

---
Tags: theming, blocks
---


# Question
Title: Programmatically getting variation type fields in order
I am trying to get variation type field values from the order entity but I can't find any documentation on this. I am using an event subscriber to run the following code when an order is paid. The code works, but I can't see any reference to the fields in kint and I can't find any references to any kind of "getVariation" or equivalent function online.

```
/**
 * This method is called when the commerce_order.order.paid is dispatched.
 *
 * @param \Symfony\Component\EventDispatcher\Event $event
 *   The dispatched event.
 */
public function commerceOrderOrderPaid(Event $event) {
  /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
  $order = $event->getOrder();
  $items = $order->getItems();
  foreach ($items as $item) {
    kint($item);
    if ($item->get('type')->target_id == 'purchase_things') {
      // 'number_of_things' is a variation type field.
      $thingQuant = $item->get('number_of_things');
      // The line does not work, obviously.
      // I cannot see 'number_of_things' anywhere in kint($item).
    }
  }
}

```

# Answer
Using Devel and Kint I was able to find the "getVariation" function I was looking for. This code lets you get the variation type fields.

`$item->getPurchasedEntity()->get('field_number_of_things')->value`
> 1 votes

---
Tags: 8, commerce
---


title: Toggle view displays on the same page

text:
# Question
Title: Toggle view displays on the same page
There are 2 view displays (2 blocks) which are showing products, one with tile display, one with list display, as shown in the image below.

Is there a way to have both blocks on the same page, but toggle them with a button? Once the button is clicked, one block is hidden and the other one is shown.

What would be the best way to achieve this? Is there a module that provides functionality about this?

# Answer
I solved this by adding a session value that decides whether it should be a list view or a tile view, depending on this value, the class changes on the list and the appropriate styling is applied. It is 1 view display with a ui-patterns applied to it and in the twig there are 2 if-cases for the styling.
> 0 votes

---
Tags: 8, views
---


# Question
Title: Migrate users datas to the profile module
I’m able to migrate users datas from a csv file with migrate, migrate\_tools, migrate\_source\_csv and drush

Now, i’m trying to import datas from the same csv file to the Profile module (which provides configurable user profiles).

Here is my configuration file for user import. Obviously, i I add the profile fields in it (here `field_profile_last_name`, it doesn’t work).

```
id: user_migrate
migration_tags: null
migration_group: null
label: 'User migration from CSV'
source:
  plugin: csv
  path: /path-to-csv/users.csv
  header_row_count: 1
  keys:
    - weblogin
process:
  # user fields with custom fields : works !
  name: weblogin
  mail: email
  roles: roles
  field_last_name: nom_salarie
  field_first_name: prenom_salarie
  field_password_web_services: weblogin
  status: status
  field_profile_address: adresse1
  field_code: code
  field_date_de_naissance: date_naissance
  field_numero_societe: numsoc
  field_profile_function: qualification
  # profile fields : doesn't work
  field_profile_last_name: nom_salarie
destination:
  plugin: 'entity:user'
migration_dependencies:
  required: {  }
  optional: {  }

```

How can i migrate datas to the profile module ? What is the entity for this module.

# Answer
I post an answer to my question. Feel free to comment or edit my answer in order to improve.

I’ve migrated users datas from a csv file. If you need help to do this, you can follow instructions in this questions : Import users into Drupal with data from a CSV file

Now, i import the profile data in a migration process that maintains the relationships between source and destination identifiers in map table.

So the profile is related to the correct uid.

More information on this here (Process plugin: migration\_lookup):

https://www.drupal.org/docs/8/api/migrate-api/migrate-process-plugins/process-plugin-migration\_lookup-formerly-migration

The configuration file looks like this. You have to adapt some values as :

uid: source: xxx

This takes the value of the xxx property in the source data, and looks it up in the map table associated with the users migration, returning the resulting user ID and assigning it to the destination uid property.

You have to adapt the fields of course and the key to your needs.

```
id: profile_migrate
migration_tags: null
migration_group: null
label: 'Profile migration from CSV'
source:
  plugin: csv
  path: /path/to/csv/users.csv
  header_row_count: 1
  keys:
    - weblogin
destination:
  plugin: entity:profile
process:
   type:
    plugin: default_value
    default_value: 'profile'
   uid:
     plugin: migration_lookup
     no_stub: true
     # previous user migration
     migration: user_migrate
     # property in the source data
     source: weblogin
   field_profile_last_name:
     plugin: get
     source: nom_salarie
   field_profile_first_name: prenom_salarie
   field_profile_address: adresse1
   field_date_de_naissance: date_naissance
   field_code: code
   field_numero_societe: numsoc
   field_profile_function: qualification
migration_dependencies:
  required: {  }
  optional: {  }

```
> 0 votes

# Answer
I have migrated profiles recently from D7 to D9. Here is what I did.

1. Get csv data from drupal 7 with content you want
2. Create a form to upload a csv file
3. In submit function here is the code what I wrote

```
public function submitForm(array &$form, FormStateInterface $form_state) {

  // Fetch the array of the file stored temporarily in database.
  $csv_file = $form_state->getValue('csv_upload');

  // Load the object of the file by it's fid.
  $file = File::load( $csv_file[0] );

  // Set the status flag permanent of the file object.
  $file->setPermanent();

  // Save the file in database.
  $file->save();

  // You can use any sort of function to process your data. The goal is to
  // get each 'row' of data into an array.
  // If you need to work on how data is extracted, process it here.
  $data = $this->csvtoarray($file->getFileUri(), ',');
  $connection = \Drupal::database();

  foreach($data as $key => $row) {
    $profile = Profile::create([
      'type' => 'main',
      'uid' => $row['uid'],
      'field_blurb' => [
        'value'  =>  $row['Blurb'],
        'format' => 'full_html'
      ],
      'field_link' => [
        'uri'=> $row['link'],
        'title' => $row['text']
      ],
      'field_reference' => [
        'target_id' =>  $row['tid'],
      ],
      'field_icon' => [
        "target_id"  =>  $row['fid'],
      ],
    ]);
    $profile->save();
  }

}

public function csvtoarray($filename='', $delimiter){
  if (!file_exists($filename) || !is_readable($filename)) {
    return FALSE;
  }
  $header = NULL;
  $data = [];

  if (($handle = fopen($filename, 'r')) !== FALSE ) {
    while (($row = fgetcsv($handle, 1000, $delimiter)) !== FALSE) {
      if (!$header) {
        $header = $row;
      }
      else {
        $data[] = array_combine($header, $row);
      }
    }
    fclose($handle);
  }

  return $data;
}

```

\` 4. This creates a profiles with id and connects them to each user with user id from csv file
> 0 votes

---
Tags: 8, users, migrations
---


# Question
Title: Trying to access a "count" variable inside a block field from paragraphs template
I'm trying to get the number of paragraphs an authenticated user inputs by counting them in the parent block template and trying to access that number in the paragraphs template. I have two templates I'm working with:

1. field--field-hover-image-block.html.twig
2. paragraph--hover-images.html.twig

The paragraphs are being loaded through the paragraph entity field in a custom block. I'm counting the number of the block paragraph fields with this code in that block's template, field--field-hover-image-block.html.twig:

```
{% for item in items %}
    {% set count = items|length %}
    <figure class="hover-image">{{ item.content }}</figure>
{% endfor %}

```

The count works, but doesn't pass to the paragraphs template.

If the count is 4 or more, I need the paragraphs template to render a class for that. Else, I don't need the class. Here is my code for the paragraphs template (paragraph--hover-images.html.twig):

```
{% if count >= 4 %}
   {{ content.field_hover_image.0 }}
   <figcaption class="four-count-plus">
        <div>
            <h2>{{ content.field_hover_title.0 }}</h2>
            <p>{{ content.field_hover_text.0 }}</p>
        </div>
   </figcaption>
{% else %}
   {{ content.field_hover_image.0 }}
    <figcaption>
        <div>
           <h2>{{ content.field_hover_title.0 }}</h2>
           <p>{{ content.field_hover_text.0 }}</p>
         </div>
   </figcaption>
{% endif %}

```

Any help with this would be greatly appreciated.

# Answer
The count needs to be in the custom block's paragraph field twig, not the paragraph twig.

In the field--field-hover-image-block.html.twig, this works:

```
{% set count = 0 %}

{% for item in items %}
   {% set count = items|length %}
   {% set figure_classes = [
      'hover-image-effect',
       'image-count-' ~ count
    ] | sort | join(' ') | trim %}

    <figure class="{{ figure_classes }}">{{ item.content }}</figure>

{% endfor %}

```

And then in paragraph--hover-images.html.twig, format as usual:

```
{% block paragraph %}

      {% block content %}

        {{ content.field_hover_image.0 }}

         <figcaption class="absolute block left-0 right-0 w-full cursor-pointer">
            <div class="border-wrapper">
                 <h2 class="m-0 font-bold capitalize text-blue-500 leading-tight">{{ content.field_hover_title.0 }}</h2>
                 <p class="text-blue-500 leading-tight">{{ content.field_hover_text.0 }}</p>
                 <a href="{{ content.field_hover_link.0['#url'] }}" title="Go to {{ content.field_hover_link.0['#title'] }}" >{{ content.field_hover_link.0['#title'] }}</a>
            </div>
         </figcaption>

   {% endblock %}

{% endblock paragraph %}

```
> 0 votes

---
Tags: blocks, paragraphs
---


# Question
Title: Extending block, a block with a paragraph field, and 3 paragraph fields... how to loop through the paragraphs from the block extension
This is what I have:

I have three twig files:

1. block--paragraph-images.html.twig (which extends block.html.twig)
2. field--field-paragraph-image-block.html.twig (the paragraph field which is located in the custom block type, block--paragraph-images.html.twig.)
3. paragraph--field-paragraph-image.html.twig (which houses three fields: field\_paragraph\_image, field\_paragraph\_title, and field\_paragraph\_text).

I can access the individual fields in the paragraph--field-paragraph-image.html.twig from the block--paragraph-images.html.twig, but it only shows the first entry. I need to loop through the paragraph fields in the field--field-paragraph-image-block.html.twig. I'm trying to execute everything from the block--paragraph-images.html.twig to keep the files more manageable. Is this doable?

What I have below only shows the first index in the array. If I uncomment the loop statement, it shows around 12 each of the first index in the array. What I need is each paragraph index to show only once in a grid.

> 0, image, title, text

> 1, image, title, text

> 2, image, title, text

Any help and direction is appreciated.

```
{% block content %}

    {# block fields #}
    {% set paragraph_count = content.field_paragraph_image_block['#items']|length %}
    {% set paragraph_count_css = 'grid-cols-' ~ paragraph_count %}

    {# paragraph fields #}
    {% set paragraph_title = content.field_paragraph_image_block.0["#paragraph"].field_paragraph_title.value %}
    {% set paragraph_text = content.field_paragraph_image_block.0["#paragraph"].field_paragraph_text.value %}
    {% set media_id = content.field_paragraph_image_block.0["#paragraph"].field_paragraph_image.target_id %}

    <div class="block__content image-paragraph mb-0 grid gap-4  {{ paragraph_count_css }} " >
        {% set paragraph_classes = [
            'paragraph-image-effect',
            'image-count-' ~ paragraph_count,
        ] | sort | join(' ') | trim %}

       {# {% for item in content.field_paragraph_image_block %} #}
            <div class="{{ paragraph_classes }}">
                    {{ drupal_entity('media', media_id) }}
                    {{ paragraph_title }}
                    {{ paragraph_text }}
            </div>
       {# {% endfor %} #}
    </div>

{% endblock %}

```

# Answer
> 2 votes
Found the solution to this issue. You **can** have just one twig file, the custom block twig file, and access the fields inside the paragraphs.

Move the paragraph variables to inside the for loop, and replace the variables like this:

*old code*

`["#paragraph"].field_paragraph_title.value`

*new code*

`item.entity.field_paragraph_title.value`

and replace the for loop like this:

*old code*

`{% for item in content.field_paragraph_image_block %}`

*new code*

`{% for item in content.field_paragraph_image_block['#items'] %}`

Here's the new code in block--paragraph-images.html.twig, no other twigs are needed:

```
{% block content %}
    {# block fields #}
    {% set paragraph_count = content.field_paragraph_image_block['#items']|length %}
    {% set paragraph_count_css = 'grid-cols-' ~ paragraph_count %}

   <div class="block__content image-paragraph mb-0 grid gap-4  {{ paragraph_count_css }} " >

    {% for item in content.field_paragraph_image_block['#items'] %}

        {# paragraph fields #}
        {% set paragraph_title = item.entity.field_paragraph_title.value %}
        {% set paragraph_text = item.entity.field_paragraph_text.value %}
        {% set media_id = item.entity.field_paragraph_image.target_id %}

        {% set paragraph_classes  = [
            'paragraph-image-effect',
            'image-count-' ~ paragraph_count,
        ] | sort | join(' ') | trim %}

            <div class="{{ paragraph_classes }}">
               {{ drupal_entity('media', media_id, 'original_size') }}
               {{ paragraph_title }}
               {{ paragraph_text }}
            </div>
     {% endfor %}
    </div>
{% endblock %}

```

---
Tags: blocks, paragraphs
---


# Question
Title: How can I programmatically render the summary of a textfield?
I can output a textarea field with the following code:

```
$entity->fieldname->view();

```

How do I need to change that code for getting the *summary* of that field?

(Where can I find a documentation of that view-function?)

# Answer
> 6 votes
You have to use the field formatter `text_summary_or_trimmed`:

```
$build[] = $entity->fieldname->view([
  'label' => 'hidden',
  'type' => 'text_summary_or_trimmed',
  'settings' => [
    'trim_length' => 600,
  ],
]);

```

The easiest way to find the field formatter name and settings is configuring a field in a display mode of a content type and exporting the configuration.

How to find the documenation, see How to apply a Field Formatter to a node field programmatically?

---
Tags: entities
---


# Question
Title: How to show a field in a view for another field?
I have twig template named `views-view-field--banner--block_1--field-banner.html.twig` Here I print `<a href="">{{ output -}}</a>` To put an anchor tag around an image field named field\_banner. I also have another field named `field_slider_banner_link` that I want to print within the `href=""`. But I have no clue how to get the value from that other field into this template.

# Answer
> 1 votes
If the template provides a `row` variable (check the available variables in the Twig comments) and is not a table:

*views-view-field.html.twig:*

```
{{ view.field.other_field.getvalue(row) }}

```

See also How can I theme individual fields in a row?

---
Tags: theming, 9
---


# Question
Title: Is it possible to use WSL-based Drush on a Windows 10 XAMPP and if so how?
I currently use Drupal 9 but concepts about Drupal 10 may be useful.

I use Windows 10 Home with XAMPP and `C:/xampp/htdocs` is my web application root.

I want to establish a minimal Drupal development environment on my Windows 10 Home instance by installing Composer and then Drush.

I can use **WSL** to install both Composer and Drush but then a question arises:
If WSL only effects its own Linux environment, how could I use WSL-based Composer and Drush to effect the XAMPP Windows environment?

# Answer
> 3 votes
Let's think about what is actually going on here.

With XAMPP, you are basically running an Apache server inside a Windows program.

With WSL v1, you have a Linux virtual machine running within Windows that has drush, composer, etc.

With WSL v2, you have Linux running in Hyper-V (MS hypervisor), so you get near-native Linux performance with less virtualization overhead.

So, basically the question becomes "How do I access a server running in a Windows environment from a Linux environment inside the Windows environment?"

Depending on how comfortable you are with firewalls and proxies and things, and depending on how your computer is already set up, configuring this may not be too hard-- but it could also be a real mess.

**composer**

For `composer`, you just need access to your Windows files from within Linux.

With WSL, Windows C: drive should be mounted at `/mnt/c` in Linux. So you can just `cd` to the Windows directory that has your files from Linux and run `composer` commands.

**drush**

For `drush`, you'll need to set up aliases and connect to the XAMPP server. You may also have to open some ports in your Windows firewall, which can present a security risk. The details of this are out of scope for this site (better fit for Server Fault).

**a better solution**

As @leymannx mentioned, DDEV is a solution that provides a solid Drupal local development environment with little configuration, and I personally use lando, which has served me well for the past 5+ years. They are both free (both open source and free as in beer), and give you solid defaults; you'll probably save a lot of time not setting things up for yourself.

---
Tags: drush, 9, composer
---


# Question
Title: How to translate the layout builder blocks of a node programmatically?
I am translating the nodes programmatically. Everything works fine except the layout builder blocks.

When I try to translate it, it also changes on the source node.

I have created a node in language `en`. Now I am translating it to `nl`. Here is my code.

```
if ($node->hasTranslation($language)) {
  $translated_entity =  $node->getTranslation($language);
}
else {
  $translated_entity =  $entity->addTranslation($language);
}

$translated_layout = $node->get('layout_builder__layout')->getValue();

foreach ($translated_layout as $section) {
  /** @var \Drupal\layout_builder\Section $section */
  $section = reset($section);

  foreach ($section->getComponents() as $component) {
    $configuration = $component->get('configuration');

    $component->setConfiguration($translated_configurations);
  }
}

$translated_entity->set('layout_builder__layout', $translated_layout);
$translated_entity->save();
$node->save();

```

Is there any way to retain the original blocks as it is on the source node and the `save` function only added the changes to the translated node?

# Answer
> 1 votes
I have done it myself. Here is the solution.

You first need to copy the layout from the source node to the translated node.

Then get the layout of the translated node and translate it.

```
if ($node->hasTranslation($language)) {
  $translated_entity =  $node->getTranslation($language);
}
else {
  $translated_entity =  $entity->addTranslation($language);
}

$translated_entity->set('layout_builder__layout', $node->get('layout_builder__layout')->getValue());
$translated_entity->save();

$translated_layout = $translated_entity->get('layout_builder__layout')->getValue();

foreach ($translated_layout as $section) {
  /** @var \Drupal\layout_builder\Section $section */
  $section = reset($section);

  foreach ($section->getComponents() as $component) {
    $configuration = $component->get('configuration');

    $component->setConfiguration($translated_configurations);
  }
}

$translated_entity->set('layout_builder__layout', $translated_layout);
$node->save();

```

---
Tags: 9, layout-builder, i18n-l10n
---


title: Upgrade Devel module and disable Kint

text:
# Question
Title: Upgrade Devel module and disable Kint
When upgrading from Devel 8.x-2.x to Devel 8.x-4.x in a composer based build, how do I handle the Kint module being removed per Remove Kint module and create a kint dumper plugin in devel?

The service container can't be created because the Kint class is missing. I'll add the class path to Kint when I blow up the build again. :) Thank you.

# Answer
> 7 votes
Since Devel 4 you have to add Kint youself:

```
composer require drupal/devel kint-php/kint

```

You can read through this epic issue to learn more: Unknown "kint" function. in Twig\ExpressionParser.

---

Also important to read the release notes. On all 4.0.0+ releases the following is written. You have to do this **before upgrading**:

> If you have Kint module enabled, please run these commands before upgrading:
>
> 1. `drush pm:uninstall kint` or uninstall Kint using the Drupal UI
> 2. `composer require kint-php/kint`

---

To fix any Kint-missing-module-error, simply downgrade Devel `composer require 'drupal/devel:^2.1'`, uninstall Kint `drush pmu kint` and then upgrade again `composer require drupal/devel kint-php/kint`.

# Answer
> 1 votes
The problem was I was including

```
// Change Kint maxLevels setting.
// @see https://gist.github.com/JPustkuchen/a5f1eaeb7058856b7ef087b028ffdfeb
include_once(DRUPAL_ROOT . '/modules/contrib/devel/kint/kint/Kint.class.php');
if (class_exists('Kint')) {
  Kint::$maxLevels = 6;
}

```

in settings.local.php. I recall reading somewhere that the default maxLevels in Kint is now 6 which makes the custom code snippet unnecessary. When I removed it, removed kint from core.extension.yml (in our case config\_split.local) and added kint-php/kint via composer, all was well.

Thanks again @leymannx

# Answer
> 1 votes
If you are facing the issue.
Use the development module **4.x-dev**
If you are using the 4+ versions then use development version 4.x-dev . https://www.drupal.org/project/devel

```
$ composer require drupal/devel:4.x-dev
$ composer require kint-php/kint
$ drush en -y devel

```

Enable Twig debugging it in development.services.yml file

```
twig.config:
    debug: true
    auto_reload: null
    cache: false

```

Goto /admin/config/development/devel and
set the "Variables dumper" to "Kint"

Add {{ kint() }} into template files.

---
Tags: 9
---


# Question
Title: Route reported as not existing, but I'm not referring to it
Drupal 9.28; I removed some test code, and am now getting the error

```
Uncaught PHP Exception Symfony\Component\Routing\Exception\RouteNotFoundException: "Route "member.test" does not exist." at /Users/pglatz/dev/wdocs/wdocs-d9-code/www/web/core/lib/Drupal/Core/Routing/RouteProvider.php line 206

```

I grepped my code and there is no longer a reference to `member.test` in any of the yml files (or anywhere else). I cleared all cashes with `drush cache-rebuild`.

Using debug in phpStorm, I set a breakpoint where the error occurred and traced back, but cannot see why it is asking for this route.

Any suggestions how to get more information on where the problem is? (the error message could be a little less terse)

# Answer
I removed "member.test" from the database tables menu\_tree and router. Not the most elegant solution, but things are working now.
> 0 votes

---
Tags: routes
---


# Question
Title: Image is "broken" with Custom Email Twig Template sending with Webform
The setup consists of Drupal 8 + Webform (ver. 5.6 - https://www.drupal.org/project/webform/releases/8.x-5.6) + CKEditor Image Upload (https://www.drupal.org/project/ckeditor\_uploadimage). This allows for users to copy and paste screenshots of issues into CKEditor easily.

When the user takes a screenshot and then uses CTRL+V to paste into CKEditor - the image is uploaded to the server and it works perfectly.

The problem arises when the user right clicks within CKEditor and selects "paste" from CKEditor's right click context menu - it then embeds the image directly (data uri - eg.

```
<img data-widget="uploadimage" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAiwAA....)

```

which isn't a problem, until I the email is sent.

I'm using a Twig Template for the body of the message (it's being emailed / pushed into a ticketing system, thus the need to customize the look) and the code is the following:

```
{% set upload_screenshot = webform_token('[webform_submission:values:upload_screenshot]', webform_submission) %}

{% if upload_screenshot %}
        <p><strong>Screenshot(s):</strong></p><p> {{ upload_screenshot }}
        {# Used to try to debug why data uris weren't rendering - with webform debug it displays data uri images, but the downside is that it doesn't render regular image uploads. #}
        {#{{ webform_debug(upload_screenshot) }}#}</p>
    {% endif %}

```

If I use the "Default" template, any type of image (whether uploaded or as an embedded image) works fine. So I'm starting to think it's the way that webform\_token processes / outputs the information.

When I inspect the code in the broken image, I notice that the data: is removed from the src

```
<img data-widget="uploadimage" src="image/png;base64,iVBORw0KGg )

```

For the meantime I'm disabling the right click context menu with this module. (https://www.drupal.org/project/ckeditor\_browser\_context\_menu)

Any ideas on how I can get the images (whether uploaded or embedded) in a custom twig email template would be appreciated.

# Answer
> 0 votes
The trimmed "data:" might be considered as the protocol and not match the filter\_protocols settings in /sites/default/services.yml.

Problem with text format and base64 inline images

---
Tags: theming, webforms, emails
---


# Question
Title: The <b> tag is replaced by '*' character
While sending out html emails that are configured to use the following template.

```
<p>Submitted on [webform_submission:created]</p>
<p>Submitted by: [webform_submission:user]</p>
<p>Submitted values are:</p>
[webform_submission:values:html]

```

The actual value returned is the following one.

```
*First Name*
Bobcares
*Last Name*
Developer
*Email*
mail@example.com [1]
*Please let us know how we may help you*
Test

[1] mailto:mail@example.com

```

I would expect it would render as follows.

```
<pre>
<b>First Name</b>
Bobcares
<b>Last Name</b>
Developer
<b>Email</b>
mail@example.com [1]
<b>Please let us know how we may help you</b>
Test

[1] mailto:mail@example.com
</pre>

```

I have installed the Mail System and the SMTP Authentication Support modules, selected *HTML mails* in the latter module and in Webform.

My guess is that something is converting the HTML mails to plain text in webform, but I am not able to find it.

Could anyone point me in the right direction?

# Answer
After one more day of digging, I finally figured it out!

The issue was with the HTML Mail module, which was supposed to format the emails in HTML format, as the name said, required an Pear library, Mail Mime to format HTML mails. It was converting my HTML formatted emails into Plain Text and sending to the SMTP server.

It had nothing to do with Webform module.

I had set the sender and formatter same in the Mail System module, which apparently solved the issue.
> 1 votes

---
Tags: emails
---


# Question
Title: emailing the webform's submission values in a table
I have been trying to email the submitted values via email handler every time an user submit a form. I have added on custom body so the submitted values would be in the table formally, but the table is all broken as you can see on the photo. Is there a way to fix the problem? Thank you in advance

Here is what I added on the custom body:

```
    <table>
    <tr>
        <th>Description</th>
        <th>Account Number</th>
        <th>Current Budget</th>
        <th>New Budget</th>
        <th>Budget Change +/-</th>
    </tr>
    <tr>
        <td>
            [webform_submission:values:budget_change_request_form_01_description]
        </td>
        <td>
            [webform_submission:values:acct_]
        </td>
        <td>
            [webform_submission:values: budget_change_request_form_01_current_budget]
        </td>
        <td>
            [webform_submission:values: budget_change_request_form_01_new_budget]
        </td>
        <td>
            [webform_submission:values:budget_change_request_form_01_budget_change_]
        </td>
    </tr>
</table>

```

And this is the output of my e-mail

# Answer
> 1 votes
It looks like you have spaces in your tokens. Removing those should fix the problem, e.g. this:

```
[webform_submission:values: budget_change_request_form_01_current_budget]

```

should be:

```
[webform_submission:values:budget_change_request_form_01_current_budget]

```

---
Tags: webforms
---


# Question
Title: Can I choose specific nodes to show in a view?
I have a Drupal 9 site with a view that shows products, but I do not want to show all products, I only want to show a select few of them.

Is it possible to filter like this? Instead of showing all the products?

Ideally I'd like a UI where I can manage the products manually. E.g. if I have 5 products but only want to display Product 1 and Product 4, I can select those 2 products.

# Answer
> 5 votes
If you want to manage the products manually, i.e. not base the filter on a product field value, the Entityqueue module offers an easy solution.

1. Install the module if you don't already have it
2. Create a queue for the products at /admin/structure/entityqueue/add
3. Choose the appropriate entity type and bundle under *Entity settings*
4. Save and add some products to it
5. In your View, add a relationship to the entityqueue

Once you've done that, only the products in the queue will be in the View's results.

As a bonus, you can also control the sort order with the entity queue if needed. Just add a sort criteria for *Content Queue Position* to the View.

---
Tags: views, 9
---


# Question
Title: Overwrite a specific VBO action processed message
I am using VBO to perform bulk operations on my view. I have 2 core VBO actions and 2 custom actions.

* Publish comment
* Unpublish comment
* Publish resource
* Unpublish resource

When the *Apply action* button is clicked with none of the grid row is selected, I get this error message.

> Select one or more comments to perform the update on.

I would like to rewrite this error message as *An attachment has to be selected to perform this action*.

How can I achieve this? I am aware of `hook_views_bulk_operations_finish()`, but it doesn't overwrite a specific action.

# Answer
> 3 votes
You could try the following:

1. Define your own ViewsField plugin that extends the CommentBulkForm (that is where that message comes from)

```
<?php

namespace Drupal\your_module\Plugin\views\field;

use Drupal\views\Plugin\views\field\BulkForm;

/**
 * Defines a custom comment operations bulk form element.
 *
 * @ViewsField("custom_comment_bulk_form")
 */
class CustomCommentBulkForm extends CommentBulkForm {

  /**
   * {@inheritdoc}
   */
  protected function emptySelectedMessage() {
    return $this->t('An attachment has to be selected to perform  this action.');
  }

}

```
2. Expose your plugin to views:

```
function your_module_views_data() {

  $data['comment']['custom_comment_bulk_form'] = [
    'title' => t('Custom comment operations bulk form'),
    'help' => t('Add a form element that lets you run operations on multiple comments, with custom messages.'),
    'field' => [
      'id' => 'custom_comment_bulk_form',
    ],
  ];

  return $data;
}

```
3. Finally, overwrite (or override) your (views.view.) Comments configuration so that your existing 'Comment: Comment operations bulk form' field is forced to use your ViewsField plugin. One way to overwrite would be via drush:

```
drush cset views.view.comment \
  display.default.display_options.fields.comment_bulk_form.field \
  custom_comment_bulk_form

```

That would eventually allow you to set your own custom message:

Good luck!

---
Tags: views, 9, actions
---


title: Why is Docker needed for DDEV?

text:
# Question
Title: Why is Docker needed for DDEV?
I need to establish a Drupal development environment on Windows 10 and I consider DDEV.

I read that DDEV requires Docker but I never worked with Docker. Why is it required for DDEV and should I master Docker itself before developing Drupal on DDEV (or any similar software for that matter)?

# Answer
I would rather write this as a comment, because although I'm experienced with Docker, I never used DDEV, but I don't have enough reputation for that.

There's the How DDEV Works page in DDEV documentation which seems to answer your questions.

> Why is \[Docker\] required for DDEV\[?\]

DDEV is a high-level application which handles lifetime of various PHP development environments. Docker is a tool used to create and configure multiple virtual computers1) (Docker containers) which run services needed for a task.

So Docker is required, because it's a tool used by DDEV to do its work, because DDEV actually does't know how to create virtual computers, it manages them and theirs configurations. It's similar to an administrator who manages an OS installed in a company's computer, but the administrator does not actually create/implement the OS.

In other words:

* DDEV: my user wants a new PHP dev environment. So from their settings, I generated this configuration of multiple virtual computers. But I actually don't know how to start them, so Docker, please, could you do it for me?
* Docker: Alright, got it.

> Should I master Docker itself before developing Drupal on DDEV\[?\]

This answer is derived from the documentation, not from experience (that's why I would prefer to write it as a comment).

DDEV's main purpose is to manage Docker containers *for you* so you can focus on the higher level tasks. So the answer seems to be: no, it's not necessary, as DDEV is a layer on top of Docker. DDEV is there so you *don't have to* handle all that complicated Docker stuff.

That being said, I would recommend to learn core basics about Docker (e.g. what are Docker images and containers and what's the difference between them, how does Docker run on Windows, ...), because it might help to understand problems when something goes wrong. (This depends on how well DDEV handles issues.)

1) Note that a Docker container is not a fully virtualised machine, it's a lightweight isolated environment. It runs natively on Linux, so on Windows, there's another layer of virtualisation. But all of that is out of scope for this question.
> 7 votes

---
Tags: virtual-machine
---


# Question
Title: How to get current language in html.html.twig of theme
I need to get the current language in the html.html.twig file of my theme. In my page.html.twig I can use:

```
{% if (language.getId() == 'nl') %}

```

This does not work in my html.html.twig. Any ideas?

# Answer
> 1 votes
Add the following snippet in your .theme file:

```
function MYTHEME_preprocess_html(&$variables) {
  $variables['lang'] = \Drupal::languageManager()->getCurrentLanguage()->getId();
}

```

Then, in your html.html.twig file use:

```
{% if (lang == 'en') %}
  // Your action
{% endif %}

```

# Answer
> 1 votes
In Drupal 9 the answer is this:

```
{{ node.langcode.langcode }}

```

---
Tags: 8, theming
---


# Question
Title: How can I remove a theme that is no longer in core?
Drush/Drupal 8 is throwing errors because a theme is 'enabled' that is 'missing'. The theme is/was part of core (`test_stable`), and I'm having difficulty getting it to uninstall.

I understand that the theme code needs to be there in order to uninstall, but this being core makes that difficult. I can manually place the module there locally, but would need to create a patch to actually have it installed (and then uninstalled) on the remote environments via composer.

The "Module Missing Message Fixer" module addresses this scenario with modules, but not themes.

I'm pretty sure enabling this theme in the first place was an accident. I'm hoping someone can help me determine if there is a way to do this w/out creating a patch that installs this old theme.

# Answer
> 8 votes
You can create a theme calling it *test\_stable*. Then, you clear the cache with `drush cr` and uninstall the theme with `drush theme:uninstall test_stable`. It will solve your problem.

You don't need to create the whole theme; the *test\_stable.info.yml* file is sufficient for Drupal to recognize the theme as present.

As the *test\_stable* theme has been removed from Drupal after Drupal 8.7.x, and that file isn't present in latest versions, before proceeding with what I suggested, I would run `drush updbst` and check for pending updates.

# Answer
> 5 votes
I had this issue :

> The base theme stable cannot be uninstalled, because theme classy depends on it.

I solved it without install a fake theme. I simply executed these 2 Drush Commands :

```
drush theme-uninstall classy

drush theme-uninstall stable

```

---
Tags: 8
---


# Question
Title: Missing module error while running unit test
I am trying to run a unit test for one of my contributed modules in my local development environment. But it keeps throwing an error:

```
$:/path/to/web$ sudo -u www-data -E phpunit -c core/phpunit.xml profiles/abc/modules/contrib/entity_clone/tests/src/Functional/EntityCloneContentTest.php
PHPUnit 6.5.9 by Sebastian Bergmann and contributors.

Testing Drupal\Tests\entity_clone\Functional\EntityCloneContentTest
F                                                                   1 / 1 (100%)

Time: 8.49 seconds, Memory: 4.00MB

There was 1 failure:

1) Drupal\Tests\entity_clone\Functional\EntityCloneContentTest::testContentEntityClone
Unable to install modules entity_clone, block, node, datetime due to missing modules entity_clone.

/path/to/web/core/lib/Drupal/Core/Test/FunctionalTestSetupTrait.php:481
/path/to/web/core/tests/Drupal/Tests/BrowserTestBase.php:578
/path/to/web/core/tests/Drupal/Tests/BrowserTestBase.php:406
/path/to/web/core/modules/node/tests/src/Functional/NodeTestBase.php:33
/path/to/web/profiles/abc/modules/contrib/entity_clone/tests/src/Functional/EntityCloneContentTest.php:50

FAILURES!
Tests: 1, Assertions: 1, Failures: 1.

```

Any idea what is wrong here? I have tried with a few other modules also, same error. Do I have to do anything additional to add my profiles in the phpunit.xml?

BR/Pratip

# Answer
> 1 votes
We ran into the same issue with the 'cookies\_etracker' submodule of 'etracker'.

I guess this happens, if you have a submodule AND a composer.json in your main module (not auto-generated by Drupal). Then I guess the dependencies for the tests are not auto-generated, while Drupal.org does it if no composer.json is present in the repo.

Someone had a similar problem described here: https://www.drupal.org/forum/support/module-development-and-code-questions/2018-06-21/sub-module-dependencies and here https://github.com/acquia/coding-standards-php/issues/6

I think it's a bug / conflict in the Drupal.org Testbot: https://www.drupal.org/project/drupalci\_testbot/issues/3250126

Currently the only way to solve this is to remove the composer.json from the parent module entirely (which might not be wanted in most cases).

---
Tags: 8, testing
---


# Question
Title: How do I export a list of users into an excel spreadsheet in Drupal 9
I'm using a Drupal 9 website and would like to export a list of the users into an excel spreadsheet. Would using the Views data export module be the best way to achieve this?

# Answer
Assuming you are willing to use drush: Create a PHP script, named something like users\_to\_csv.php

```
<?php

$fields = [
            'name',
            'mail',
            'langcode',
            'preferred_langcode',
            'timezone',
            'created',
            'changed',
          ];

$users = \Drupal::entityTypeManager()
            ->getStorage('user')
            ->loadByProperties([
              // some properties here if you care to restrict the users list
            ]);

foreach ($users as $user ) {

  foreach ($fields as $field) {

    echo $user->get($field)->getValue()[0]['value'] . ', ';

  }

  echo PHP_EOL;

}

```

Then run it with

```
drush php:script users_to_csv.php > users.csv

```

The fields list is up to You.
> 2 votes

# Answer
If it's a quick on-off, you could write a simple View and highlight and copy (Control C) the Users list on the page to a text file, or use Views Data Export and export as a CSV.
> 1 votes

---
Tags: importing-exporting, 9
---


# Question
Title: Adding an "Accept Terms" checkbox on User Registration form
I need to add an "Accept terms and conditions" checkbox onto a user registration form. What is the best way to do this?

Also, it seems odd to me that there is no easy way to use radio buttons nor checkboxes on the User Registration form at admin/config/people/accounts/fields. Select lists are awkward, especially for multi-select lists on a mobile device.

Is there a way to output the list fields as radio buttons and checkboxes?

# Answer
Just add a required boolean field on the User entity (like literally just add this via admin, no code needed). Position it in the Registration form display (see Manage Form Display), but hide it in the view display (i.e. Manage Display). You can use the field help text as fine print.
> 5 votes

---
Tags: forms, 9
---


# Question
Title: Is there a way to duplicate existing fields instead of manually creating new ones?
I am using Drupal 9 and I have a template which will require 40 text fields and 20 image fields.

They are meant to display 20 individual products, so they are all similar. The display would be something like this -

Product Title 1 Product Thumbnail 1 Product Subtitle 1

Product Title 2 Product Thumbnail 2 Product Subtitle 2

And so on for 20 products.

To add this field manually will take a very long time since it's 60 fields. Is there a module or some other way to duplicate existing fields?

# Answer
> 3 votes
If you have 20 products, you have 20 things. In Drupal-speak, you have 20 entities.

In Drupal, every "thing" is an entity-- pages (nodes) are entities, and comments are also entities.

Each "thing" should be its own entity type. Drupal provides a lot of tools for linking different entities (such as Entity Reference module) and displaying entities (such as Layout Builder module and Views module). But, all of these tools assume that **each "entity" is representing a single thing**.

So, if you put 20 products in one entity (node/page), you will prevent yourself from using most of Drupal's features that make it a great CMS.

Instead, I suggest making a custom content type, **Product**. You can add just three fields to the product:

* Title
* Thumbnail
* Subtitle

Next, create 20 products by adding content of your new content type **Product**.

Then, create a view using the Views module. This will give you great control over how the products are displayed-- you can make a simple list of products to start, and if you want to expand it later, you can show related products and do many other cool things.

---
Tags: entities, 9
---


# Question
Title: Display a pager on the top and bottom of view pages but only on the bottom of view blocks
For a project running on Drupal 9.2.9, I want pagers on the top and bottom of view pages. I have it working on pages by an edit to a custom views-view.html.twig in the theme (using the full pager option in the Views display). Unfortunately, this resulted in double pagers on blocks using minipager also.

I think I need a little conditional logic in the views-view.html.twig template to check for `if … is full pager` versus `if … is mini pager`, or `if … is page` vs. `if … is block`. How can I achieve that?

Maybe, a better approach is a template for full pager and a different one for mini pager, but I don't understand how all these templates work together to use that approach.

# Answer
> 3 votes
Views provides theme suggestions, one of them keys off of the display type (e.g. page, block, etc.). Override the suggestion for pages (`views-view--page.html.twig`) and copy `{% if pager %}{{ pager }}{% endif %}` to wherever you want on top of the view. This will only apply to Page displays of a view, and nowhere else.

Refer to `views-view.html.twig` for the default markup of this template. The default placement of `{{ pager }}` is after the rows.

# Answer
> 3 votes
See Views template files for details on how views templates can be overridden. To quote from that page:

> All views templates can be overridden with a variety of names, using the view, the display ID of the view, the display type of the view, or some combination thereof.

So in your case, you probably want to have different templates for your views block and your views page.

These links could also help you better understand how template suggestions work, especially in the context of views:

Also Locating Template Files with Debugging can help you to enable twig debug and get information on the available template suggestions in your specific case.

---
Tags: views, theming
---


# Question
Title: How do I switch user account in drush to test permissions?
I'm playing around with the D9 Groups module and I want to test the access control in drush, either using drush php or writing a script and using drush scr.

In drush 8 I would always use drush -u to run as a specific user but that option seems to have disappeared in drush 10.

What's the easiest way to either run drush as a specific user or switch the user in drush php or a script?

Edit: I'm working around this by making calls to json:api endpoints instead but it would still be nice to validate this in drush.

# Answer
> 0 votes
Hi In your test you could use account switcher service @ `core/lib/Drupal/Core/Session/AccountSwitcherInterface.php`

For example,

```
// You can switch to any type of account here.
$this->accountSwitcher->switchTo(new UserSession(['uid' => 1]));

// Using try-catch-finally we make sure we be never leave it by accident.
try {
  // Whatever you want to test
}
catch (\Exception $e) {
  $this->logger->get(self::MODULE_NAME)->error($e->getMessage());
} finally {
  // Making sure we always switch back. Very important if you using u1.
  $this->accountSwitcher->switchBack();
}

```

---
Tags: drush, 9
---


# Question
Title: Subsequent migrations take long time to being importing data to destination
I've got a pretty large migration set of roughly 200k users. The first time I run the migration (via drush), or after rolling it back and starting again, the rollback+import starts immediately. By this I mean that the progress bar starts showing progress on importing items right away.

I know there's no way around the migration itself taking a long time due to the number of items, but I'm running into an issue on subsequent runs where, before the data actually starts importing into the destination, the migration just sits there, seemingly without doing anything, for an insane amount of time. By subsequent runs, I mean any run of the migration that is not the first run, or the first run after a rollback. So, a migration that is executed either to pull in additional users or is run after the initial one hits an error.

If I add `--feedback=x`, I do see a console message of `Processed 0 items (0 created, 0 updated, 0 failed, 0 ignored) - continuing with 'upgrade_d7_user'` every so often, so I know it must be doing *something* and updating after that number of items, but I don't know what it is. It seems like we are just waiting for it to "take a look" at every item before processing it, which does not happen on an "initial" run, and I'd guess is basically doubling how long the run will take. I guess my questions are:

* What exactly is the migration even doing at this point? Is it just doing some sort of data verification?
* Is there some way to bypass this step and just jump directly into processing the data itself? We're already looking and days to run this single migration and this extra time is pretty debilitating.

# Answer
I think what's happening here is that even though the migration has already been run once, each subsequent run will trigger the `prepareRow()` and `hook_migrate_prepare_row()` implementations for every row of the migration. Regardless of whether it has already been imported or not. Check out `\Drupal\migrate\Plugin\migrate\source\SourcePluginBase::next` to see where this happens. Basically, the source plugin runs a query and builds an array of rows to migrate. Then iterates over each one and *skips* the ones that have already been imported. But not before first calling the prepare row implementations.

When you're migrating Users, or any kind of fieldable entity, the source plugin (`\Drupal\user\Plugin\migrate\source\d7\User` in this case) likely extends `\Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity` and calls the `\Drupal\migrate_drupal\Plugin\migrate\source\d7\FieldableEntity::getFields` method. See `\Drupal\user\Plugin\migrate\source\d7\User::prepareRow` for example. This runs a query, once for every row, to see if the source entity has any fields associated with it. And I'm guessing running this query 200k+ times is pretty slow. And is what causes subsequent runs to take a long time.

One way around this is to use a high water mark

What this will do is modify the query the source plugin runs to build the array that it loops over so that it only returns values that are above the high water mark. And the array won't get populated with a bunch of rows that have already been imported. And the subsequent runs should be much faster because it's only processing *new* rows.
> 1 votes

---
Tags: migrations, 9
---


# Question
Title: How to make the private image accessible with image style?
I have a private image with this URL.

```
http://mystite.com/system/files/images/IMG_0371_24.jpg/IMG_0371_24.jpg

```

An image style is created for the above image on location

```
http://mysite.com/system/files/styles/square/private/images/IMG_0371_24.jpg/IMG_0371_24.jpg

```

The problem is when I display the original image, it works fine. But when I display the image with style, the image is not displaying and in the console, I get 404.

When I try to access the original image through the browser, I can access the image. But when I try to access the image with style in the browser, I get the `The requested page could not be found`.

I can confirm the image is present in the specified location. But don't know what is the issue.

Can anyone tell what can be the issue?

# Answer
I found the solution.

Actually, the problem is that the image style URLs need an `ITOK` at the end of the URL.

So for that, I used the `buildUrl` function from the image style.

```
$image_style_url = $image_style->buildUrl($original_image_uri);

```

Now this gives a URL like this

```
http://mysite.com/system/files/styles/square/private/images/IMG_0371_24.jpg/IMG_0371_24.jpg?itok=p2-MBbc

```

And now with that URL, I can access the image with an image style.
> 0 votes

---
Tags: files, 9
---


title: Add default value to existing field

text:
# Question
Title: Add default value to existing field
I have tried to add default value to an existing field using `hook_form_alter()` but it does not work.

Below is the html of the fields

```
<fieldset class="js-form-item js-form-type-textfield form-type-textfield js-form-item-order-fieldscheckout-field-my-fieldname-0-value form-item-order-fieldscheckout-field-my-fieldname-0-value form-group" style="display: block;">
  <label for="edit-order-fieldscheckout-field-my-fieldname-0-value">field Label</label>
  <input class="js-text-full text-full form-control" data-drupal-selector="edit-order-fieldscheckout-field-my-fieldname-0-value" type="text" id="edit-order-fieldscheckout-field-my-fieldname-0-value" name="order_fields:checkout[field_my_fieldname][0][value]" value="" size="60" maxlength="9" placeholder="">
</fieldset>

```

Below is the code that I tried to set default value in the field

```
function module_name_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'commerce_checkout_flow_multistep_default') {
    $form['field_my_fieldname'][LANGUAGE_NONE][0]['value']['#type'] = 'hidden';
    $form['field_my_fieldname']['widget'][0]['value']['#value'] = 1;
    // Tried to add class attribute but not working
    $form['field_my_fieldname']['#attributes']['class'][] = '123456789';
  }
}

```

# Answer
> 1 votes
I could make your code work like this:

```
function module_name_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'commerce_checkout_flow_multistep_default') {
    $form['field_my_fieldname']['widget'][0]['value']['#type'] = 'hidden';
    $form['field_my_fieldname']['widget'][0]['value']['#value'] = 1;
    $form['field_my_fieldname']['widget'][0]['value']['#attributes']['class'][] = '123456789';
  }
}

```

Note that `LANGUAGE_NONE` is Drupal 7 specific and won't work in Drupal 8 and newer.

---
Tags: 8, forms
---


# Question
Title: How to not split select list by content type
This is about the regular `select` widget that you can choose in the `Manage form display` page.

If this widget is linked to an `entity_reference` field allowing several bundles to be selected; then you end up with an `#options` populated as follow:

```
_none -> "None"
Bundle label 1 ->
  id1 -> "label of ID 1"
  id3 -> "label of ID 3"
  id4 -> "label of ID 4"
Bundle label 1 ->
  id5 -> "label of ID 5"
  id6 -> "label of ID 6"

```

I would like to have

```
_none -> "None"
id1 -> "label of ID 1"
id3 -> "label of ID 3"
id4 -> "label of ID 4"
id5 -> "label of ID 5"
id6 -> "label of ID 6"

```

Is there any option to change? or should I hook something?

# Answer
> 4 votes
It would be nice if this were optional, but ...

You will have to write a `hook_form_alter` or similar to rewrite/reorganize the options in the field: They're organized in logically obvious subarrays matching what you see on screen. You can "flatten" them into a single array and re-order the options as you please.

---
Tags: forms
---


# Question
Title: How to alter the view behind a select widget in a regular node edit form
I have an entity\_reference field in a content type: `field_node_ref`

In the field definition, it can reference all the nodes of a given type.

The widget used for this field is a `select` widget

Depending the context, in the node edit form, I would like to use different views to populate the `#options` of the `select` widget.

Ex:

Context A --\> View A will be used

Context B --\> View B will be used

The context is calculated in my business logic (I speak about it to show that multiple views can be used and then, it can't be encoded in the field definition)

In `my_module_form_alter` the `#options` are already populated and I can't update the select widget array to populate them with a custom view. I assume, I have to hook before, but I don't know how.

# Answer
You can create a customized selection for an entity reference field by setting an Entity Reference display of a view as the source.

To do this, create a view with an Entity Reference display. Construct that view like you normally do (select what fields to render, the basic filters, sorts, limits, etc.). Then create a custom contextual filter, grab the context, inject needed service classes, use your business logic on it, and then apply that contextual filter to the view.

In most cases, you build a filter against the ID of the entity, and your filter's job is to find out if that item should be shown or suppressed. Drupal's built in "Content ID from URL" and "Taxonomy term ID from URL" are examples of these kinds of filters. Your filter will just need to incorporate more logic than just comparing IDs.

Then on the entity reference field settings, change the **Reference method** to **View: Filter by an entity reference view**.
> 2 votes

---
Tags: entities, forms
---


# Question
Title: Some image styles not generating while other are
I'm seeing a strange issue where some of our image styles seem to be broken while others work fine. The broken ones are showing the typical signs of the source image existing while the image style url used on the page is broken. I can't seem to find any consistencies -- similar effects are used on working and broken styles, and some broken ones are defaults (thumbnail) while others are customized. Quite odd.

Any ideas what might cause this? Site is running D9. I'm hesitant to purge the image styles in case it doesn't work and we end up with even more broken images.

# Answer
> 0 votes
The solution ended up being needing to enable mod\_rewrite as described in Image styles do not work. No idea why some images were generating fine while others weren't, as it seems like all should be affected equally but, in either case, the issue was resolved all around by enabling mod\_rewrite.

---
Tags: media
---


# Question
Title: What is the use of Drupal.settings.ajaxPageState object?
I am working on a Drupal site on which a functionality breaks because the value of `Drupal.settings.ajaxPageState.js` gets reset to an empty array instead of an object containing the list of js files.

So I want to know what exactly is the use of this **`ajaxPageState`** object

# Answer
The `ajaxPageState` object is used to collect already loaded theme assets (css, js files in Drupal 7, libraries in Drupal 8 and later) and pass that on to Drupal when doing AJAX requests, so that assets that have already been loaded are not loaded again. It also holds information about the theme currently in use, so that rendered results of AJAX requests can use the same theme.

See where it's used in Drupal 7:
https://git.drupalcode.org/project/drupal/-/blob/7.x/misc/ajax.js#L348

And in the current Drupal 9:
https://git.drupalcode.org/project/drupal/-/blob/9.3.x/core/misc/ajax.es6.js#L783

Resetting `ajaxPageState` to an empty object or array will definitively have surprising effects on all features that rely on AJAX requests, as it basically means a lack of context for the theme logic on the server side.
> 2 votes

---
Tags: 7, ajax, javascript, theming
---


# Question
Title: Update node and all translations programmatically
I need to add tags as taxonomy terms to already created nodes in 7 languages.

If I do this:

```
$node = Node::load($nid);
$node->set('field_tags', getTerms($terms));
$node->save();

```

Just default node in English is updated, however, all terms are created in all languages.

*getTerms() - is my own function, which is getting term ids and creating them if they don't exist.*

I need to update all node translations. But how?

Tried this:

```
foreach (getLanguages() as $key => $value) {
  $node_translation = $node->addTranslation($key, $node->toArray());
  $node_translation->set('field_tags', getTerms($terms));
  $node_translation->save();
}

```

Gives me this error: `[error] Invalid translation language (ru) specified.` But 'ru' language is active.

*getLanguages() - return array of all languages. The same function is used to create nodes and terms and it's working fine there.*

How to **update** a node and all its translations?

# Answer
Finally found the right solution to update node translation programmatically:

```
if ($node->hasTranslation($key)) {
  $translation = $node->getTranslation($key);
  $translation->set('field_tags', $terms);
  $translation->save();
}

```

$key - language tag, for example 'en', 'es', 'ru', etc.
> 0 votes

---
Tags: 9
---


# Question
Title: How can I remove default image from image fields?
I need to create an image field with a default value, which must also be nullable on single content entities. Contrary to text fields or entity reference fields, I was unable to remove this default value on single content entities.

E.g. I can create a text field with default value "Lorem ipsum". On node creation, the field is prefilled with that text, but I can also delete that text and the field will stay empty.

But on image fields, there is no button/option to remove the default value at all. I can remove an override image, but not the default one. Even after uploading a non-default image, storing, and then removing that image again, the default value kicks in again.

How can I make the image field "nullable"?

Note that I can not use media entity references, because I must support SVG and those images also must not leak into the reuseable global media pool.

# Answer
Actually default image does not cause any data save but it affects image formatter so if it finds no values for image field, then it displays the default image which is set in field settings.

you can check in DB or simply create a content with default image A.png and then go to field settings and change the default image to B.png, and when you display your node you will see that B.png will shown in content.

So if you don't want to see the default image in some cases you can duplicate default image formatter and do whatever you like.

and if you really want to save a data for image field with default value, you can do it by altering node form like below:

```
function my_module_form_node_article_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  foreach (array_keys($form['actions']) as $action) {
    if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
      array_unshift($form['actions'][$action]['#submit'], 'my_module_test_form_submit');
    }
  }
}

function my_module_test_form_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  $image = $form_state->getValue('field_image');
  if (empty($image[0]['fids'])) {
    $form_state->setValue('field_image', $form['field_image']['widget'][0]['#default_image']['fid']);
  }
}

```
> 5 votes

---
Tags: entities
---


# Question
Title: Adding theme JS library in custom module
My theme **documention.libraries.yml** file is defined as follows :

```
global-styling:
  version: VERSION
  css:
    base:
      styles/dist/styles.css: {}
tocbot:
  js:
    libraries/tocbot/tocbot.js: {}
    js/tocInit.js: {}
  css:
    layout:
      libraries/tocbot/tocbot.css: {}
layout_tweaksLib:
  js:
    js/layout_tweaks.js: {}

```

My custom module implements a custom template which also requires the theme functionality defined in **tocInit.js**. So I'm trying to include the tocbot library from my theme in my module.

I have tried including a dependencies clause in **my\_module.libraries.yml** file, resulting in the following :

```
my_module:
  js:
    js/my-module.js: {}
  dependencies:
    - documentation/tocbot
  css:
    component:
      css/my-module.css: {}

```

However, the *tocInit.js* script is not being loaded on the modules' custom template.

I would appreciate some help, please.

# Answer
> 0 votes
From `documentation.libraries.yml`, extend the module's definition of the `my_module` library to include `documentation/tocbot`'s assets using `libraries-extend`.

```
# documentation.libraries.yml
libraries-extend:
  my_module/my_module:
    - documentation/tocbot

```

---
Tags: theming, javascript
---


# Question
Title: Adding a class to an image using preprocess function
I am having trouble adding a class to an image using a preprocessor function in Drupal 9. Specifically, I only want certain images to have that class added. The image is being added using paragraphs.

I've tried a few variations of the following and cannot seem to get class added. I've also tried using `['#item']` but it causes an error.

```
function confluence_preprocess_field__paragraph__field_card_image(&$variables) {
    foreach($variables['items'] as $key => $item){
        $variables['items'][ $key ]['content']['item']['class'] = 'card-img-top';
    }
}

```

# Answer
> 0 votes
You can add it via the content's `#item_attributes` array like so:

```
foreach($variables['items'] as $key => $item){
  $variables['items'][$key]['content']['#item_attributes']['class'][] = 'card-img-top';
}

```

---
Tags: theming, hooks
---


title: How to load theme style(s) in CKEditor?

text:
# Question
Title: How to load theme style(s) in CKEditor?
In Drupal 8, how can you have CKEditor load additional stylesheets when using a configured filter format? In Drupal 7, you could give the WYSIWYG module paths to CSS sheets to load, which made the editor text reflect the theme as much as possible. I am not seeing this option.

# Answer
> 15 votes
Here is one way to do it... not sure if there are others (admin based):

```
use Drupal\editor\Entity\Editor;

/**
 * Implements hook_ckeditor_css_alter().
 *
 * Injects our CSS sheets anytime CKEditor has loaded.
 *
 * @param array $css
 * @param Drupal\editor\Entity\Editor $editor
 */
function mymodule_ckeditor_css_alter(array &$css, Editor $editor) {
  if (!$editor->hasAssociatedFilterFormat()) {
    return;
  }

  $known_formats = [
    'basic_html',
    'full_html'
  ];

  if (in_array($editor->getFilterFormat()->id(), $known_formats)) {
    $css[] = drupal_get_path('theme', 'mytheme') . '/build/css/style.css';
  }
}

```

# Answer
> 14 votes
Unless you want to load styles for specific formats, you can easily add CSS within your `MODULE.info.yml` file, like so:

```
ckeditor_stylesheets:
  - css/application.css
  - css/ckeditor.css

```

Use `@import` statements inside one of the stylesheets to pull in external stylesheets not in your theme:

```
/* in css/ckeditor.css */
@import url('//mycdn.com/myfonts.css');
@import url('/path/to/drupal/module/styles.css');

```

# Answer
> 7 votes
Here is a simple solution for this in Drupal 8, when you are using a custom theme or custom admin theme.

1. Open your custom theme info file **\*.info.yml** and add the line above `libraries` or below `base_theme`.

```
ckeditor_stylesheets:
  - css/ckeditor.css

```
2. Create a file **ckeditor.css** in the `css/` directory.
3. Write your CSS in that file and the styles will be applied to CKEditor.

# Answer
> 0 votes
You can add custom CSS with something like this. You can add your custom CSS to `editor.css`.

```
use Drupal\editor\Entity\Editor;

function MYMODULE_ckeditor_css_alter(array &$css, Editor $editor) {
  $css[] = drupal_get_path('module', 'MYMODULE') . '/ckeditor/moono_dark/editor.css';
}

```

This page was one of the top hits for theming a Drupal CKEditor skin too

I was able to change the skin with this code from Drupal.org. You can load Moono Dark with something like this. You can put it in your custom module's `.module` file.

You will have to change the URL below based on where you download the skin, but you get the idea.

```
function MYMODULE_editor_js_settings_alter(array &$settings) {
  foreach (array_keys($settings['editor']['formats']) as $text_format_id) {
    if ($settings['editor']['formats'][$text_format_id]['editor'] === 'ckeditor') {
      $settings['editor']['formats'][$text_format_id]['editorSettings']['skin'] = 'Moono Dark,https://www.example.com/modules/custom/MYMODULE/ckeditor/moono_dark/editor.css';
    }
  }
}

```

https://www.drupal.org/docs/8/api/ckeditor-api/overview

---
Tags: 8, wysiwyg
---


# Question
Title: Is it possible to add an entity to the current route parameters?
Using `\Drupal::routeMatch()->getParameter()`, it's possible to fetch objects that come from the parameters of the URL.

I'm wondering if it is possible to add values to the routeMatch. For example, if using the Groups module, nodes may be part of a group, however the group is not part of the path. Is there a way to load the group from the node, and add the group to the parameters that can be retrieved with `\Drupal::routeMatch()->getParameter()`?

Or, more broadly, I'd like to set the $group to be part of the "context" of a page request on a node page.

# Answer
> 2 votes
To use it in a block you could create a custom `route.node_group` context which gets the context from the route match. Hierarchically you have to place it under the `route` context. When merging contexts, for example if the context bubbles up to the page level, `route` can replace `route.node_group`.

---
Tags: 9, group
---


# Question
Title: How do I get the current path alias or path?
How can I get the current alias and/or path in Drupal 8?

In Drupal 7 I did this with `drupal_get_path_alias()`. What is the equivalent code I should use in Drupal 8?

# Answer
Some of the other answers were only correct during previous alpha/beta versions of **Drupal 8**, or seemed to be incomplete. As of beta7 (and hopefully permanently), the following rules should apply:

For the current raw **path** (the un-aliased **Drupal** path):

```
$current_path = \Drupal::service('path.current')->getPath();

```

For the current **URI**, which is pretty-much a direct representation of the request (it may even include a query string):

```
$current_uri = \Drupal::request()->getRequestUri();

```

There is of course no guarantee that this `$current_uri` value will give you an alias, even if one is available for the request, as it only represents what the user has requested. So to strictly do what you are asking about (get alias if available, and path if not) I think you could do:

```
$current_path = \Drupal::service('path.current')->getPath();
$result = \Drupal::service('path_alias.manager')->getAliasByPath($current_path);

```

Of course, depending on the type of processing you are doing it may be best to be working with routes instead of paths, but I suppose that's a whole other topic.
> 169 votes

# Answer
The proper way for the url without the URL alias.

```
\Drupal::request()->attributes->get('_system_path');

```

For the URL with alias:

```
\Drupal::request()->getRequestUri();

```
> 40 votes

# Answer
In Drupal 8 you can do this with Twig:

```
{{ url('<current>') }}

```

example:

```
<a href="{{ url('<current>') }}">{{ 'Reload'|t }}</a>

```

from: https://www.drupal.org/docs/8/theming/twig/functions-in-twig-templates
> 30 votes

# Answer
For getting the current path in Drupal 7, you use to use `current_path()`, but in Drupal 8 you use `$url = Url::fromRoute('<current>');`.

Source: https://www.drupal.org/node/2382211
> 20 votes

# Answer
To get current path (aliased path):

```
// Returns something like /about
$url = \Drupal\Core\Url::fromRoute('<current>');

```

To get current path (system path):

```
// Returns node/1
$path = $url->getInternalPath();

```
> 13 votes

# Answer
To get full current url not just the path (Drupal 8), this is the cleanest solution I was able to find:

```
Url::fromRoute('<current>',array(),array('absolute'=>'true'))->toString();

```
> 10 votes

# Answer
In Twig template / Drupal 8 :

**URL of the current page**

```
{{ url('<current>') }}

```

**only PATH**

```
{{ path('<current>') }}

```

See: https://www.drupal.org/docs/8/theming/twig/functions-in-twig-templates
> 9 votes

# Answer
If you want the absolute URL with the querystring too:

```
use Drupal\Core\Url;
// ...
Url::fromRoute('<current>', [], ['query' => \Drupal::request()->query->all(), 'absolute' => 'true'])->toString();

```
> 5 votes

# Answer
Get the current route name:

```
$current_route = \Drupal::routeMatch()->getRouteName();

```

Get current query parameters (upscaled):

```
$current_parameters = \Drupal::routeMatch()->getParameters();

```

Get current URL as an object of type `Drupal\Core\Url`, which requires the query parameters to be an array of values rather than upscaled objects

```
use Drupal\Core\Url;

$url = Url::fromRoute(\Drupal::routeMatch()->getRouteName(), \Drupal::routeMatch()->getRawParameters()->all());

```
> 2 votes

# Answer
Since Drupal 8.8.0, the path.alias\_manager has been deprecated in favor of the new service path\_alias.manager (see the change record.)

Accordingly, you can get the current path alias this way:

`$current_path = \Drupal::service('path.current')->getPath();
$alias = \Drupal::service('path_alias.manager')->getAliasByPath($current_path);`
> 2 votes

# Answer
To get the full current Url it is best to use this:

```
$current_url = \Drupal::request()->getUri();

```

`$current_url` will look something like this:

```
http://example.com/my-current-page.html?query_var1=1&query_var2=2

```
> 1 votes

---
Tags: 8, path-aliases
---


# Question
Title: How to stop duplicates caused by date range in views
On my site I have a content type called Course. Courses can have several sessions. To display these sessions I am using the date range.

When a course has more than one date range entered an instance appears in the view for each start date.

How do I only display one instance for each course? There is only one course, even though there are multiple sessions.

The Distinct option in Query settings doesn't resolve this, nor does using Aggregation

# Answer
> 1 votes
I've found an answer to this.

To only display the first instance of each Course I needed to add a new filter to the view for **field\_date\_range:delta** and change the Operator to **Is equal to Value 0**.

Each Course session date range is assigned a delta number in the database. This new filter makes sure that only the first one is displayed in a view. What does Delta mean in Drupal

---
Tags: 8, views
---


# Question
Title: drupalcommerce/project-base prohibits upgrade to Drupal 9.2.4
I'm running into composer errors while trying to update a Drupal Commerce site to Drupal 9.2.4.

I'm not sure how to interpret this output when I try `composer prohibits drupal/core 9.2.4`

results: https://pastebin.com/EWaDQejD

eg: drupal/core 9.2.4 requires twig/twig (^2.12.0) drupalcommerce/project-base - does not require twig/twig (but v1.44.4 is installed)

Not sure what to do next. Also I can't upgrade admin\_toolbar as it's not compatible (accord to Composer) with Commerce Base. Seems to be related.

Tried upgrading commerce base: `composer require drupalcommerce/commerce_base:9.x-dev` but no love.

It used to be 1.x-dev.

Some instructions on how to update a Drupal 8 Commerce site (installed with composer as instructed) would be helpful.

Thank you for any advice!

# Answer
Here's how I managed to upgrade from 8.9.20 to 9.2.9

You need to add to your composer.json :

```
"repositories": {
  "drupal": {
    "type": "composer",
    "url": "https://packages.drupal.org/8"
  },
  "commerce_base": {
    "type": "vcs",
    "url": "https://github.com/drupalcommerce/commerce_base"
  },
  "asset-packagist": {
    "type": "composer",
    "url": "https://asset-packagist.org"
  }
},

```

You can find it here line 17 https://github.com/drupalcommerce/project-base/blob/8.x/composer.json#L17

The answer was here : https://github.com/drupalcommerce/commerce\_base/issues/5

I hope it helps you.
> 0 votes

---
Tags: commerce, composer, 9
---


title: How to validate a paragraph field?

text:
# Question
Title: How to validate a paragraph field?
I have a paragraph type with 2 fields: year and quarter

I have a content type with a paragraph field (`field_year_and_quarter`) targeting ONLY this paragraph type

I am trying to create a constraint to disallow the encoding of a duplicate (same year/quarter)

I have tried:

1-A constraint at the node level which is looping into `field_year_and_quarter` with `$node->get('field_year_and_quarter')->referencedEntities()` to check if any duplicate

=\>This is not working as it is not taking into account what is encoded in the widget, only the last saved version is checked

2-A constraint at the paragraph level which is getting its Parent to be able to loop into `field_year_and_quarter` with `$node_parent->get('field_year_and_quarter')->referencedEntities()` to check if any duplicate \[I replace one item by the paragraph provided in the parameter \]

Here is the code:

```
  public function validate($certificate_p, Constraint $constraint) {
    /* @var \Drupal\paragraphs\Entity\Paragraph $certificate_p */
    if ($certificate_p->bundle() == 'qoc') {
      $prod_company = $certificate_p->getParentEntity();
      $certificates = $prod_company->get('field_year_and_quarter')
        ->referencedEntities();
      $all_certificates = [];
      foreach ($certificates as $certificate) {
        // use the paragraph provided in the function parameter
        $certif_to_check = ($certificate_p->id() == $certificate->id()) ? $certificate_p : $certificate;
        $year = $certif_to_check->get('field_qoc_year')->value;
        $quarter = $certif_to_check->get('field_qoc_quarter')->value;
        // Year/Quarter are already encoded
        if (isset($all_certificates[$year][$quarter])) {
          $this->context->addViolation($constraint->duplicate_certif, [
            '%quarter' => surround_by_nbsp($quarter),
            '%year' => surround_by_nbsp($year),
          ]);
          break;
        }
        $all_certificates[$year][$quarter] = TRUE;
      }
    }

```

=\>This is not working for the same reason

3- A constraint at the field level... here is the code:

```
  public function validate($items, Constraint $constraint) {
    $certificates = $items->referencedEntities();
    $all_certificates = [];
    foreach ($certificates as $certificate) {
      $year = $certificate->get('field_qoc_year')->value;
      $quarter = $certificate->get('field_qoc_quarter')->value;
      // Year/Quarter are already encoded
      if (isset($all_certificates[$year][$quarter])) {
        $this->context->addViolation($constraint->duplicate_certif, [
          '%quarter' => surround_by_nbsp($quarter),
          '%year' => surround_by_nbsp($year),
        ]);
        break;
      }
      $all_certificates[$year][$quarter] = TRUE;
    }
  }

```

=\>Not working for the same reason

What should I do? (I have also tried to validate in the form without luck)

# Answer
OK, looking at the ERR implementations of `$items->referencedEntities()` and `$item->entity` it seems like the first function is able to handle new entities, but only the second is able to handle unsaved entities.

So loop over $items and then get the paragraph from the single field item:

```
foreach ($items as $item) {
  $paragaph = $item->entity;
  $value = $paragraph->field_foo->value;
  // ...
}

```
> 1 votes

---
Tags: paragraphs
---