# Question
Title: How can I get the canonical path with {{ path('entity.node.canonical') }}
When I use `{{ path('entity.node.canonical', {'node': node.id}) }}` in a node template file, it renders the path alias.

How can I get the canonical path?

# Answer
`{{ path('entity.node.canonical', {'node': node.id}, {'path_processing': false}) }}`
> 3 votes

# Answer
{# /\**

* @file
* Theme override to display a view of unformatted rows.
*
* Available variables:
* + title: The title of this group of rows. May be empty.
* + rows: A list of the view's row items.
* + attributes: The row's HTML attributes.
* + content: The row's content.
* + view: The view object.
* + default\_row\_class: A flag indicating whether default classes should be
* used on rows.
*
* @see template\_preprocess\_views\_view\_unformatted() \*/ #} {% if title %}

### {{ title }}

{% endif %}

{% for row in rows %} {% set row\_classes = \[ default\_row\_class ? 'views-row', \] %} {% endfor %}

\<div{{ row.attributes.addClass(row\_classes) }}\>

```
                <div> SHOOP</div>

```

{# The content type is named :"shop" If we have just added one node for in contente type "SHOOP", we can keep the node content type id with : {{ view.result.0.nid) }}. Il we have more node content type, we have to use the loop "for". And in order to reach each field value we use this followig method. Note thate, the active template was : "views-wiew--unuformated.htlm.twig". The suggested view that we create in the theme suggestion we be : "views-view--shop.html.twig"

#}

```
{% set items = view.result %}

{#for each item 'of content type' #}
{% for item in items %}

        {# Champ 'Title' of content type "SHOP"  #}
        {{ item._entity.title.value|raw}}

        {# Champ 'Image 1' du TDC "SHOP"  #}
         <img src="{{ file_url(item._entity.field_image_1.entity.uri.value) }}"/>

         {# Champ 'Image 2' of content type "SHOP"  #}
        <img src="{{ file_url(item._entity.field_image_2.entity.uri.value) }}"/>

        <img src="{{ file_url(item._entity.field_image_3.entity.uri.value) }}"/>

        {# field 'Description' of content type "SHOP"  #}
        {{ item._entity.field_description.value|raw }}

        {# Champ 'weight' of content type "SHOP" #}
        {{ item._entity.field_weight.value }}

<button type="button" class="btn btn-primary">
     <a href="{{ path('entity.node.canonical', {'node' : item.nid }) }}"> {{"See more"|t}}
    </a>
</button>
{% endfor %}

```
> -2 votes

---
Tags: nodes
---


title: Regenerate image styles

text:
# Question
Title: Regenerate image styles
I'm currently using Drupal 8.2.3 for my website design. My aim is to use it for publishing my blogs to social media sites, such as Facebook, Twitter, LinkedIN, etc. With that in mind, i'm using image styles to create OpenGraph and Twitter meta tags in my blog posts to properly display content on various platforms.

The problem comes when I make a change to the imagestyle. When I flush the contents, it doesn't automatically regenerate the imagestyle content for my metadata. Is there a way to automatically regenerate the imagestyles and content?

Any help much appreciated.

# Answer
There is a setting to flush the image style at admin/config/media/image-styles:

Or you can use drush:

```
drush image-flush --all (flush all styles)
drush image-flush thumbnail (flush thumbnail style)

```
> 7 votes

# Answer
If you are using Drupal Console (and let's face it, why not?) then you can use:

```
drupal image:styles:flush image_style

```

Documenation: https://docs.drupalconsole.com/en/commands/image-styles-flush.html
> 2 votes

# Answer
> The problem comes when I make a change to the imagestyle. When I flush the contents, it doesn't automatically regenerate the imagestyle content for my metadata. Is there a way to automatically regenerate the imagestyles and content?

I have a couple of questions to you:

* What kind of changes you make to the image style?
* What does flushint the contents mean?
* By imagestyle content you mean the derivated image from the original one? (so generated image file itself)
> 0 votes

# Answer
Sometimes - images are not showing, when seeing files in contents.

This mostly caused by server permissions.

For CentOS/Redhat/Fedora/Rocky Linux systems :

```
chown -R apache:apache /var/www/html/demodrupal/sites/default/
chcon -R -t httpd_sys_rw_content_t sites/default/

```

Two commands are required/
> 0 votes

# Answer
It seems you want to generate proper metatags for your node pages (blogs). To generate them dynamically i propose to add to your module.module file next code with **hook\_entity\_view** function:

```
  function your_module_entity_view(array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {

  if ($entity->getEntityTypeId() == 'node') {
      $bundle = $entity->bundle();
      switch ($bundle){
          case 'blog':
              $image = $entity->get('field_image');
              $image_id = $image->getValue()[0]['target_id'];
              $image_file = \Drupal\file\Entity\File::load($image_id);
              $uri = $image_file->uri->value;
              $facebook_image_url = Drupal\image\Entity\ImageStyle::load('your_facebook_style')->buildUrl($uri);
              $facebook_metatag = [
                  '#tag' => 'meta',
                  '#attributes' => [
                    'property' => 'og:image',
                    'content' => $facebook_image_url,
                  ],
                ];
               $build['#attached']['html_head'][] = [$facebook_metatag, 'facebook_metatag'];
// the same for other social networks:

$twitter_image_url = Drupal\image\Entity\ImageStyle::load('your_twitter_style')->buildUrl($uri);
//etc
                  break;

          }

      }

    }

```

And you get this metatag type **meta property="og:image" content="http://static01.nyt.com/images/2015/02/19/arts/international/19iht-btnumbers19A/19iht-btnumbers19A-facebookJumbo-v2.jpg"** Also you can add any metatag in such a manner:

```
 $facebook_metatag = [
    '#tag' => 'meta',
    '#attributes' => [
             'property' => 'og:title',
             'content' => $your_node_title,
          ],
   ];
   $build['#attached']['html_head'][] = [$facebook_metatag, 'facebook_metatag'];

```
> -3 votes

---
Tags: 8, media
---


# Question
Title: Get the node that a block is placed on without a route parameter?
Is there a way to devise from a block instance that was placed in Layout Builder how to load up and extract what node (or entity) it was placed into?

We are indexing pages into Solr and some inline components that load the node from the current route for data are failing because Search API is loading the entities to index and not crawling paths.

# Answer
> 4 votes
A block placed in Layout Builder can load the `entity` context:

```
$entity = $this->getContextValue('entity');

```

This works in the block build method. If you are altering an existing block you can use a LayoutBuilderEvents::SECTION\_COMPONENT\_BUILD\_RENDER\_ARRAY event:

```
public function onBuildRender(SectionComponentBuildRenderArrayEvent $event) {
  $build = $event->getBuild();
  $contexts = $event->getContexts();
  if (isset($contexts['entity'])) {
    if ($entity = $contexts['entity']->getContextValue()) {
      $build['content'][] = ['#markup' => $entity->label()];
    }
  }
  $event->setBuild($build);
}

```

---
Tags: 10
---


# Question
Title: ['#attributes']['class'] variable is not being rendered on the page
I'm working on an old Drupal 7 site.

In the template file paragraphs-item--user-block-paragraph.tpl.php the content is being rendered, but the class is not added to the element.

Here is the code:

```
$content['#attributes']['class'][] = 'my-class';
print "<script>alert('".$content['#attributes']['class'][0]."');</script>"; // confirmed variable is set to my-class
print render($content); // confirmed correct file name

```

What variable in $content determines the classes of the element?

# Answer
I don't know the structure of the template but it should be something like this:

```
$content['field'][0]['#attributes']['class'][] = 'my-class';

```

or

```
$content['field']['#attributes']['class'][] = 'your-class';

```
> 0 votes

---
Tags: 7, theming, hooks
---


# Question
Title: When providing default settings for elements in a field widget, what is the syntax for multiple value checkboxes?
I have a field widget with three different settings, two of them are just string values but the third is multiple checkboxes.

This page describes how to set default settings, simple enough for integer or string and single value fields, but I'm not sure how to set default values for some of the checkboxes in the multiple checkbox element.

Below is the function where i need to set some of the values in the multiple checkboxes element to true. I can just put 'checkboxes\_element' =\> '', as a default value which makes them all unticked, but i need to set some of those checkboxes as true for the default value.

```
/**
 * {@inheritdoc}
 */
 public static function defaultSettings() {
  return [
    // Create the custom setting 'size', and
    // assign a default value of 60
    'size' => 60,
  ] + parent::defaultSettings();
}

```

# Answer
Thanks to Clive, much easier than I was expecting, the default settings function should just look like the following, replacing the options in the array with the relevant keys:

```
 public static function defaultSettings() {
    return [
      'checkboxes_options' => array('option1', 'option5', 'option9'),
    ] + parent::defaultSettings();
  }

```
> 1 votes

---
Tags: forms
---


# Question
Title: Custom Menu Template not Rendering Menu Links
I'm building a custom module that modifies the main theme (barrio bootstrap in this case) to establish a landing page. In that process, it hides blocks in some regions and takes over rendering the main menu.

When I try to replace the default menu template used by the primary menu, `menu--main.html.twig` with my own template `mymenu--main.html.twig` which is exactly the same TWIG code (other than debugging text), it doesn't render the menu links. My custom template is being used, however for some reason it's not rendering the menu links the same.

I'm doing this in a custom module called `main_sections` which uses the `main_sections_theme` hook, inside the file `main_sections.module`, to override the page template with a custom landing page template called, `phtml--landing.html.twig`.

To render the main menu on this custom page template, I pass the main menu as a TWIG variable called `main_menu_def`. This seems to work just fine and renders my main menu on my landing page, as expected, and is using the un-modified default menu template from the theme, `menu--main.html.twig`.

However, when I edit the menu object's `#theme` variable, to use my custom menu template, `mymenu--main.html.twig` before passing the variable to the page template, `phtml--landing`, it no longer renders the menu links.

To illustrate the difference I have passed two menu variables, the first called `main_menu_def` which is unmodified, and `main_menu` which is a copy with the theme variable changed to my custom menu template.

## **main\_sections.module**

In this file, I have a function, `main_sections_block_access` that is used to hide unwanted regions, and the theme hook, `main_sections_theme` in which I pull the main menu object and edit the theme template, as well as register my custom templates, `phtml--landing` and `mymenu--main`.

```
<?php

// use Drupal\block\Controller as bController;
// // use core\modules\block\src\Controller\;
use Drupal\block\Entity\Block;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Updater\Theme;
use Symfony\Component\Console\Completion\Suggestion;

/**
 * Implements hook_block_access().
 * Used to hide blocks on regions not used on pages set by main_sections module
 */
function main_sections_block_access(Block $block, $operation, AccountInterface $account) {
  // get active path
  $current_path = \Drupal::service('path.current')->getPath();
  // $path_alias = \Drupal::service('path_alias.manager')->getAliasByPath($nodeid);
  // \Drupal::service('path.matcher')->matchPath($path_alias, '/landing/*')

  // path on which to hide blocks
  $hide_on_path = '/landing';
  // if the current path matches hide blocks path
  if ( \Drupal::service('path.matcher')->matchPath($current_path, $hide_on_path) ){
    // list of regions on which to hide blocks
    $hide_regions = array(
      'primary_menu',
      'header',
      'header_form',
      'breadcrumb'
    );
    // Get the block's visibilty condition configuration
    // These are the same visibility settings found on the block config page in the admin UI
    $config = $block->getVisibilityConditions()->getConfiguration();
    foreach ($hide_regions as $region){
      // if block is on a region to hide, then update settings to hide it
      if($block->getRegion() === $region){
        // add the path on which block should be hidden to visibility pages list
        $config['pages'] = $hide_on_path;
        // set visibility pages to 'Hide for listed pages'
        $config['negate'] = TRUE;
        // update block with new visiblity pages config
        $block->setVisibilityConfig('request_path', $config);
      }
    }  //END foreach region
  }  //END path match

}  // END of block access hook

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

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

  $blocks = \Drupal\block\Entity\Block::loadMultiple();
  $block_ids = [];
  $block_regions = [];
  $condition_list = [];
  $visibilities = [];

  foreach($blocks as $block){
    $block_ids[] = $block->id();
    $block_regions[] = $block->getRegion();
    $conditions = $block->getVisibilityConditions()->getConfiguration();
    $visibility = $block->getVisibilityConditions();
    $condition_list[] = $conditions;
    $visibilities[] = $visibility;
  } //for each block

  // $state = \Drupal::state()->getMultiple();

  $theme = \Drupal::config('system.theme')->get('default');

  // get the menu tree interface object
  $menu_tree_interface = \Drupal::menuTree();
  // create menu tree parameters object
  $menu_parameters = new \Drupal\Core\Menu\MenuTreeParameters();
  // get menu tree object for the 'main' navigation menu
  $main_menu_tree = $menu_tree_interface->load('main', $menu_parameters);
  // create array of desired manipulators to apply to menu tree
  $manipulators = array(
    // Only show links that are accessible for the current user.
    array(
      'callable' => 'menu.default_tree_manipulators:checkAccess',
    ),
    // Use the default sorting of menu links.
    array(
      'callable' => 'menu.default_tree_manipulators:generateIndexAndSort',
    ),
  );
    // apply manipulators to the menu tree using \Drupal::menuTree()->transform()
    $tree = $menu_tree_interface->transform($main_menu_tree, $manipulators);
    // build transformed menu tree into renderable array object for TWIG
  $main_menu = $menu_tree_interface->build($tree);
  $main_menu_def = $main_menu;
  // $menu_html = \Drupal::service('renderer')->render($main_menu);
  // change to using local theme
  // $main_menu['#theme'] = 'navigation/mymenu--main';
  // $main_menu['#theme'] = 'navigation/mymenu__main';
  // WORKING reference
  $main_menu['#theme'] = 'mymenu__main';
  // $main_menu['#theme'] = 'menu__main';

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

  return [
    'pphtml__landing' => [
      // 'render element' => 'children',
      'template' => 'layout/phtml--landing',
      'variables' => [
        'test_var' => 'test text variable',
        'theme' => $theme,
        'menu_theme' => $main_menu['#theme'],
        'path' => $path,
        'type' => $type,
        // 'existing' => $existing,
        // 'main_menu_tree' => $main_menu_tree,
        'main_menu' => $main_menu,
        'main_menu_tree' => $main_menu_tree,
        'main_menu_def' => $main_menu_def,
        // 'site_config' => $site_config,
        // 'site_information' => $site_info,
        'site_slogan' => $site_slogan,
        // 'block_ids' => $block_ids,
        'block_regions' => $block_regions,
        'condition_list' => $condition_list,
        'existing' => $existing,
        // 'visibilites' => $visibilities,
        // 'config_main_menu' => $config_main_menu,
        // 'vars' => $variables,
      ],
      // 'base hook' => 'node',
    ],
    'mymenu__main' => [
      'template' => 'navigation/mymenu--main',
      'variables' => [
        'main_menu' => $main_menu,
        'menus'  => $main_menu_tree,
      ],
      // 'render element' => 'children',
      // 'base hook' => 'menu__main',
      // 'render element' => 'menu',
    ]
  ];
}

```

## phtml--landing.html.twig

Here is the custom landing page template.

```
<div class="layout-container">
  <header role="banner">
    <div>
      <p>TESTING HEAD</p>
    </div>
    {{ kint() }}
  </header>

  <div class="container">
    <div> Menu that automatically uses default bootstrap barrio menu--main twig template </div>
    <nav class="navbar navbar-dark bg-primary navbar-expand-lg  menu--main">
      <div class="container-fluid contextual-region block block-menu navigation justify-content-center">
        {{ main_menu_def }}
      </div>
    </nav>
    <div> Menu with #theme render array variable changed to mymenu--main twig template </div>
    <nav class="navbar navbar-dark bg-primary navbar-expand-lg  menu--main">
      <div class="container-fluid contextual-region block block-menu navigation justify-content-center">
        {{ main_menu }}
      </div>
    </nav>
    <div class="row">
        <p>TESTING BODY</p>
        <div>{{ kint(theme) }}</div>
        <div>{{ kint(menu_theme) }}</div>
        <div>{{ kint(main_menu) }}</div>
        <div>{{ kint(main_menu_tree) }}</div>
    </div>
  </div>

  <footer role="contentinfo">
    {{ page.footer }}
    <div>
      <p>FOOTER TESTING</p>
    </div>
  </footer>
</div>

```

## mymenu--main.html.twig

This is my custom menu template, which is a copy of the default theme's menu template, `menu--main` with an added text line and kint for debugging.

```
{% import _self as menus %}
{# {% import _self as main_menu %} #}
{#
  We call a macro which calls itself to render the full tree.
  @see http://twig.sensiolabs.org/doc/tags/macro.html
#}

{{ menus.menu_links(items, attributes, 0) }}
{# {{ main_menu.menu_links(items, attributes, 0) }} #}
<div style="color:lime"> My Main Menu </div>
{{ kint() }}
{{ kint(menus) }}
{{ kint(main_menu) }}
{% macro menu_links(items, attributes, menu_level) %}
  {% import _self as menus %}
  {# {% import _self as main_menu %} #}
  {% if items %}
    {% if menu_level == 0 %}
      <ul{{ attributes.addClass('nav navbar-nav')|without('id') }}>
    {% else %}
      <ul class="dropdown-menu">
    {% endif %}
    {% for item in items %}
      {%
        set classes = [
          menu_level ? 'dropdown-item' : 'nav-item',
          item.is_expanded ? 'menu-item--expanded',
          item.is_collapsed ? 'menu-item--collapsed',
          item.in_active_trail ? 'active',
          item.below ? 'dropdown',
        ]
      %}
      <li{{ item.attributes.addClass(classes) }}>
        {%
          set link_classes = [
            not menu_level ? 'nav-link',
            item.in_active_trail ? 'active',
            item.below ? 'dropdown-toggle',
            item.url.getOption('attributes').class ? item.url.getOption('attributes').class | join(' '),
            'nav-link-' ~ item.url.toString() | clean_class,
          ]
        %}
        {% if item.below %}
          {{ link(item.title, item.url, {'class': link_classes, 'data-bs-toggle': 'dropdown', 'aria-expanded': 'false', 'aria-haspopup': 'true' }) }}
          {{ menus.menu_links(item.below, attributes, menu_level + 1) }}
        {% else %}
          {{ link(item.title, item.url, {'class': link_classes}) }}
        {% endif %}
      </li>
    {% endfor %}
    </ul>
  {% endif %}
{% endmacro %}

```

## Resulting Output

The resulting page shows both menus, the top one is using the un-modified menu variable `main_menu_def` which uses the `menu--main` barrio bootstrap template, and renders as expected, and the 2nd one using the modified menu variable, `main_menu`, which uses my custom `mymenu--main` template which does not render the links.

Here are the variables of the non-working menu block, expanded and the inspector showing it is pulling the desired template.

What am I doing wrong with this setup? One of the parts I'm not sure about is how to establish multiple theme template overrides through hooks, properly. Especially as one template override (ie the mymenu--main template) is rendered inside another template override (phtml--landing, in this case). This is what I worked out to get these templates to be recognized and used, but clearly it's not quite right.

# Answer
> 0 votes
For reasons I don't fully understand, directly changing the `#theme` parameter of the menu object, in the module's theme hook, as I did above, is not handling the menu object variable the same way as the default theme template. It changes the menu template, but the menu object, and subsequently, the items array variable, are not available at the same level so do not process the same on the template.

In order to have my custom menu handled the same way as the original menu, it was necessary to leave the menu's `#theme` parameter alone, and instead use a theme\_suggestions\_HOOK\_alter function to add the custom menu template, as such.

### main\_sections.module file updated from original post (not showing block\_access hook, which is still in actual code)

```
function main_sections_theme_suggestions_menu_alter(array &$suggestions, array $variables) {
  $current_path = \Drupal::service('path.current')->getPath();
  // The landing page menu is given the menu_name, 'landing_menu' inside
  // the main_sections_theme hook so it can be identified here.
  if ($variables['menu_name'] == 'landing_menu') {
    $suggestions[] = 'mymenu__main';
  }
}

/**
 * Implements hook_theme()
 * Primary module hooks for test_module module.
 */
function main_sections_theme($existing, $type, $theme, $path) {
  // get the menu tree interface object
  $menu_tree_interface = \Drupal::menuTree();
  // create menu tree parameters object
  $menu_parameters = new \Drupal\Core\Menu\MenuTreeParameters();
  // get menu tree object for the 'main' navigation menu
  $main_menu_tree = $menu_tree_interface->load('main', $menu_parameters);
  // create array of desired manipulators to apply to menu tree
  $manipulators = array(
    // Only show links that are accessible for the current user.
    array(
      'callable' => 'menu.default_tree_manipulators:checkAccess',
    ),
    // Use the default sorting of menu links.
    array(
      'callable' => 'menu.default_tree_manipulators:generateIndexAndSort',
    ),
  );
  // apply manipulators to the menu tree using \Drupal::menuTree()->transform()
  $tree = $menu_tree_interface->transform($main_menu_tree, $manipulators);
  // build transformed menu tree into renderable array object for TWIG
  $main_menu = $menu_tree_interface->build($tree);
  $main_menu_def = $main_menu;

  // Changing the #theme parameter directly does change the template used,
  // However, it does not carry the menu object and variables as desired.
  // $main_menu['#theme'] = 'mymenu__main';
  // Instead it works better to change name of the menu to something that can then be
  // filtered for by main_sections_theme_suggestions_menu_alter,
  // which will generate the association to the desired template.
  $main_menu['#menu_name'] = 'landing_menu';

  return [
    'pphtml__landing' => [
      'template' => 'phtml--landing',
      'path' => \Drupal::service('extension.list.module')->
                getPath('main_sections').'/templates/layout',
      'variables' => [
        'main_menu' => $main_menu,
        'main_menu_def' => $main_menu_def,
      ],
    ],
    // register custom menu template
    'mymenu__main' => [
      'template' => 'mymenu--main',
      'path' => \Drupal::service('extension.list.module')->
                getPath('main_sections').'/templates/navigation',
      // Passing the modified menu variable here is not necessary as it is
      // has already been passed to the 'phtml__landing' template.
      // Here we just need to register our custom templates location.
      // 'variables' => [
      //   'main_menu' => $main_menu,
      // ],
    ]
  ];
}

```

### Resulting Custom Menu Rendering Appropriately

As we can see, the changes above now allow the customized menu to render as expected. However, we also note that the because we used non-conformant TWIG template names, we get an 'INVALID FILE NAME SUGGESTION:' warning in the TWIG debug text in the web inspector. This doesn't seem to cause any functional problems, but to eliminate it we can make further refinements discussed next.

### main\_sections.module, Final Updated Version to Eliminate TWIG Warning

In order to get rid of the template suggestion warning, we can further refine the code to use a template name that follows the expected Drupal patterns. In this case, that can be done by changing the custom template name from `mymenu--main.html.twig`, to one with the prefix `menu--`, such as `menu--landing.html.twig`, and update our template registration appropriately. Using an expected template naming convention that matches our template theme registration name also allows it to be automatically discovered, eliminating the need to specify the template name in the registration.

```
function main_sections_theme_suggestions_menu_alter(array &$suggestions, array $variables) {
  $current_path = \Drupal::service('path.current')->getPath();
  if ($variables['menu_name'] == 'landing_menu') {
    $suggestions[] = 'menu__landing';
  }
}

/**
 * Implements hook_theme()
 * Primary module hooks for test_module module.
 */
function main_sections_theme($existing, $type, $theme, $path) {
  // get the menu tree interface object
  $menu_tree_interface = \Drupal::menuTree();
  // create menu tree parameters object
  $menu_parameters = new \Drupal\Core\Menu\MenuTreeParameters();
  // get menu tree object for the 'main' navigation menu
  $main_menu_tree = $menu_tree_interface->load('main', $menu_parameters);
  // create array of desired manipulators to apply to menu tree
  $manipulators = array(
    // Only show links that are accessible for the current user.
    array(
      'callable' => 'menu.default_tree_manipulators:checkAccess',
    ),
    // Use the default sorting of menu links.
    array(
      'callable' => 'menu.default_tree_manipulators:generateIndexAndSort',
    ),
  );
  // apply manipulators to the menu tree using \Drupal::menuTree()->transform()
  $tree = $menu_tree_interface->transform($main_menu_tree, $manipulators);
  // build transformed menu tree into renderable array object for TWIG
  $main_menu = $menu_tree_interface->build($tree);
  $main_menu_def = $main_menu;

  // Changing menu name to make it filterable by main_sections_theme_suggestions_menu_alter
  $main_menu['#menu_name'] = 'landing_menu';

  return [
    'pphtml__landing' => [
      'template' => 'phtml--landing',
      'path' => \Drupal::service('extension.list.module')->
                getPath('main_sections').'/templates/layout',
      'variables' => [
        'main_menu' => $main_menu,
        'main_menu_def' => $main_menu_def,
      ],
    ],
    // register custom menu template
    'menu__landing' => [
      // No longer necessary to specify template name
      // 'template' => 'menu--landing',
      // The path must still be specified because the template is in a module
      'path' => \Drupal::service('extension.list.module')->
                getPath('main_sections').'/templates/navigation',
    ]
  ];
}

```

---
Tags: navigation, bootstrap-theme, theme-negotiation
---


# Question
Title: Is it possible to force your module's update hook to run?
I am the author of the Date iCal module, and the new major version I'm working on (3.x) requires a two-part schema update for users who had 2.x installed. I've written the update hook that makes these changes, but if one of my users fails to run the database update script, they will get an error message relating to their iCal feeds importers.

The right solution is for them to run the update script... but if they just go in and manually change their importers to get rid of the message, their importers will remain permanently broken (because the second part of the schema update won't have been executed).

So is there any way to display a message to users who haven't run the update? Or somehow forcibly execute the update hook the first time a page load occurs when 3.x gets installed overtop of 2.x?

# Answer
extending on comment from Jimajamma:

> do a `variable_set()` in your update function that sets a variable when it was successfully run that you could look at inside a \_preprocess\_page()

and instead of checking this on every page load do it only if browsing the admin area and if the installed version is 3.0 (3.1, 3.2, kill that check if you stop supporting the old version as an upgrade path).

Additionally make use of hook\_requirements to provide feedback on the status report page:

> Check installation requirements and do status reporting.
> (...)
> The 'runtime' phase is not limited to pure installation requirements but can also be used for more general status information like maintenance tasks and security issues.
> 4 votes

# Answer
There are few ways of forcing module update.

1. Calling the update function directly.

```
$sandbox = [];
module_load_include('install', 'FOO');
FOO_update_7001($sandbox);

```
2. Resetting the schema version to the point of interest and run the updates again as usual.

```
drupal_set_installed_schema_version('module_name', '7000');

```

Or reset to re-run only the latest update schema:

```
drupal_set_installed_schema_version('foo', drupal_get_installed_schema_version('foo') - 1);

```

Notes:

* This can be placed in `hook_install`, so during the update process all sequent update hooks would be executed.
    * In order to use this function outside of the installation file, you've to include Drupal `install.inc` first and installation file of the module, e.g.

    ```
    require_once DRUPAL_ROOT . '/includes/install.inc';
    module_load_include('install', 'foo');

    ```
    * Consider adding `ini_set('max_execution_time', 0);` for longer installation updates to prevent PHP timeouts.
3. Using `drush`. Find below few examples:

* `drush eval 'module_load_include('install', 'foo'); $s = []; foo_update_7001($s);'`
    * `drush sqlq "UPDATE system SET schema_version = 7000 WHERE name = 'foo'" && drush -y updb`
> 21 votes

# Answer
You could "SELECT schema\_version FROM system" to detect whether an update has been performed. If not, then refuse to run (with an error message).
> 1 votes

# Answer
I agree with the above suggestions - my only addition would be to investigate "Triggers and Actions" also - it seems that you need an action (notify user or run update) to occur when a trigger (user checks admin page, etc) is pulled. For use examples see the Examples module, there are both action and trigger example code. :)
> 0 votes

# Answer
`function MYMODULE_install() {
 $functions = get_defined_functions();
 foreach ($functions['user'] as $function) {
 if (strpos($function, 'MYMODULE_update_') === 0) {
 call_user_func($function);
 }
 }
}`
> 0 votes

# Answer
Using Drush you can force your hook to run

```
ddev drush eval 'module_load_include('install', 'module_name'); $s = []; module_hook_9001($s);'

```
> 0 votes

---
Tags: 7, updating
---


# Question
Title: user_cancel_reassign() doesn't work when user has more than 10 nodes
I am attempting to delete users with no permissions/roles from our sites. The user's node should be kept.

This code works when the user has a few nodes. On deletion, their ownership is passed to the anonymous user.

```
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use \Drupal\user\Entity\User;

function mymodule_preprocess_page(&$variables, $hook) {
  $route_name = \Drupal::routeMatch()->getRouteName();
  $user = \Drupal::currentUser();
  if (count($user->getRoles()) == 1 && ($route_name != "system.401" && $route_name != "user.login")) {
    $userWithoutRole = User::load($user->id());
    if ($userWithoutRole !== NULL) {
      user_cancel([], $user->id(), 'user_cancel_reassign');
      $userWithoutRole->delete();
    }
    throw new UnauthorizedHttpException('insufficient permissions');
  }
}

```

It doesn't work when the user is the author of more than 10 nodes. All the nodes are deleted when the user is deleted.

Another method is invoked, I suppose.

How can I solve this?

The same issue is present with the *Auto purge users* module.

# Answer
> 2 votes
`user_cancel()` is run in a batch. This means that either it's called in a form, or `batch_process()` needs to be called after it. For example, this is the code used by `UserController::confirmCancel()`.

```
$edit = [
  'user_cancel_notify' => isset($account_data['cancel_notify']) ? $account_data['cancel_notify'] : $this->config('user.settings')->get('notify.status_canceled'),
];
user_cancel($edit, $user->id(), $account_data['cancel_method']);

// Since user_cancel() is not invoked via Form API, batch processing
// needs to be invoked manually and should redirect to the front page
// after completion.
return batch_process('<front>');

```

It's not necessary to delete the account, as that is already done from `_user_cancel()`, the batch operation callback used from `user_cancel()`.

```
case 'user_cancel_reassign':
case 'user_cancel_delete':
  // Send account canceled notification if option was checked.
  if (!empty($edit['user_cancel_notify'])) {
    _user_mail_notify('status_canceled', $account);
  }
  $account->delete();
  // …

```

It's also probable that `hook_preprocess_page()` is the wrong place to call `user_cancel()` as it would be called when the page is being rendered, while the batch operations require to redirect users. See `batch_process()`, which contains the following code.

```
if (($function = $batch['redirect_callback']) && function_exists($function)) {
  $function($batch_url->toString(), [
    'query' => $query_options,
  ]);
}
else {
  return new RedirectResponse($batch_url->setAbsolute()->toString(TRUE)->getGeneratedUrl());
}

```

# Answer
> 1 votes
In my case, I was performing mass user deletion in a Drush command. First I was calling directly the batch operation `_user_cancel` because calling `user_cancel()` was leading to perform a batch in a batch, which would not work. But the problem was that because of that I was skipping some actions of `user_cancel()`, like for example the call of `hook_user_cancel()` of any other module implementing the hook in question.

Finally I was able to call `user_cancel()` :

```
protected function cancelUsers() {
  $user_settings = \Drupal::config('user.settings');

  foreach ($this->obsoleteUser as $uid) {
    $cancel_method = $user_settings->get('cancel_method');

    $edit = [
      // Use $user_settings->get('notify.status_canceled') in
      // the following if you need to apply the user settings.
      'user_cancel_notify' => FALSE,
      'user_cancel_method' => $cancel_method,
    ];

    // user_cancel() will set batch operations itself. All is needed is a call
    // to process it.
    user_cancel($edit, $uid, $cancel_method);
  }
}

```

And make sure in my command that I was using the batch initiated by `user_cancel()` :

```
$batch =& batch_get();

if (empty($batch)) {
  return;
}

drush_backend_batch_process();

```

---
Tags: nodes
---


title: Hide a view tab if it has no results

text:
# Question
Title: Hide a view tab if it has no results
I have a view which has 5 menu tabs. I want to hide the tab if it doesn't have any results. Can anyone please help me with the suggestions.

# Answer
> 0 votes
Can be done with Jquery Check for the class "view-empty", if this div has inner div, then that means it has some content, if not hide that parent tab div.

# Answer
> 0 votes
By implementing hooks as below

function custom\_tabs\_hide\_menu\_local\_tasks\_alter(&$data, $route\_name, $route\_match) {

// Check if the current route matches the route where your Views is being displayed.

if ($route\_name === 'entity.view.your\_view\_id.page\_1') {

```
// Replace 'your_view_id' with the actual ID of your view.
// Check if the View has no results.

$view = \Drupal\views\Views::getView('your_view_id');

```

// Replace 'your\_view\_id' with the actual ID of your view.

```
$view->setDisplay('page_1'); // Replace 'page_1' with the display ID of your view.

$view->execute();

if (empty($view->result)) {
  // Hide the tab.
  unset($data['tabs']['view-id.your_view_id-page_1']);
}

```

} }

---
Tags: views
---


title: Drush database issue

text:
# Question
Title: Drush database issue
I have encountered an issue with Drush, which doesn't show many commands that should be present. When I run a command with the `--debug` flag, I see the following error message.

> \[Symfony\Component\Console\Exception\CommandNotFoundException\] Command rq was not found. Drush was unable to query the database. As a result, many commands are unavailable. Re-run your command with `--debug` to see relevant log messages.

When I run `drush sql:connect`, it shows all the correct database information for the site.

I tried Drush 9.7.2, as well as Drush 10.2.2. Both versions return the same error, whenever I install Drush locally to the site, or globally.

I am trying the commands on Drupal 8.8.5, which runs on PHP 7.1.33, on macOS 10.14.6.

To add to the above, the site itself works fine. And again, these commands above show all the correct information, so it is clearly SEEING the database. This is a local (development) build, on my local machine, under MAMP 5.7.

Furthermore, when I run `drush site install -vvv`, I get the following error.

> \[preflight\] Config paths: /Users/\[machine name\]/vendor/drush/drush/drush.yml
> \[preflight\] Alias paths:
> \[preflight\] Commandfile search paths: /Users/\[machine name\]/vendor/drush/drush/src
> \[debug\] Bootstrap further to find site
> \[debug\] Trying to bootstrap as far as we can
> \[debug\] Done with bootstrap max in Application::bootstrapAndFind(): trying to find site again.
>
> In Application.php line 230:
>
> \[Symfony\Component\Console\Exception\CommandNotFoundException\] Command site was not found. Pass --root or a @siteAlias in order to run Drupal-specific commands.
>
> Exception trace:
> at /Users/\[machine name\]/vendor/drush/drush/src/Application.php:230 Drush\Application-\>bootstrapAndFind() at /Users/\[machine name\]/vendor/drush/drush/src/Application.php:192
> Drush\Application-\>find() at /Users/\[machine name\]/vendor/symfony/console/Application.php:235
> Symfony\Component\Console\Application-\>doRun() at /Users/\[machine name\]/vendor/symfony/console/Application.php:147
> Symfony\Component\Console\Application-\>run() at /Users/\[machine name\]/vendor/drush/drush/src/Runtime/Runtime.php:118
> Drush\Runtime\Runtime-\>doRun() at /Users/\[machine name\]/vendor/drush/drush/src/Runtime/Runtime.php:49
> Drush\Runtime\Runtime-\>run() at /Users/\[machine name\]/vendor/drush/drush/drush.php:72
> require() at /Users/\[machine name\]/vendor/drush/drush/drush:4

It seems to say it can't find the site, which is understandable, as I am running the command to install a site.

Something is clearly wrong. I'm hoping someone can help me sort this out.

The output of `drush list` is the following.

> Drush Commandline Tool 10.2.2
>
> Run `drush help [command]` to view command-specific help. Run `drush topic` to read even more documentation.
>
> Available commands: \_global:browse Display a link to a given path or open link in a browser.
> drupal:directory Return the filesystem path for moddules/themes and other key folders.
> entity:updates Apply pending entity schema updates.
> generate Generate boilerplate code for modules/plugins/services etc.
> help Display usage details for a command.
> list List available commands.
> pm:security Check Drupal Composer packages for pending security updates.
> runserver Runs PHP's built-in http server for development.
> updatedb Apply any database updates required (as with running update.php).
> updatedb:status List any pending database updates.
> user:login Display a one time login link for user ID 1, or another user.
> version Show Drush version.
> cache:clear Clear a specific cache, or all Drupal caches.
> cache:get Fetch a cached object and display it. \> cache:rebuild Rebuild a Drupal 8 site.
> cache:set Cache an object expressed in JSON or var\_export() format.
> cache:tags Invalidate by cache tags.
> config:import Import config from a config directory. \> config:pull Export and transfer config from one environment to another.
> core:edit Edit drushrc, site alias, and Drupal settings.php files.
> core:init Enrich the bash startup file with bash aliases and a smart command prompt.
> core:rsync Rsync Drupal code or files to/from another server using ssh.
> core:status An overview of the environment - Drush and Drupal.
> core:topic Read detailed documentation on a given topic.
> php:eval Evaluate arbitrary php code after bootstrapping Drupal (if available).
> php:script Run php a script after a full Drupal bootstrap.
> site:alias Show site alias details, or a list of available site aliases.
> site:alias-convert Convert legacy site alias files to the new yml format.
> site:install Install Drupal along with modules/themes/configuration/profile.
> site:set Set a site alias that will persist for the current session.
> site:ssh Connect to a Drupal site's server via SSH, and optionally run a shell command.
> sql:cli Open a SQL command-line interface using Drupal's credentials.
> sql:connect A string for connecting to the DB.
> sql:create Create a database.
> sql:drop Drop all tables in a given database.
> sql:dump Exports the Drupal DB as SQL using mysqldump or equivalent.
> sql:query Execute a query against a database.
> sql:sync Copy DB data from a source site to a target site.

There are commands missing from the list. It appears that Drush is not connecting to the database, which is weird, because it clearly sees the database, it's clearly aware of the necessary credentials to make the connection, and Drupal itself is connecting. The commands that show up on the DRUSH LIST seem to work fine, for example `drush pm:security`.

> \[warning\] One or more of your dependencies has an outstanding security update.
> \[notice\] Try running: composer require drupal/core drupal/webform --update-with-dependencies \[notice\] If that fails due to a conflict then you must update one or more root dependencies.
>
> | Name | Installed Version |
> | --- | --- |
> | drupal/core | 8.8.4 |
> | drupal/webform | 5.9.0 |

I'm confused on what the solution is.

This is the output of `drush cr`.

> In Connection.php line 416:
> SQLSTATE\[HY000\] \[2002\] No such file or directory
>
> `cache:rebuild [--cache-clear [CACHE-CLEAR]] [--no-cache-clear] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-d|--debug] [-y|--yes] [--no] [--remote-host REMOTE-HOST] [--remote-user REMOTE-USER] [-r|--root ROOT] [-l|--uri URI] [--simulate] [--pipe] [-D|--define DEFINE] [--notify] [--druplicon] [--xh-link XH-LINK] [--] <command>`

This is the output of `drush cr --debug`.

> Using the Drush script found at /Users/brianeller-mini/vendor/drush/drush/drush using proc\_open
> \[preflight\] Config paths: /Users/brianeller-mini/vendor/drush/drush/drush.yml
> \[preflight\] Alias paths: /Users/brianeller-mini/Projects/various/docroot/drush/sites,/Users/brianeller-mini/Projects/various/drush/sites
> \[preflight\] Commandfile search paths: /Users/brianeller-mini/vendor/drush/drush/src
> \[debug\] Starting bootstrap to site \[debug\] Drush bootstrap phase 2 \[debug\] Try to validate bootstrap phase 2 \[debug\] Try to validate bootstrap phase 2 \[debug\] Try to bootstrap at phase 2 \[debug\] Drush bootstrap phase: bootstrapDrupalRoot() \[debug\] Change working directory to /Users/brianeller-mini/Projects/various/docroot
> \[debug\] Initialized Drupal 8.8.4 root directory at /Users/brianeller-mini/Projects/various/docroot
> \[debug\] Try to validate bootstrap phase 2
> \[debug\] Try to bootstrap at phase 2
> \[debug\] Drush bootstrap phase: bootstrapDrupalSite()
> \[debug\] Initialized Drupal site default at sites/default

In Connection.php line 416:

> \[PDOException (2002)\]
> SQLSTATE\[HY000\] \[2002\] No such file or directory

Exception trace:

> at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php:416
> PDO-\>\__construct() at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Core/Database/Driver/mysql/Connection.php:416
> Drupal\Core\Database\Driver\mysql\Connection::open() at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Core/Database/Database.php:371
> Drupal\Core\Database\Database::openConnection() at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Core/Database/Database.php:166
> Drupal\Core\Database\Database::getConnection() at n/a:n/a call\_user\_func\_array() at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php:79
> Drupal\Component\DependencyInjection\PhpArrayContainer-\>createService() at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Component/DependencyInjection/Container.php:173
> Drupal\Component\DependencyInjection\Container-\>get() at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php:265
> Drupal\Component\DependencyInjection\PhpArrayContainer-\>resolveServicesAndParameters() at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Component/DependencyInjection/PhpArrayContainer.php:62
> Drupal\Component\DependencyInjection\PhpArrayContainer-\>createService() at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Component/DependencyInjection/Container.php:173
> Drupal\Component\DependencyInjection\Container-\>get() at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Core/DrupalKernel.php:544
> Drupal\Core\DrupalKernel-\>getCachedContainerDefinition() at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Core/DrupalKernel.php:896
> Drupal\Core\DrupalKernel-\>initializeContainer() at /Users/brianeller-mini/Projects/various/docroot/core/lib/Drupal/Core/DrupalKernel.php:477
> Drupal\Core\DrupalKernel-\>boot() at /Users/brianeller-mini/Projects/various/docroot/core/includes/utility.inc:38
> drupal\_rebuild() at /Users/brianeller-mini/vendor/drush/drush/src/Commands/core/CacheCommands.php:221
> Drush\Commands\core\CacheCommands-\>rebuild() at n/a:n/a call\_user\_func\_array() at /Users/brianeller-mini/vendor/consolidation/annotated-command/src/CommandProcessor.php:257
> Consolidation\AnnotatedCommand\CommandProcessor-\>runCommandCallback() at /Users/brianeller-mini/vendor/consolidation/annotated-command/src/CommandProcessor.php:212
> Consolidation\AnnotatedCommand\CommandProcessor-\>validateRunAndAlter() at /Users/brianeller-mini/vendor/consolidation/annotated-command/src/CommandProcessor.php:178
> Consolidation\AnnotatedCommand\CommandProcessor-\>process() at /Users/brianeller-mini/vendor/consolidation/annotated-command/src/AnnotatedCommand.php:302
> Consolidation\AnnotatedCommand\AnnotatedCommand-\>execute() at /Users/brianeller-mini/Projects/various/vendor/symfony/console/Command/Command.php:255
> Symfony\Component\Console\Command\Command-\>run() at /Users/brianeller-mini/Projects/various/vendor/symfony/console/Application.php:1000
> Symfony\Component\Console\Application-\>doRunCommand() at /Users/brianeller-mini/Projects/various/vendor/symfony/console/Application.php:255
> Symfony\Component\Console\Application-\>doRun() at /Users/brianeller-mini/Projects/various/vendor/symfony/console/Application.php:148
> Symfony\Component\Console\Application-\>run() at /Users/brianeller-mini/vendor/drush/drush/src/Runtime/Runtime.php:118 Drush\Runtime\Runtime-\>doRun() at /Users/brianeller-mini/vendor/drush/drush/src/Runtime/Runtime.php:49
> Drush\Runtime\Runtime-\>run() at /Users/brianeller-mini/vendor/drush/drush/drush.php:72
> require() at /Users/brianeller-mini/vendor/drush/drush/drush:4
>
> `cache:rebuild [--cache-clear [CACHE-CLEAR]] [--no-cache-clear] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-d|--debug] [-y|--yes] [--no] [--remote-host REMOTE-HOST] [--remote-user REMOTE-USER] [-r|--root ROOT] [-l|--uri URI] [--simulate] [--pipe] [-D|--define DEFINE] [--notify] [--druplicon] [--xh-link XH-LINK] [--] <command>`

# Answer
> 0 votes
You might be missing the global drush which is causing this issue. Try to install drush globally in the following path where the composer is installed - *C* or *D:\Users\<username\>\AppData\Roaming\Composer*

Add the following lines to your *composer.json* file :-

```
"drush/drush": "9.x"

```

and run

```
composer global update

```

Alternately you can also run

```
composer global require drush/drush:9.x

```

Update the path to global drush in ENV variables. Your path to drush would be :-

Restart your Apache or open a new terminal window to check the *drush status*.

---
Tags: drush
---


title: How to bulk delete translation strings

text:
# Question
Title: How to bulk delete translation strings
I imported some translations using the locale update module but the translations are horrible and it would be better to revert to English.

How do I bulk delete all the imported translations in Drupal 8?

I found an issue on adding back the D7 translation string deletion option to the UI, but I want to mass delete all strings, not individual strings.

Drupal 7 version of this question

**EDIT**: Deleting the language is one approach, but I can't do that because I already have a lot of content translated into the language. I want to keep the content that I have translated into the language, but delete all the user interface strings that were imported through localization update.

# Answer
> 5 votes
If you intend to remove ALL strings imported through interface translation, you could execute something like this:

```
// Replace the empty string with your target language code.
$langcode = '';
\Drupal::database()
  ->delete('locales_target')
  ->condition('language', $langcode)
  ->condition('customized', 0)
  ->execute();

```

You may also want to reset the source file history information, so - if you change your mind afterwards - you can re-import the very same translations:

```
\Drupal::database()
  ->delete('locale_file')
  ->condition('language', $langcode)
  ->execute();

```

or

```
locale_translation_file_history_delete([], [$langcode]);

```

As the locale module makes heavy use of static caches, you may run above commands in a dedicated process as, e.g. Drush PHP CLI (`drush php:cli`).

# Answer
> 1 votes
* Suggestion 1

if you want to get rid of all translations of a language, just delete the langauge in */admin/config/regional/language*

* Suggestion 2

if there are some specific string you want to be not translated, Go to locales\_source to identify those strings lids, then execute the following code (devel/php or custom hook\_update\_N or drush ev...)

```

$lids = [4, 5];
db_delete('locales_target')->condition('lid', $lids, 'IN')->execute();

```

hope this helps

# Answer
> 1 votes
I found http://web.archive.org/web/20230609014802/http://vaerenbergh.com/blog/drupal-8-reimport-all-translation-files the only solution that worked:

```
DELETE FROM key_value WHERE collection='locale.translation_status';
UPDATE locale_file SET timestamp = 0;
UPDATE locale_file SET last_checked = 0;

```

then

```
drush ev "\Drupal::state()->set('locale.translation_last_checked', 0);"
drush cr
drush locale-check && drush locale-update && drush cr

```

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


# Question
Title: How to hide terms from entity reference field on node form
I've been searching quite a bit on this already and was not able to find a solution. installation is d10 So on my node I have an entity reference field which is showing Taxonomy terms. Two of those taxonomy terms should always be hidden on the node form. But they should exist as taxonomy terms, so removing them from the taxonomy is not an option. I tried using hook\_form\_alter() and unsetting the keys, but that didn't work.

Anyone has experience with this?

Thanks in advance!

# Answer
> 1 votes
@WebAssistant 's answer:

create an Entity Reference View and use a filter to remove the unwanted terms. In the settings of the reference field on the node choose: Views: filter by an entity reference view. Choose the view you created and voila.

---
Tags: forms, taxonomy-terms, hooks
---


# Question
Title: How to get multiple articles with specific ids via JSON:API in one request
how can I get multiple articles with specific ids in one request. I have tried lots of variations of `https://website.com/jsonapi/node/article/aecc1a8b-b827-46a5-956b-16feb49e47c9` but without success. Please help.

# Answer
Drupal's JSON:API implementation basically follows the JSON:API Specification, which is not specific to Drupal.

That means you don't need to include Drupal in search queries; a search for "jsonapi multiple ids" gave this as the first result:

```
filter[id]=1,2,3

```
> 0 votes

---
Tags: http-request
---


# Question
Title: how to print view title in views-view-unformatted.html.twig?
I have to style the view title and print it in the unformatted twig. how can i achieve this ?

# Answer
> 8 votes
As per @Clive's comment

```
{{ view.getTitle() }}

```

# Answer
> 0 votes
How do I get the URL value in the views-view-unformatted--domains\_devs.html.twig? I'm using D10.

`<a href="[My_Link]"/>Go to Link</a>`

---
Tags: views, theming
---


# Question
Title: Override Default Theme's 'page' TWIG template, but not the original page template pre-process hook
I'm using the default theme, Bootstrap Barrio, but for certain pages I'm overriding the `page.html.twig` template to re-arrange the layout, however I still want the pre-processing done by my theme in `bootstrap_barrio_preprocess_page` to execute so that I don't have to maintain a copy of that code inside my custom template's pre-process function, `custom_module_preprocess_page__landing`.

Is there a way to override the template, but still have the original theme's pre-process run so it can setup the default variables? I found this post that seemed to imply that adding this page suggestion hook that would then reference my `page--landing` in the module that is setting things up, would achieve this, but it's not working for me.

(my template is called `page--landing`, but the theme is registered as `page__landing` and i've tried both syntax)

```
function my_module_theme_suggestions_page(array $variables) {
  $path = explode('/', trim(\Drupal::service('path.current')->getPath(), '/'));
  if (isset($path[0]) && $path[0] == 'landing') {
    return 'page--landing';
  }
}

```

# Answer
> 0 votes
It seems like you want to override the `page.html.twig` template for specific pages while still benefiting from the preprocessing logic provided by your theme's `bootstrap_barrio_preprocess_page` function. To achieve this, you can follow these steps:

1. **Create a Sub-theme:** If you're customizing the template in your default theme (`Bootstrap Barrio`), you might consider creating a sub-theme. This will allow you to make modifications without altering the core theme's files and maintain the preprocessing logic. Refer to the theme's documentation on creating a sub-theme.
2. **Override `page.html.twig` in Sub-theme:** In your sub-theme, create a file named `page--landing.html.twig`. This is where you'll customize the layout for the specific landing page. You're doing this to ensure the correct template is used for your specific landing page.
3. **Add Template Suggestions:** You've already attempted this, but make sure you're implementing the theme suggestion correctly in your sub-theme's `my_subtheme.theme` file. In this file, use the correct function name (`my_subtheme_theme_suggestions_page`), and return an array of suggestions. It's important to ensure that the suggestion corresponds to the template file you've created (`page--landing.html.twig`).

```
function my_subtheme_theme_suggestions_page(array $variables) {
  $suggestions = [];

  // Get the current path.
  $path = \Drupal::service('path.current')->getPath();
  $args = explode('/', $path);

  // Check if the first path component is 'landing'.
  if (!empty($args[0]) && $args[0] == 'landing') {
    $suggestions[] = 'page__landing';
  }

  return $suggestions;
}

```
4. **Ensure Preprocessing Logic is Executed:** Ensure that your sub-theme's preprocessing function is named correctly and is placed in the `my_subtheme.theme` file:

```
function my_subtheme_preprocess_page__landing(array &$variables) {
  // Your preprocessing logic here.
}

```

The above function should be placed in the `my_subtheme.theme` file of your sub-theme. Replace `my_subtheme` with the actual machine name of your sub-theme.
5. **Clear Cache:** After adding the theme suggestion function and the template, clear Drupal's cache to ensure the changes are recognized.

By following these steps, you should be able to create a custom template for your landing page while retaining the preprocessing logic from your sub-theme. Make sure that your sub-theme's preprocessing function is properly named and placed in the `my_subtheme.theme` file.

---
Tags: theming, bootstrap-theme
---


title: Is there a "registry rebuild" command?

text:
# Question
Title: Is there a "registry rebuild" command?
I just did a fresh Drush installation, and now I have version 8.1.15.

When I run `drush rr`, I get the following error message.

> The drush command 'rr' could not be found. Run `drush cache-clear drush` to clear the commandfile cache if you have installed new extensions.

Even after running `drush cache-clear`, I still get that `rr` is not a known command.

Is this still available in Drush 8?

# Answer
Take a look at https://www.drupal.org/project/registry\_rebuild

The documentation is there:

> How To Use Registry Rebuild With Drush
>
> This is the preferred technique, and it should work with multisite installs.
>
> You can just `drush @none dl registry_rebuild-7.x` and drush will download it into your .drush folder. (Alternately, you can obtain the package another way and copy the folder into .drush yourself.)
>
> Make a backup of your database.
>
> Clear Drush own cache with `drush cc drush`
>
> On a multisite install, either use correct drush alias, or cd into the site you're rebuilding, as in cd sites/mymultisite
>
> Run `drush rr` or `drush @sitename rr` for soft rebuild (default), or: To force aggressive rebuild from scratch run `drush @sitename rr --fire-bazooka`
> 2 votes

# Answer
That command (drush rr) is currently only for Drupal 7.

It does not matter what version of Drush you use since it is enabled for Drush via a module.

The module that enables that command does not work as of now for newer versions of Drupal.

--\> Module link is https://www.drupal.org/project/registry\_rebuild as stated in the answer by @FLY
> 0 votes

---
Tags: drush
---


# Question
Title: "Uncaught PHP Exception Drupal\Component\Plugin\Exception\PluginNotFoundException"
I get this exception, which does not say which plugin causes it.

> Uncaught PHP Exception Drupal\Component\Plugin\Exception\PluginNotFoundException
> The "" entity type does not exist. at /var/www/html/web/core/lib/Drupal/Core/Entity/EntityTypeManager.php line 139

How can I debug this error?

# Answer
To solve the problem I add this code in the file Entity/EntityTypeManager.php before the line 139 and I get all the error information that I don't get with Watchdog

```
$e = new \Exception;
var_dump($e->getTraceAsString());
exit;

```
> 0 votes

---
Tags: 9, debugging, plugins
---


title: Expand {product.variations}

text:
# Question
Title: Expand {product.variations}
In the product detail page I would like to display the price at the BOTTOM of the {product.variations}

Where can we alter the {product.variations} ?

# Answer
> -1 votes
Go to /admin/commerce/config/product-variation-types, click Edit on your product variation type, click the Manage Display tab, here you can change the order of the fields on whichever display mode you are using.

---
Tags: commerce
---


# Question
Title: How can I work with Twig when using the Display Suite module?
I am working with Commerce 2 and Display suite, i want to add a field to the presentation that when a product has a boolean field valued to true, do not display a field and display other with twig. Maybe this way im more clear: field in product: Variation and a boolean flag if flag = true dont show the variation "Add to cart" but "Coming soon"

The problem i want to solve is that when i have no stock "add to cart" pass to "out of stock" but i would like to shot "Coming soon" if a flag is true even is i do have stock or not.

Thanks for the time reading this!

# Answer
Well i manage to do what i asked, i added a new field to product that name is proximamente,i had to let the variation stay but i hide it from view, with a twig field i can show the things in the way i want

twig code:

```
{% set variable = commerce_product.product_id.value%}
{% if commerce_product.field_proximamente.value is null %}
{{ drupal_field('variations','commerce_product',variable,'add_to_cart') }}
{% elseif commerce_product.field_proximamente.value == true %}
<p class="proximamente-btn-view button--add-to-cart button button--primary js-form-submit form-submit is-disabled btn-primary btn">Próximamente</p>
{% else %}
{{ drupal_field('variations','commerce_product',variable,'add_to_cart') }}
{% endif %}

```

i guess is kinda simple but works for me, when the boolean field is true i show the "Próximamente" with all the classes that a variation in Commerce 2 has, the reason of the first " IF " is because i added that new field way later on the product, so some products might not have it enabled so i have to cover that part
> 0 votes

---
Tags: commerce, display-suite
---


title: Override user login form template

text:
# Question
Title: Override user login form template
I'm trying to customize my user login page in my custom theme using the template file `page--user--login.html.twig`, but am having issues accessing the different form elements. All aspects of the form are located in `page.content`, but I'd like to edit the content that's being outputted.

For a simple example, the base theme has Username and Password stacked vertically, where I'd like to adjust this to use bootstrap so that they are stacked horizontally on large screen and vertically on mobile.

In Drupal 7, we had a `form` element in the template file that allowed me to render certain form elements separately, like:

```
<div class="col-sm-12 col-lg-6">
  <?php print drupal_render($form['name']); ?>
</div>
<div class="col-sm-12 col-lg-6">
  <?php print drupal_render($form['pass']); ?>
</div>

```

Is there an equivalent for Drupal 8?

I attempted to create a template file for the form (`form--user-login.html.twig` and `form--user-login-form.html.twig`) to see if I could alter the form template itself instead of the page the form exists on, but didn't have any luck with that.

I'd prefer to override the current login theme instead of creating a whole new page and form and have to add all the necessary configurations so that a user lands on the correct login page, but have yet to find any way to do so, thanks in advance.

# Answer
if you overrided correctly `element` will contain all items in `form--user-login.html.twig`,

```
<div class="login-form login-form__wrapper">
    <form{{ attributes }}>
        <div class="login-form__top">
            <h3>hello world</h3>
            <div id="error_messages"></div>
            {{ element.messages }}
            {{ element.name }} {# username element #}
            {{ element.pass }} {# password element #}
            <div class="login-form__help_actions">
                <input id="show_password" class="show_password" type="checkbox" />
                <label class="password-toggle" for="show_password">Show password</label>
                <a href="/user/password" class="forgot-password">Forgot Password?</a>
            </div>
            {{ element.form_build_id }} {# required #}
            {{ element.form_id }} {# required #}
            <div class="login-form__submit">
                {{ element.actions.submit }}
            </div>
        </div>
    </form>
</div>

```

if the template is not valid, you should try to add it.

```
function Yourtheme_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {

  if ($hook == 'form' & !empty($variables['element']['#id'])) {
    $suggestions[] = 'form__' . str_replace('-', '_', $variables['element']['#id']);
  }
}

```

then create `form--user-login-form.html.twig` in your theme.

do not forget to clear the cache.
> 2 votes

# Answer
In addition to Yuseferis answer:

I'm using this function to add theme suggestions for forms in Drupal 10:

```
/**
 * Implements hook_theme_suggestions_HOOK_alter() for form templates.
 *
 * Make forms themeable:
 * e.g. => form--user-login-form.html.twig
 */
function YOURTHEME_theme_suggestions_form_alter(array &$suggestions, array $variables) {
  if (!empty($variables['element']['#form_id'])) {
    $suggestions[] = 'form__' . $variables['element']['#form_id'];
  }
}

```
> 3 votes

---
Tags: 8, theming, forms
---


# Question
Title: Acquia BLT - How to put remote config_split config values back into version control
I have been using Acquia BLT and config split.

I understand how to set up the config splits and deploy them using BLT.

What I don't understand is - once I have a split in place, say on dev, and I've changed the configuration on dev... how do I get that changed configuration which is only in the dev database back into version control?

Doing a `cex` command on the Acquia server doesn't work - I get a long list of permission denied errors (presumably because without livedev mode on, the code on the Acquia server is read only).

```
...
[warning] unlink(/mnt/www/html/xxxx/config/default/workflows.workflow.editorial.yml): Permission denied FileSystem.php:124
 [error]  The file permissions could not be set on /mnt/www/html/xxxx/config/default.

```

So how can I export the config from dev once I've changed it, and get it into my version control system?

Addition: I am expecting that I would have my `/config/envs/{env}` directory on my local containing the remote yaml config files, so that I could track changes to the split configuration across environments. But maybe this isn't true?

# Answer
> 1 votes
What I usually do is get the relevant file's config on the server via `drush cget ...` or by alias and put it in the relevant split YAML in VCS. This assumes your split config doesn't cover a whole lot of configuration.

---
Tags: configuration, deployment, acquia-cloud
---


title: How can I email admin when stock is 0?

text:
# Question
Title: How can I email admin when stock is 0?
I'd like to email the admin when the stock is 0.
In one option, I've tried to set a condition in rules based on the stock field, but I can't get the field to display in *Entity has Bundle*.

Are there other options?

I am using Drupal 9.5.10, Commerce Core 8.x-2.36, and Commerce Stock 8.x-1.1.

# Answer
> 1 votes
By looking at the code proposed by the module `commerce_stock` I believe you'll have to write a new EventSubscriber that subscribe to the event `onOrderComplete`.

So you create the file: `modules/custom/my_custom_commerce_stock/src/EventSubscriber/SendEmailWhenNoStockSubscriber.php`

```
<?php

namespace Drupal\my_custom_commerce_stock\EventSubscriber;

class SendEmailWhenNoStockSubscriber implements EventSubscriberInterface {

  public static function getSubscribedEvents() {
    'commerce_order.post_transition' => 'onOrderComplete',
  }

  public function onOrderComplete(WorkflowTransitionEvent $event) {
    // code to send email.
  }

}

```

If you don't know how to send an email with Drupal, this is very well documented:

If you don't want to code, you can try the following module https://www.drupal.org/project/commerce\_stock\_notifications

---
Tags: commerce, emails
---


# Question
Title: How do you programmatically get custom content field data from commerce product?
**Background:** I'm creating a rule that runs after an order is submitted that checks all the line items for any backorder and emails the customer. In the PHP function I've been able to use entity\_metadata\_wrapper(), commerce\_line\_item\_load(), and commerceproduct\_load()to successfully get the product information as seen in the var\_dump() below. Now I need to get the available stock stored in the Colorway content type.

**edit:** The Colorway content type is a node with a reference field to commerce products. The function is located inside a custom module we named commerce\_overides. it just contains various hooks and functions directly related to commerce. There are no includes.

**Question** How do I get the fields stored in the Colorway content type? The product has the same sku number as the Colorway as seen below; However, this only made it easy to get the product into the node but not the other direction.

# Answer
> 0 votes
After trying just about everything I finally figured it out. I needed to use EntityFieldQuery(). this allowed me to use the sku from the commerce product and find the matching fabric\_colorway node. then I just used the nid that spit out to load the entire node and get the field I needed.

I did need to add other conditions to the query such as only wanting to look at published nodes and returning only the first result, but the basics are here for anyone else needing them.

```
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'fabric_colorways')
  ->propertyCondition('status', NODE_PUBLISHED)
  ->fieldCondition('field_sku', 'value', $sku)
  ->range(0, 1)
  ->addMetaData('account', user_load(1));

$result = $query->execute();

foreach ($result['node'] as $r) {
  $nid = $r->nid;
}

$node = node_load($nid);

```

---
Tags: 7, commerce
---


# Question
Title: How do you programmatically include an entity type to a workflow?
I have a workflow to which I want to include entity/content types programmatically since these content types will be included to the system by the installation of the module to which they reside. I'm not sure how to load the specific workflow object and attach the entity type to that via code.

# Answer
You need the addEntityTypeAndBundle method from ContentModerationInterface

A static way to implement it looks like:

```
$workflow = \Drupal::entityManager()->getStorage('workflow')->load([workflow_id]);

$workflow->getTypePlugin()->addEntityTypeAndBundle('node', 'article');

$workflow->save();

```
> 3 votes

# Answer
I think you will need to load the workflow configuration as editable and modify the entity values in the type\_settings.

Here's the quick code used to see how this was structured:

```
$config = \Drupal::config("workflows.workflow.editorial");
$settings = $config->get('type_settings');
print_r($settings['entity_types']);

```

Output:

```
Array
(
    [node] => Array
        (
            [0] => basic_page
        )

)

```
> 0 votes

# Answer
This is now entityTypeManager rather than entityManager:

```
  // Add bundle to default workflow
  $workflow = \Drupal::entityTypeManager()->getStorage('workflow_type')->load('workflow_id');
  $workflow = Workflow::load('workflow_id');
  $workflow->getTypePlugin()->addEntityTypeAndBundle("entity_type_id", "entity_bundle_id");
  $workflow->save();

```
> 0 votes

---
Tags: 8, workflows
---


# Question
Title: Is there a reliable way to show Drupal messages from JavaScript?
I need to show status messages (the kind typically shown by `drupal_set_message()`) in my module's JavaScript code. How can I do this reliably, such that the theme and placement of the messages remains consistent with the way `drupal_set_message()` does it?

I'm looking for a solution that accounts for the presence or absence of prior messages on the page, and that works for any theme.

Pointing to existing modules that perform this would be great!

# Answer
> 0 votes
This API available in Drupal since 8.7.0. See details here.

Just an example:

```
const messages = new Drupal.Message();
// Probably you want to clean up previously rendered messages:
messages.clear();
messages.add('test message');
messages.warning('test warning message');
messages.error('test error message');

```

Don't forget to add a dependency for your custom library - `core/drupal.message`.

For Drupal 7 you need to use one of the contrib solutions.

# Answer
> 0 votes
I'm using Nice messages module to replace every message with a popup in the corner of the screen.

https://drupal.org/project/nicemessages

It lets you choose if you want the messages of a status to stay visible until closed, or auto close after x seconds. And add a handy "close all" if there are more than one.

If anything, check out how it works. It's a good starting point i guess.

# Answer
> 0 votes
There are various modules out there that can replace the use of drupal\_set\_message or the Messenger service with JavaScript based libraries. SweetAlert is one such module.

You could replace the Messenger service with your own for deeper customization, too.

Like the JavaScript based tools, your implementation code could theme the response as a message and write it into the area it should appear.

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


title: How can I identify the service ID?

text:
# Question
Title: How can I identify the service ID?
I am trying to use Cdn service provided in CDN module version 4.0.1 in my custom module Until 3.x version we had service id as cdn.settings

But from 4.x version I can see there is no service id

https://git.drupalcode.org/project/cdn/-/blob/4.x/cdn.services.yml?ref\_type=heads

I need to pass cdn.settings service id as an argument in my custom service but I am not able to pass due to missing service id as shown below , when I pass cdn.settings in argument it gives an error, what should be the solution for the same ?

<pre><code>    class: 'Drupal\abc_views\CDNWrapperService'
    arguments: ["@cdn.settings", "@request_stack"]```

</code></pre>

# Answer
> 2 votes
These are the first two entries in the services file you have linked:

```
services:
  Drupal\cdn\CdnSettings:
    arguments: ['@config.factory']

  Drupal\cdn\File\FileUrlGenerator:
    public: false
    decorates: file_url_generator
    arguments:
      - '@Drupal\cdn\File\FileUrlGenerator.inner'
      - '%app.root%'
      - '@stream_wrapper_manager'
      - '@request_stack'
      - '@private_key'
      - '@Drupal\cdn\CdnSettings'

```

You can see in the second service definition that the last argument is referencing the first service.

Using the class name as service ID makes it easier to autowire services, although Drupal didn't take this route for core services, they implemented aliases. See https://www.drupal.org/node/3323122

---
Tags: 10, symfony-services
---


# Question
Title: Using custom scheme (myapp://dashboard) in drupal simple-oauth2 module's redirect url
How can I use custom scheme i.e. myapp://dashboard for the redirect field of Drupal simple oauth2 module?

I get this error: 'myapp://dashboard is not a valid url'

I also tried to use the redirect module to redirect a node to this url but I got the same- invalid url error.

# Answer
> 0 votes
Yes you can add an exception. If you do not already have a `services.yml` file, copy `default.services.yml` to `services.yml`. In `services.yml` update the list of `filter_protocols` to contain the custom protocol.

# Answer
> 0 votes
I have found 3 ways to do this:

1. Create a node, in the oauth2 redirect add this node's url, using redirect module redirect this node to your custom scheme eg: myapp://dashboard.
2. Use deep linking or App Links in your app and website, verify your ownership and use Intent in your native app. Now whenever oauth2 module will redirect after verification (https://your.site/login/callback node), your app's requested screen will open and oauth2 login/authentication will get completed automatically!
3. (NOT the best method) I followed Cliefen's advice, updated the list of filter\_protocols and edited the required cell in the 'consumers' table of the database. Now it works perfectly fine! (Clear your cache)

---
Tags: uri, redirection
---


# Question
Title: How to add module libraries to the page through an admin page?
Looking for some guidance on how to create a custom module, `mymodule`, that will pull all the libraries from the custom module and display it in an admin screen. Once the libraries are displayed, I want to be able to set `Add to Pages` (checkbox) for each library to determine if it should be added to the nodes. It would be ideal if the setting became a configuration.

The goal is to be able to add any libraries I need to the custom module, but selectively add them to nodes using hook\_page\_attachments. How would I do this?

I initially tried this, but couldn't find a way to get all the libraries.

**mymodule.libraries.yml**

```
library1:
  version: 1.x
  header: true
  js:
    path/to/library/file1.js

library2:
  version: 1.x
  js:
    /path/to/library/file2.js

```

**mymodule.module**

```
/**
 * Implements hook_page_attachments().
 */
function mymodule_page_attachments(array &$attachments) {
  $libraries = [
    'mymodule/library1',
    'mymodule/library2',
  ];

  foreach($libraries as $library) {
    $attachments['#attached']['library'][] = $library;
  }
}

```

# Answer
Your module is referencing the library names wrong. It should be “mymodule/library\_name” instead of just the library name.

As long as you get that right, it wouldn’t be hard to loop node field values or a config object and add them like that.
> 0 votes

# Answer
Replace:

```
js:
    path/to/library/file1.js

```

With

```
js:
    path/to/library/file1.js: {}

```
> 0 votes

---
Tags: 8, hooks
---


title: Struggling to enable twig debugging

text:
# Question
Title: Struggling to enable twig debugging
Update: I've realized that neither my settings nor settings.local files are doing anything. I placed `die()` and print statements throughout both files, rebuilt cache, and see nothing. I'm stumped.

Update 2: I added the output from `ddev drush status` at the bottom of the post

Default Drupal 10 site built by Pantheon. The only thing I've done besides setting up these files was update the permission for settings.php and services.yml

```
chmod 644 sites/default/settings.php
chmod 444 sites/default/services.yml

```

Banging my head against the wall on this. I can't seem to get twig debugging of any kind working, even going directly into my services.yml file and switching it to true.

I've looked through the drupal and ddev docs and what I can find on google, fiddled with all of the following files, rebuilt cache, restarted DDEV, etc. I can't seem to get it working.

I'm using a Mac, if that matters.

Any help is greatly appreciated. Here is my sites/development.services.yml:

```
# Local development services.
#
# To activate this feature, follow the instructions at the top of the
# 'example.settings.local.php' file, which sits next to this file.
parameters:
  http.response.debug_cacheability_headers: true
  twig.config:
    debug: true
    auto_reload: true
    cache: false
services:
  cache.backend.null:
    class: Drupal\Core\Cache\NullBackendFactory

```

in my sites/default folder:

settings.php:

```
<?php

/**
 * Load services definition file.
 */
$settings['container_yamls'][] = __DIR__ . '/services.yml';

/**
 * Include the Pantheon-specific settings file.
 *
 * n.b. The settings.pantheon.php file makes some changes
 *      that affect all environments that this site
 *      exists in.  Always include this file, even in
 *      a local development environment, to ensure that
 *      the site settings remain consistent.
 */
include __DIR__ . "/settings.pantheon.php";

/**
 * Skipping permissions hardening will make scaffolding
 * work better, but will also raise a warning when you
 * install Drupal.
 *
 * https://www.drupal.org/project/drupal/issues/3091285
 */
// $settings['skip_permissions_hardening'] = TRUE;

/**
 * If there is a local settings file, then include it
 */
$local_settings = __DIR__ . "/settings.local.php";
if (file_exists($local_settings)) {
  include $local_settings;
}

// Automatically generated include for settings managed by ddev.
$ddev_settings = dirname(__FILE__) . '/settings.ddev.php';
if (getenv('IS_DDEV_PROJECT') == 'true' && is_readable($ddev_settings)) {
  require $ddev_settings;
}

```

settings.ddev.php:

```
<?php

/**
 * @file
 * #ddev-generated: Automatically generated Drupal settings file.
 * ddev manages this file and may delete or overwrite the file unless this
 * comment is removed.  It is recommended that you leave this file alone.
 */

$host = "db";
$port = 3306;
$driver = "mysql";

// If DDEV_PHP_VERSION is not set but IS_DDEV_PROJECT *is*, it means we're running (drush) on the host,
// so use the host-side bind port on docker IP
if (empty(getenv('DDEV_PHP_VERSION') && getenv('IS_DDEV_PROJECT') == 'true')) {
  $host = "127.0.0.1";
  $port = 49474;
}

$databases['default']['default']['database'] = "db";
$databases['default']['default']['username'] = "db";
$databases['default']['default']['password'] = "db";
$databases['default']['default']['host'] = $host;
$databases['default']['default']['driver'] = $driver;
$databases['default']['default']['port'] = $port;

$settings['hash_salt'] = 'REMOVED FOR SECURITY';

// This will prevent Drupal from setting read-only permissions on sites/default.
$settings['skip_permissions_hardening'] = TRUE;

// This will ensure the site can only be accessed through the intended host
// names. Additional host patterns can be added for custom configurations.
$settings['trusted_host_patterns'] = ['.*'];

// Don't use Symfony's APCLoader. ddev includes APCu; Composer's APCu loader has
// better performance.
$settings['class_loader_auto_detect'] = FALSE;

// Set $settings['config_sync_directory'] if not set in settings.php.
if (empty($settings['config_sync_directory'])) {
  $settings['config_sync_directory'] = 'sites/default/files/sync';
}

// Override drupal/symfony_mailer default config to use Mailhog
$config['symfony_mailer.mailer_transport.sendmail']['plugin'] = 'smtp';
$config['symfony_mailer.mailer_transport.sendmail']['configuration']['user']='';
$config['symfony_mailer.mailer_transport.sendmail']['configuration']['pass']='';
$config['symfony_mailer.mailer_transport.sendmail']['configuration']['host']='localhost';
$config['symfony_mailer.mailer_transport.sendmail']['configuration']['port']='1025';

// Enable verbose logging for errors.
// https://www.drupal.org/forum/support/post-installation/2018-07-18/enable-drupal-8-backend-errorlogdebugging-mode
$config['system.logging']['error_level'] = 'verbose';

```

finally, settings.local.php:

```
<?php

// phpcs:ignoreFile

/**
 * @file
 * Local development override configuration feature.
 *
 * To activate this feature, copy and rename it such that its path plus
 * filename is 'sites/default/settings.local.php'. Then, go to the bottom of
 * 'sites/default/settings.php' and uncomment the commented lines that mention
 * 'settings.local.php'.
 *
 * If you are using a site name in the path, such as 'sites/example.com', copy
 * this file to 'sites/example.com/settings.local.php', and uncomment the lines
 * at the bottom of 'sites/example.com/settings.php'.
 */

/**
 * Assertions.
 *
 * The Drupal project primarily uses runtime assertions to enforce the
 * expectations of the API by failing when incorrect calls are made by code
 * under development.
 *
 * @see http://php.net/assert
 * @see https://www.drupal.org/node/2492225
 *
 * It is strongly recommended that you set zend.assertions=1 in the PHP.ini file
 * (It cannot be changed from .htaccess or runtime) on development machines and
 * to 0 or -1 in production.
 *
 * @see https://wiki.php.net/rfc/expectations
 */
assert_options(ASSERT_ACTIVE, TRUE);
assert_options(ASSERT_EXCEPTION, TRUE);

/**
 * Enable local development services.
 */
$settings['container_yamls'][] = DRUPAL_ROOT . '/sites/development.services.yml';

/**
 * Show all error messages, with backtrace information.
 *
 * In case the error level could not be fetched from the database, as for
 * example the database connection failed, we rely only on this value.
 */
$config['system.logging']['error_level'] = 'verbose';

// Enable Twig debugging.
$settings['twig_debug'] = TRUE;

/**
 * Disable CSS and JS aggregation.
 */
$config['system.performance']['css']['preprocess'] = FALSE;
$config['system.performance']['js']['preprocess'] = FALSE;

/**
 * Disable the render cache.
 *
 * Note: you should test with the render cache enabled, to ensure the correct
 * cacheability metadata is present. However, in the early stages of
 * development, you may want to disable it.
 *
 * This setting disables the render cache by using the Null cache back-end
 * defined by the development.services.yml file above.
 *
 * Only use this setting once the site has been installed.
 */
$settings['cache']['bins']['render'] = 'cache.backend.null';

/**
 * Disable caching for migrations.
 *
 * Uncomment the code below to only store migrations in memory and not in the
 * database. This makes it easier to develop custom migrations.
 */
# $settings['cache']['bins']['discovery_migration'] = 'cache.backend.memory';

/**
 * Disable Internal Page Cache.
 *
 * Note: you should test with Internal Page Cache enabled, to ensure the correct
 * cacheability metadata is present. However, in the early stages of
 * development, you may want to disable it.
 *
 * This setting disables the page cache by using the Null cache back-end
 * defined by the development.services.yml file above.
 *
 * Only use this setting once the site has been installed.
 */
$settings['cache']['bins']['page'] = 'cache.backend.null';

/**
 * Disable Dynamic Page Cache.
 *
 * Note: you should test with Dynamic Page Cache enabled, to ensure the correct
 * cacheability metadata is present (and hence the expected behavior). However,
 * in the early stages of development, you may want to disable it.
 */
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null';

/**
 * Allow test modules and themes to be installed.
 *
 * Drupal ignores test modules and themes by default for performance reasons.
 * During development it can be useful to install test extensions for debugging
 * purposes.
 */
# $settings['extension_discovery_scan_tests'] = TRUE;

/**
 * Enable access to rebuild.php.
 *
 * This setting can be enabled to allow Drupal's php and database cached
 * storage to be cleared via the rebuild.php page. Access to this page can also
 * be gained by generating a query string from rebuild_token_calculator.sh and
 * using these parameters in a request to rebuild.php.
 */
$settings['rebuild_access'] = TRUE;

/**
 * Skip file system permissions hardening.
 *
 * The system module will periodically check the permissions of your site's
 * site directory to ensure that it is not writable by the website user. For
 * sites that are managed with a version control system, this can cause problems
 * when files in that directory such as settings.php are updated, because the
 * user pulling in the changes won't have permissions to modify files in the
 * directory.
 */
$settings['skip_permissions_hardening'] = TRUE;

/**
 * Exclude modules from configuration synchronization.
 *
 * On config export sync, no config or dependent config of any excluded module
 * is exported. On config import sync, any config of any installed excluded
 * module is ignored. In the exported configuration, it will be as if the
 * excluded module had never been installed. When syncing configuration, if an
 * excluded module is already installed, it will not be uninstalled by the
 * configuration synchronization, and dependent configuration will remain
 * intact. This affects only configuration synchronization; single import and
 * export of configuration are not affected.
 *
 * Drupal does not validate or sanity check the list of excluded modules. For
 * instance, it is your own responsibility to never exclude required modules,
 * because it would mean that the exported configuration can not be imported
 * anymore.
 *
 * This is an advanced feature and using it means opting out of some of the
 * guarantees the configuration synchronization provides. It is not recommended
 * to use this feature with modules that affect Drupal in a major way such as
 * the language or field module.
 */
$settings['config_exclude_modules'] = ['devel', 'stage_file_proxy'];

```

`ddev drush status`:

```
Drupal version   : 10.1.2
Site URI         : https://evan-poe-drupal-showcase.ddev.site
DB driver        : mysql
DB hostname      : db
DB port          : 3306
DB username      : db
DB name          : db
Database         : Connected
Drupal bootstrap : Successful
Default theme    : olivero
Admin theme      : claro
PHP binary       : /usr/bin/php8.1
PHP config       : /etc/php/8.1/cli/php.ini
PHP OS           : Linux
PHP version      : 8.1.21
Drush script     : /var/www/html/vendor/bin/drush
Drush version    : 12.1.3.0
Drush temp       : /tmp
Drush configs    : /var/www/html/vendor/drush/drush/drush.yml
Install profile  : standard
Drupal root      : /var/www/html/web
Site path        : sites/default
Files, Public    : sites/default/files
Files, Private   : sites/default/files/private
Files, Temp      : /tmp

```

# Answer
Since Drupal 10.1.0 Twig debugging seems to be actived/deactivated according some settings stored in the `state` table: Change record.

This prevents that these settings can be accidentally committed. And it also seems that these settings take precedence over the old way of having the settings.local file load a certain services YAML with putting `debug: true` in `twig.config`.

Instead you now enable Twig debug mode either in the UI at https://example.com/admin/config/development/settings or enable it directly on the command line with Drush:

```
# Enable Twig debug mode in Drupal 10
drush twig:debug on && \
drush state:set disable_rendered_output_cache_bins 1 --input-format=integer  && \
drush cache:rebuild

# Disable Twig debug mode in Drupal 10
drush twig:debug off && \
drush state:set disable_rendered_output_cache_bins 0 --input-format=integer && \
drush cache:rebuild

```
> 8 votes

---
Tags: theming, debugging, 10
---


# Question
Title: Install and enable 'Real AES' module: Dependency with Defuse PHP-encryption library
I downloaded the real\_aes-8.x-2.2.zip file from the Real AES project page, unzipped and copied it to contrib module folder (/var/www/html/modules/contrib).

While trying to enable this module using `drush en real_aes`, I get below error:

> Module real\_aes doesn't meet the requirements to be enabled. \[error\] Please install the Defuse PHP-encryption library via Composer. See README.txt (Currently using Defuse PHP-Encryption\[error\] library version Not Installed)

So now I ran the command `composer require defuse/php-encryption` to install Defuse PHP-encryption. I could see that it is downloaded to the location /var/www/html/vendor.

After this, even though the Defuse PHP-encryption is downloaded, if I try to enable the Real AES module using Drush command and also tried Drupal module interface, it still throws the above error.

* Drupal version: 8.6.5
* PHP Version : 7.0.32
* Drush version: 8.1.18

Any help appreciated resolving this issue.

# Answer
> 0 votes
Founded solution:

1. Download Ludwig - https://www.drupal.org/project/ludwig
2. Install module and go to admin/reports/packages - https://www.drupal.org/docs/contributed-modules/ludwig/installation-and-usage
3. Install automatically or add manually to folders:

* modules/address/lib/doctrine-collections/1.8.0
* modules/address/lib/doctrine-deprecations/v1.0.0
* modules/address/lib/commerceguys-addressing/v1.4.2
* modules/commerce/lib/commerceguys-intl/v2.0.1

4. Next clear the cache - admin/config/development/performance

Now u can install all modules :)

---
Tags: 8, installation, composer
---


# Question
Title: Website doesn't load properly from htdocs/web
Built a website on localhost, moved it to shared-hosting where webroot is `htdocs` but when visiting the website through the hosting's given IP address it obviously doesn't load the website, because the index.php is inside `htdocs/web/`?

This is very limited shared-hosting, no control panel and no way to edit apache's configs, only .htacess files accessible in `htdocs`.

Current attempts:

a. Homepage loads fine, but `/web/` is added in the URL in the address bar for every sub-page.

```
RewriteEngine On
RewriteRule ^(.*)$ /web/$1 [L]

```

b. Homepage loads and no `/web/` is added for any links in e.g. main menu navigation while from homepage and clicking them even loads the page without `/web/` added to the URL, but the `/web/` is added back to the menu once you're within any subpage.

```
 RewriteRule ^(.*)$ web/$1 [L,NC]

```

Menu links from homepage

Same menu links from within subpages

Interesting find, while you can visit content pages from menu links, you cannot access e.g. `/user` when trying to login, you get WSOD `Redirects to external URLs are not allowed by default, use \Drupal\Core\Routing\TrustedRedirectResponse for it.` You have to enter `web/user` in order to login.

**update:** Similar issue described here https://www.drupal.org/forum/support/installing-drupal/2022-02-21/redirects-to-external-urls-are-not-allowed-by-default-use-drupalcoreroutingtrustedredirectresponse#comment-14996104 but no actual solution, only the mention of the redirection to /web/? How to redirect properly without /web/ showing in URL adress bar?

# Answer
> This is very limited shared-hosting, no control panel and no way to edit apache's configs, only .htacess files accessible in htdocs

Look for a new hosting company, until then you can use the legacy composer project:

```
composer create-project drupal/legacy-project my_site_name_dir

```

and then require all the components you had before.

Instead of install.php for a new database, you can put a copy of the existing database and sites/default/files directory in the fresh composer project and clear the cache. If this produces errors, check that you have exactly the same versions of all modules.
> 3 votes

---
Tags: uri, redirection, .htaccess, 10
---


# Question
Title: Why does my view duplicate the same content ( translation )?
I have a multilingual site for **Properties** with 2 languages ( English - Arabic ) and I have a view that give me the all properties that I need to sell.

But when I enter to this view every multilingual content will duplicate like is shown in this image:

This is the **filter criterion** :

Any idea to solve the duplication problem?

# Answer
> 3 votes
after searching I found the solution for my problem :

This may happen if you have applied filters on any date field. So.

in Views Advanced Settings under OTHER options, select "Query Setting" and check "Distinct" option.

That's it .

# Answer
> 1 votes
You need to add a filter by language as well. You can set the value to "Current user's language" to make it select the language based on the current selected language in the site. You can also create two views displays, one for each language.

# Answer
> 1 votes
Try using the Internationalizations Views module, which extends the i18n module with multilingual support for Views.

It allows to add the translated field as a filter instead of the original one, which may be what you're looking for.

True, the Internationalizations Views module only has a **DEV** version for D7, but right now there are over 31K users using this version. Therefor I think "DEV" is not a valid release qualifier for that version anymore, because *+31K users can't be wrong*, right?

**Note**: Filtering Views results in a multi language site can sometimes be challenging, as illustrated also in discussions such as in How to filter views results to the current language nodes.

# Answer
> 1 votes
I had the same problem in D8, I simply solved adding in the view a filter "Content: Translation language" and setting it to " Interface text language selected for page":

**NO need** to set DISTINCT or REDUCE DUPLICATES

# Answer
> 0 votes
I don't see any entity translation in core, and following the documentation says to use "Content Translation".

I have solved my problem following the solution of adding a new "Filter Creteria" in the view (Content: Translation language (= Interface text language selected for page) described in https://www.drupal.org/forum/support/translations/2016-11-24/solved-translated-content-duplicate-on-a-view-with-choosen

# Answer
> 0 votes
If you have content in multilanguages you have to make some changes to your view.

Firstly, you have to go to the "Filter criteria" section and add a new rule, such like this:

Then you have to "Language" section and add this:

And finally you have to "Query settings" and check the Distrit data

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