# Question
Title: How do I re-order a node's body and link fields in my Bartik subtheme?
I have a simple subtheme of the standard Bartik theme in Drupal 9.3.0. By default, when a `node` is rendered, its `links`, eg. "read more", "log in", come before the `body`.

For example,

```
<div class="node__content clearfix">
  <div class="node__links">
    <ul class="links inline">
      <li class="node-readmore"><a href="/node/11" rel="tag" >Read more</a></li>
      <li class="comment-forbidden"><a href="/login?destination=/comment/reply/node/11/comment_node_story%23comment-form">Log in</a> to post comments</li>
    </ul>
  </div>
  <div class="clearfix text-formatted field field--name-body ...">
    <p>Body teaser ...</p>
  </div>
</div>

```

I want to swap the two components, ie. `body` and `links`, so that the `body` is rendered first and the `links` second. However, I can't determine which template to override to do this.

`node.html.twig` contains:

```
<div{{ content_attributes.addClass('node__content', 'clearfix') }}>
  {{ content }}
</div>

```

which suggests that `{{ content }}` consists of the `links` and `body`. However I can't figure out where its rendering takes place.

Can anyone point me in the right direction?

# Answer
```
{{ content }}

```

contains everything, you can be more granular and replace it with, for example:

```
{{ content.title }}
{{ content.body }}
{{ content.field_name }}
{{ content.links }}

```
> 2 votes

# Answer
Simply go to Structure \> Content types \> My content type \> Manage display.

https://example.com/admin/structure/types/manage/page/display.

There you re-order fields displayed in your default frontend theme with a couple of clicks, *export* config, done. For deployment `git push` the exported config files, on prod `git pull` it again and now *import* config, done.

You can also use the Field Group module if you feel the need to add additional wrappers around any group of fields through the UI.

By templating all the things you defeat the Field UI while the display settings are always the first place where any future maintainer of that site will look why something looks odd or simply wants to change a formatter and then might wonder why it has no effect. "Damn, I need to look through the templates now and code the stuff that could have been changed with one click."

Only template when you really have the need to adjust the markup to more advanced needs like when working with web components or some fancy JS plugin for slideshows that has no Drupal module yet but requires certain markup nesting.
> 1 votes

# Answer
In your node template say "node--article.html.twig" you can reorder links and body as follow.

```
<div{{ content_attributes.addClass('content') }}>
{{ content.body }}
{{ content.links }}

```
you can also use {{ kint(content) }} in your template to view other things as follow.
> 0 votes

---
Tags: theming
---


title: How can I print subparagraphs?

text:
# Question
Title: How can I print subparagraphs?
I have a content type with a paragraph field. That paragraph field has two paragraph fields which I will refer to as subparagraphs.

I want to print one of the two subparagraphs depending on the flag set in the preprocess function.

Paragraph: field\_banner\_header

Subparagraphs: field\_banner\_header\_single, field\_banner\_header\_multi

Twig:

```
<div class="callout-options">
    {% if callout_options == 'Single' %}
        {{ content.field_banner_header[0]['#node'].field_banner_header_single.value }}
    {% else %}
        {{ content.field_banner_header[0]['#node'].field_banner_header_multi.value }}
    {% endif %}
</div>

```

I have a preprocess hook that stores the value ('Single' or 'Multi') of a bool in callout\_options:

```
function cse_preprocess_node(&$variables) {
  $node = $variables['elements']['#node'];

  if ($node->getType() == 'unit_landing_page') {
    $variables['callout_options'] = $node->get('field_active_callout_tab')->value;
  }
}

```

On page render, I get the following error:

> drupal.js?v=8.4.6:13 Uncaught Quick Edit could not associate the rendered entity field markup (with \[data-quickedit-field-id="paragraph/426/field\_banner/en/default"\]) with the corresponding rendered entity markup: no parent DOM node found with \[data-quickedit-entity-id="paragraph/426"\]. This is typically caused by the theme's template for this entity type forgetting to print the attributes.

I could be wrong, but this seems to be telling me that I am referencing the subparagraph incorrectly.

What is the correct syntax for printing a subparagraph?

# Answer
Figured it out. The trouble was the Boolean values were being treated as markup so I added \['#markup'\] to the conditional like so:

```
{% if content.field_active_callout_tab.0['#markup'] == 'Single' %}
    {{ content.field_banner_header_single.0 }}
{% else %}
    {{ content.field_banner_header_multi.0 }}
{% endif %}

```

I discovered this by passing the boolean field (field\_active\_callout\_tab) to the kint module and inspecting its attributes.
> 1 votes

# Answer
Seems your preprocess function is the key. To get the value of a field, do the following:

```
$callout_tab = $node->get('field_active_callout_tab')->first()->getValue();
$variables['callout_options'] = $callout_tab['value'];

```

Really, please install the Devel submodule Kint and then check first what you get:

```
ksm($node->get('field_active_callout_tab')->value);

```

Which will most likely get you `NULL` or an array. So `{% if callout_options == 'Single' %}` can never work.

---

And regarding the subparagraph, all I could get was the entity ID:

```
{{ kint(content.field_paragraphs.0['#paragraph'].get('field_subparagraph').value) }}

```

but maybe I'm doing something wrong (and you already solved that yourself). But if the entity ID really is the maximum you can get you are better off loading the subparagraph in the preprocess function as well and pass the render array over to Twig like you did pass the bool. In theory this should work :)
> 1 votes

# Answer
With the help of Twig Tweak Module, you can print subparagraphs content in the right context :

```
 {{ drupal_field('field_paragraph', 'paragraph', paragraph_id) }}

```

Here is the example documentation.
> 1 votes

---
Tags: 8, theming, hooks, paragraphs
---


# Question
Title: views_embed_view() ignores template file using Ajax
I have a view shown in two ways. Once I show it as a normal block and one time using `views_embed_view()` in combination with Ajax.

For the regular block I created a `views-view-list.html.twig` template in my theme adding a `div` wrapper. My styling is based on this added div.

For the embedded block, this `views-view-list.html.twig` block is ignored and therefor the styling is off.

Using `views_embed_view()` inside a `preprocess` does work the way you'd expect, but using it with Ajax ignores the templates.

How can I make sure the template is not ignored, or is there a way to add another template that is seen when embedding the view?

I have a custom module *my\_view\_ajax*

I attach the js file in my *.module* file:

```
function my_view_ajax_preprocess_node(&$variables) {
  $node = $variables['node'];
  //check content type
  if ($node->getType() == 'article' || $node->getType() == 'issue' ) {
    $variables['#attached']['library'][] = 'my_view_ajax/my_view_ajax__js';
  }
}

```

In my *.js* file I use Ajax to get my views block.

```
const routing_url = '/custom/ajax/articles';
$.ajax({
  type: 'GET',
  url: routing_url,
  data: 'nid='+nid,
  dataType: 'html',
  async: true,
  complete: function (data) {
    $containerContent.empty().html(data.responseText);

    $containerContent.fadeIn();
    $ajaxLoader.fadeOut();
  }
});

```

In my `routing.yml` I create the Ajax path

```
my_view_ajax.articles:
  path: '/custom/ajax/articles'
  defaults:
    _title: 'Articles'
    _controller: '\Drupal\my_view_ajax\Controller\viewsajaxController::issueArticles'
  requirements:
    _permission: 'access content'

```

And finally in my `viewsajaxController.php`

```
namespace Drupal\my_view_ajax\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\node\Entity\Node;
use \Symfony\Component\HttpFoundation\Response;

class viewsajaxController extends ControllerBase {
  public function issueArticles() {
    $nid = 11;

    $markup = \Drupal::service('renderer')->render(views_embed_view('ccr_overview', 'block_articles_view', $nid));
    return new Response($markup);
  }
}

```

# Answer
> 0 votes
I have tried to replicate the case as follow.

1.Added following structure in views-view-table--articles.html.twig

```
<div class="example-template">
{% for row in rows %}
  {% set titletxt = '' %}
  {% set viewnod = '' %}
  {% set editnode = '' %}
    {% for key, column in row.columns %}
      {% for field in column.fields %}
        {% for content in column.content %}
          {% if field == 'title' %}
             {% set titletxt = content.field_output %}
          {% endif %}
          {% if field == 'view-node' %}
             {% set viewnod = content.field_output %}
          {% endif %}
          {% if field == 'edit-node' %}
             {% set editnode = content.field_output %}
          {% endif %}
        {% endfor %}
      {% endfor %}
    {% endfor %}
    <div>
      <h3>
        {{titletxt}}
      </h3>
      <div>
        {{viewnod}}
      </div>
      <div>
        {{editnode}}
      </div>
    </div>
{% endfor %}

```
2. In node--article.html.twig embed following view

```
 <div class="relatedarticles">
   <h2>Articles From Block View</h2>
   {% if articles %}
     {{ articles }}
   {% endif %}
 </div>

```
3. in fluffiness.theme add as follow

function fluffiness\_preprocess\_node(&$variables) { $relatedArticles = views\_embed\_view('articles', 'block\_1'); $variables\['articles'\] = \Drupal::service('renderer')-\>render($relatedArticles);
}

Then i noticed in node view mode, structure with template of view is rendered as follow.

---
Tags: views, 9
---


# Question
Title: Is there a way to control how RouteProvider caches a route?
Drupal caches routes in `cache_data`. This happens in `Drupal\Core\Routing\RouteProvider`.

I am looking at a high traffic website with "interactive" search functionality based on a map. When you resize your window or move around in the map, a couple of requests are sent to the server for search results based on the map view.

Nearly all requests will be unique, because the map coordinates are part of the request parameters. This in turn seems to flood the `cache_data` table. The `cache_data` table easily grows with 100GB in an hour, so a lot of writes are taking place.

Consequently, the database is very busy.

1. Is it possible to disable this caching?
2. If #1 is not possible, is there a way to control the `cid` of the cached routes? The route cache is essentially useless as it is now, as users never will get a cache hit. The possible combinations of query parameters are simply too big.

# Answer
> 1 votes
For high traffics sites in general you would put cache tables in memory (Redis or Memcached). Configure Redis as cache, see https://redis.io/topics/config

In this specific case, unless you want to write your own non-cacheable route provider, you could remove the query string

```
$request->server->set('QUERY_STRING', '');

```

in a kernel event request subscriber with a priority \>32. You can store the query parameters in a service class property so that the controller can retrieve them later or, if it's not your own controller, you could register a second subscriber in the same class with a lower priority to restore the query string after routing.

Restrict the special query string handling to specific paths, some system routes modify the query parameters during routing.

---
Tags: routes, 9
---


# Question
Title: Display comments only for users with "administer comments" permission
In `hook_node_view_alter`, I'm trying to restrict the display of comments to users who have the "administer comments" permission.

So far I have this but it is not working.

```
if (isset($build['comment'])) {
  if (!\Drupal::currentUser()->hasPermission('administer comments')) {
    $build['comment']['#access'] = FALSE;
  }
}

```

# Answer
> 0 votes
Solution below:

```
$build['comment']['#access'] = Drupal::currentUser()->hasPermission('administer comments');

```

---
Tags: comments
---


title: Webform two dependent select lists

text:
# Question
Title: Webform two dependent select lists
I have a content type "course" and a taxonomy vocabulary "Course categories" and a Webform "Register" the user will register by choosing the course category in select list then use the course related to this term .

Now i have a list for terms and a list for courses The problem is i don't know how to link between the two lists so the courses list show only the correct course

# Answer
Install conditional fields module and it creates relationship between fields.
> 0 votes

# Answer
I use the Client-side Hierarchical Select module with a patch that gets it to work for webforms too.
> 0 votes

---
Tags: webforms
---


# Question
Title: Has anyone tried running Drupal 9 under Windows Datacenter 2022 IIS?
We are running Drupal 9 happily under IIS and Windows Datacenter 2019 under Azure. Microsoft have released Windows Datacenter 2022 so I thought I should try to migrate to that platform. It opens find, but none of the links work, for example https://site/login gives a Page not found error. I have URL Rewrite installed and the same rules as in other environments; one is supposed to rewrite ^(.\*)$ to index.php with the Append query string set.

I suspect that URL Rewrite isn't playing ball, but I can't be sure. Has anyone else any experience?

# Answer
After lots of hunting around, and testing with another index.php file, I determined that Drupal was a red herring. the URL Rewrite module was not working. Uninstalling, rebooting the server and reinstalling it cured the problem.
> 0 votes

---
Tags: iis
---


# Question
Title: addViolation() is deprecated: how to replace it?
How to adapt the following code to avoid the deprecation of `addViolation()` according to https://www.drupal.org/node/3238432 ?

```
class MyValidator extends ConstraintValidator {

  public function validate($items, Constraint $constraint) {
    if (!$this->isValid($items)) {
      $this->context->addViolation($constraint->message); // How to adapt this line?
    }
  }
}

```

# Answer
The code shown in the question doesn't need to be changed: Once Start using the class Symfony\Component\Validator\ValidatorBuilder instead of copied classes is fixed, `$this->context` won't contain anymore an instance of `\Drupal\Core\TypedData\Validation\ExecutionContext` but `\Symfony\Component\Validator\Context\ExecutionContext`.
As the documentation says, classes that extend `ConstraintValidator` should just assume that `$this->context` is an object implementing `ExecutionContextInterface`, not which class is actually used. With that assumption, the changes introduced by that issue won't influence contrain validator classes (except for the fact the deprecation message won't be anymore triggered).
> 2 votes

---
Tags: symfony-services
---


# Question
Title: related by entity reference module views in Drupal 9
I have two content types:

Company:

* body
* field\_events (Entity reference)

Events

* body
* field\_company (Entity reference)

I have created a view that has this setup:

**View Settings**:

**Fields**:

* (field\_events: Content) Content: Title

**Filter Criteria**:

* Content: Published (= Yes)
* Content: Content type (= Company)

**Contextual Filters**:

* (field\_events: Content) Content: ID

**Relationship**:

* field\_events: Content

I have followed the instructions from: Related block by entity reference

My goal is to display similar events from the same company but excluding the current event shown in the page.

What step am I missing?

Thanks!

# Answer
> 2 votes
Follow the steps and let me know if you face the same issue

1. Click on the "advanced" tab.
2. Click on add under "contextual filters".
3. Choose Content:nid.
4. Under "when the filter variable is not available, choose "provide default value".
5. From the drop down menu select "content id from url".
6. Scroll all the way down to the bottom of the window and click on the "More" link.
7. Click "Exclude"

---
Tags: views
---


title: Redirecting to a route name

text:
# Question
Title: Redirecting to a route name
I've recently built a module. In the twig template that I render, you can delete an item. For example it goes to `/delete/item/1`. That works fine. that route triggers a delete method from my controller

```
public function deleteFittest(){
    $connection = \Drupal::service('database');
    $query = $connection->delete('user_fittests')
    ->condition('id', \Drupal::request()->query->get('id'))
    ->condition('user_id', \Drupal::currentUser()->id())
    ->execute();
    return $this->redirect_to('mib_my_fit_test.my_fittest');
}

```

After the delete, I want to redirect the user to the page that he was on, in this case the 'index' page. But none of the found redirect methods on the internet that I've found work. So what is the proper way to redirect to go to the routing name from my code example?

# Answer
I'm not sure what `redirect_to` is, that's not a method provided by Drupal or Symfony.

The standard way to redirect from a controller, i.e. one that extends `Drupal\Core\Controller\ControllerBase`, is:

```
return $this->redirect('route.name');

```
> 2 votes

# Answer
It seems you ask to redirect from a controller, but in case you need to redirect from a form :

If you want to redirect from a form embedded in a renderable array of a controller, you can use

```
$form_state->setRedirect('route.name');

```
> 0 votes

---
Tags: redirection
---


# Question
Title: Is it possible to render a region in a menu template?
In my Drupal 8 theme I have a template called \__menu.html.twig which gets called in my page.html.twig

I am trying to render a region within the \__menu.html.twig where I can place blocks.

I have rendered the region within my theme.info. How can I declare the region in \__menu.html.twig?

# Answer
> 0 votes
I'm not sure if this will answer your question as you are stating that you want to render a region in the menu template. You can't do this in the traditional sense but you can use Twig Tweak to render blocks pretty much in any template assuming you have the right context.

See their help pages for good documentation on how to do this.

As an example, to render a block in any template, you'd write something like this:

```
{{ drupal_block('plugin_id', {label: 'Example'|t, some_setting: 'example', setting_array: {value: value}}) }}

```

You can also render views and full entities which comes in handy as well, for example:

```
{{ drupal_entity('block_content', 1) }}

```

In general, Twig tweak is a super handy module that we use pretty much on most D8/D9 projects.

---
Tags: 8, theming, navigation
---


# Question
Title: Get the value of Entity reference revisions field in order email twig file
I want to get the entity reference field value in order email.

Name of the entity reference is `field_price_value` and called paragraph field is `field_price` now I want to get the field price value I tried below method but none work for me

```
 order_entity.field_price_value.field_price.value

 {% for order_item in order_entity.getItems %}

{{ order_item.getPurchasedEntity.getfield_price_value.getfield_price

{% endif %}

```

# Answer
I think you would do it like this (if I'm understanding your scenario correctly):

```
{{ node.field_price_value.entity.field_price.value }}

```

Also this question has been asked and responded to before, you may find this helpful: Twig get value of field in entity reference

Good luck!
> 1 votes

---
Tags: 8, commerce
---


# Question
Title: After updating from 9.2 to 9.3, my site breaks, but turning CSS/JS aggregation off fixes it. What can I change to make it so I can turn it back on?
After updating from 9.2 to 9.3, my site breaks. When I turn off CSS and JavaScript aggregation, it fixes my 9.3 versioned site. I would like to turn it on as that would speed up my site. Normally I find the issue is that the correct owner isn't in place or the permissions are off. My `sites/default/files` directory seems to have the correct permissions of 775 and the correct owner, being the server. The js and css directory in the files directory have the same permissions and owner as the files directory. I have also been clearing the cache. I have also run cron. Also, It is only an issue when I am logged in. Anonymous users wouldn't notice the difference.

# Answer
> 1 votes
I found the issue! This link talks about how previously, if a module required for example core/jquery.ui.dialog, Seven and Claro removed files that were breaking the layout. With this change, this override was removed, and broke my site. I read someone had this issue when using admin toolbar search, and this was my issue as well. I just uninstalled it and everything worked. While I will be taking jQuery out to prepare for D10, this will be fixed in D9 and needs review.

---
Tags: 9, css-js-aggregation
---


# Question
Title: Status page shows "Mismatched Entity.." for a Paragraph field but Drush entup give error "..storage cannot change the schema for an existing field"
I'm stuck in a loop. The Drupal 9.3 status page shows the following error:

```
Mismatched entity and/or field definitions
The following changes were detected in the entity type and field definitions.
Paragraph
The paragraph.field_heading field needs to be updated.

```

When I run `drush entup` I get the below error. I have a lot of data in the mentioned field so I can't delete the field. How did this mismatch happen and why can't `entup` resolve it?

# Answer
> 5 votes
*With this new information do you have any suggestions on how to fix the error?*

This schema mismatch in a plain text field doesn't normally happen. You can't change the maximum length in UI, it's not allowed if the field contains data. And you can't import a modified field storage definition, this throws the same error as above and stops the import. So it's unclear how you did this, but the fix is then to use the same way to change it back.

---

*Why can't entup resolve it?*

See https://www.drupal.org/project/devel\_entity\_updates

---
Tags: drush, paragraphs
---


# Question
Title: Disable submissions basing on a form element value/selection
I know I can turn submissions being saved in the database either on or off completely.

Is there a way I can avoid the submission is saved basing on the value selected for a form element, for example a *Yes/No* radio button?

# Answer
You can use a WebformSettingsHandler to conditionally disable the saving of results.
> 3 votes

---
Tags: webforms
---


# Question
Title: Safely save data to the order in onNotify()
I'm new to Drupal and have to make an off-site payment gateway (with Drupal Commerce 2). It all works, but sometimes it doesn't.

The remote payment provider's server sends notification requests to the server, about the status of the payment, so I have both `onReturn` and `onNotify` in the PaymentGateway class.

Since `onReturn` is not guaranteed to be called (the customer might close the browser, etc, and the provider does not necessarily send him back in my case), but `onNotify` is guaranteed to be called, I create and save the `Payment` object in `onNotify`, not in `onReturn`, when the payment is complete. (This is also what the documentation suggests to do: https://docs.drupalcommerce.org/commerce2/developer-guide/payments/create-payment-gateway/off-site-gateways/handling-ipn)

So my code looks something like this. (It's a very simplified pseudo-code; validation checks aren't included.)

```
class RedirectCheckout extends OffsitePaymentGatewayBase implements SupportsNotificationsInterface {

  public function onReturn() {
    $is_order_accepted = /* Check the remote payment provider has accepted the order */
    if (!$is_order_accepted) {
       throw new NeedsRedirectException()
    }
    // If all is good, do nothing.
  }

  public function onNotify() {
    /** @var OrderInterface $order */
    $order = /* Load the order the notification is about */

    $is_order_accepted = /* Check the remote payment provider has accepted the order */
    if ($is_order_accepted) {
      $payment = $payment_storage->create();
      $payment->save();
      $order->setData('transaction_id', $transactionId);
      $order->save(); // This is what sometimes overwritten by  onReturn(), I believe.
    }
  }
}

```

Notice that I need to save some data on the order, when an order is accepted (which is not available when the order is created, only when a payment has succeeded).
The Drupal Commerce documentation says you "don't need to (and should not)" touch the order, but I have to save some extra data on the order that other parts on the system expects to be there.

This often works. However, the two `onReturn` and `onNotify` requests from the remote server sometimes arrives at almost the same time, which I believe leads to a race condition.

Unfortunately, even though I am not doing anything to the order in `onReturn`, Commerce seems to still save the order. I believe this can sometime overwrite the data saved to the order by `onNotify`. For example:

* `onReturn` starts running, and loads the order (This is done by the commerce library itself, so I can't do anything about this.)
* The notify request arrives, so `onNotify` starts running, loads and saves the order, and returns
* After this, the `onReturn` method returns, gives back control to Commerce, which saves the order again; since it loaded the order object before `onNotify` saved it, it overwrites whatever `onNotify` wrote with old data

(Perhaps the converse order can also be problematic, where `onNotify` can overwrite any data saved to the order by Drupal Commerce behind the scenes, if any, during the `onReturn` request.)

Is there a good way to handle this, for example work around the race-condition to be able to save order data in `onNotify`?

I'm using Drupal 8.6.

# Answer
You are right about race condition, but onReturn does not modify order at all

This is what happens in the background:

* the `commerce_payment.checkout.return` route on commerce payment module is called which at first it let order payment gateway plugin to create an payment for order
* then no matter what happens in the onReturn method of plugin order checkout flow will be redirected on another stage (if onReturn throws exception it will be redirected to previous stage else it will be redirect to next stage)
* in this situation the method `redirectToStep` in the `Drupal\commerce_checkout\Plugin\Commerce\CheckoutFlow\CheckoutFlowBase` will modify and save order which is where the problem happens.

this is the implementation of `redirectToStep`:

```
/**
 * {@inheritdoc}
 */
public function redirectToStep($step_id) {
  if (!$this->isStepVisible($step_id)) {
    throw new \InvalidArgumentException(sprintf('Invalid step ID "%s" passed to redirectToStep().', $step_id));
  }

  $this->order->set('checkout_step', $step_id);
  $this->onStepChange($step_id);
  $this->order->save();

  throw new NeedsRedirectException(Url::fromRoute('commerce_checkout.form', [
    'commerce_order' => $this->order->id(),
    'step' => $step_id,
  ])->toString());
}

```

so to solve the problem in your onReturn method you should stand for onNotify changes to be done (a while loop which waits until changes on order are set)

hopes it helps.
> 1 votes

---
Tags: 8, commerce, payment-gateways
---


# Question
Title: Read field value from $variables in hook_preprocess_html()
I want to get a field value from a node that I can use in the *html--front.html.twig* template file.
I can create a new variable, for example with `$variables['custom_twig_variable'] = 'Some important value';`.

Then in the template file, I would simply get that value with `{{ custom_twig_variable }}`.

I don't know how to get the field value from `$variables`, the argument passed to the theme hook, whose content is the following one.

```
Array (
  [user] => Drupal\Core\Session\AccountProxy Object (
    [requestStack:protected] => Symfony\Component\HttpFoundation\RequestStack Object (
      [requests:Symfony\Component\HttpFoundation\RequestStack:private] => Array (
        [0] => Symfony\Component\HttpFoundation\Request Object (
          [attributes] => Symfony\Component\HttpFoundation\ParameterBag Object (
            [parameters:protected] => Array (
              [_system_path] => node/4
              [_controller] => \Drupal\node\Controller\NodeViewController::view
              [_title_callback] => \Drupal\node\Controller\NodeViewController::title
              [node] => Drupal\node\Entity\Node Object (
                [values:protected] => Array (
                  [vid] => Array (
                      [x-default] => 4
                  )
                  [field_background_color] => Array (
                    [x-default] => Array (
                      [0] => Array (
                        [value] => ff00ff
                      )
                    )
                  )
                )
              )
            )
          )
        )
      )
    )
  )
)

```

How do I get the value of *field\_background\_color*?

# Answer
> 7 votes
So your field is on the node?

Then you need to get the node object first.

```
<?php
if (($node = \Drupal::routeMatch()->getParameter('node')) && $node instanceof \Drupal\node\NodeInterface) {

}

```

Once you have that, you can read your field, assuming it is a text field, like this: `$node->field_background_color->value`. Make sure to always check if you really have a $node object as done in the snippet above when you're in the global context. You will only have on on node/N, but not on other pages.

There are many questions already about how to access field values, and there are great presentations as well.

# Answer
> 1 votes
Simply iterate the `$variables['view']->result` array and get every field value you want.

```
foreach ($variables['view']->result as $key=>$result){
    $field = $result->_entity->get('field_name')->getValue();
    $variables['rows'][$key]['var_name'] = $field[0]['value'];
}

```

In this line `$variables['rows'][$key]['var_name'] = $field[0]['value'];` you save the data into the row-variable where you can access it later in your twig-template with `{{row.var_name}}`

# Answer
> 0 votes
You have entity values at hand

```
$element = $variables['element'];
if ( $entity = $element['#object'] ) {
  dump ($entity);
  exit;
}

```

---
Tags: 8, theming
---


title: Custom Module Rename

text:
# Question
Title: Custom Module Rename
We have three custom pieces of code for our Drupal website: module, theme and a non-drupal php library. The names of these components have become awkward over time. I would like to rename our custom module from "rsm\_library" to "rsm\_module".

I created a copy of "rsm\_library" on Github as "rsm\_module". I then changed all of the internal references from "rsm\_library" to "rsm\_module". These changes were mostly `namespace` and `use` statements. I also made updates to `.info` and `.module`. I then used composer to load the new module into the website so that both "rsm\_library" and "rsm\_module" are available at `modules/custom`. So far so good.

My next step is to uninstall "rsm\_library" using the drupal admin gui. I received a warning message saying the listed configuration will be deleted when I uninstall the module:

* three custom blocks
* one REST resource

This seems correct as the support for the blocks/rest is coded in the "rsm\_library" module. I looked at the configuration of one of the custom blocks. It contains the following lines -- among others:

```
dependencies:
  module:
    - node
    - rsm_library

```

```
provider: rsm_library

```

This is likely the interface between the custom module and the custom block. The REST configuration contains a dependency on "rsm\_library" but does not include a `provider:`.

I am not sure how to proceed to complete the rename of "rsm\_library" to "rsm\_module". Perhaps something like this:

* Export the four configurations
* Change the dependencies/provider from "rsm\_library" to "rsm\_module"
* Should I delete the uuid: line?
* Include the resulting yml in "rsm\_module/config/install"

The four configurations will be deleted when I uninstall "rsm\_library". They will be included once again when I install "rsm\_module". Does this seem to be the correct approach?

# Answer
I proceeded the way I described in the question above -- including deleting the `uuid:` lines from the yml files. I now have "rsm\_library" uninstalled and "rsm\_module" installed on the website. The block and rest configurations are in place and seem to be working. I should be able to promote this to our public website with some additional testing.
> 0 votes

---
Tags: blocks, configuration
---


# Question
Title: How do I add grouping, programmatically?
I've added a custom field to a view and want to display results as a grid grouped by this field. How do I set that "Grouping field Nr.1" option in my code? I tried the `hook_views_pre_build()` using the `$view->addHandler` but m not able to make it work. I guess the issue lies in the `$option` array and the `$type` parameter for `addHandler` method. Here is my code.

```
function utility_views_pre_view(ViewExecutable $view, $display_id, array &$args) {
  if ($view->id() == 'frontpage' && $display_id == 'page_1') {
    $options = array(
      'style' => array(
        'options' => array(
          'grouping' => array(
            'field_category',
          ),
        ),
      ),
    );
    $view->addHandler("page_1", "grouping", "node__field_category", "field_category", $options);
  }
}

```

**Update** When I use `$view->addHandler("page_1", "field", "node__field_category", "field_category", $options);` I get the a catgeory field added to each of the view items.

Can anyone help me on this?

# Answer
> 1 votes
Finally found a solution. The grouping is not an Eventhandler in Drupal 8 but a Plugin (`Style Plugin`) specifically. Here is the code

```
function utility_views_pre_build(ViewExecutable $view) {
  $view->style_plugin->options['grouping'][0] = array('field' => 'field_category');
}

```

# Answer
> 0 votes
this worked for me in Drupal 8

```
function utility_views_pre_view(\Drupal\views\ViewExecutable $view, $display_id, array &$args) {
    $view->getStyle()->options['grouping'][0]['field'] = 'field_category';
    }

```

---
Tags: 8, views
---


# Question
Title: How to change a grouping field in a view programmatically?
I've added a custom field to a view and want to display results as a grid grouped by this field. How do I set that "Grouping field Nr.1" option in my code? I tried the following but it doesn't work (probably I'm doing it in the wrong place or change wrong setting...)

```
function MYMODULE_views_query_alter(&$view, &$query)
{
    $view_name = 'MYVIEW';
    $display_name = 'MYDISPLAY';
    if ($view->name == $view_name && $view->current_display == $display_name)
    {
        $custom_field = 'field_MYFIELD_value';

        //code piece adding this field to a view's SELECT statement, sorting by it etc

        $style_options = $view->display['default']->handler->options['style_options'];
        $style_options['grouping'][0]['field'] = $custom_field;
    }
}

```

# Answer
> 2 votes
```
function MYMODULE_views_pre_build( &$view ) {
  $custom_field = 'field_MYFIELD_value';
  $view->display[$view->current_display]->handler->options["style_options"]["grouping"] = $custom_field;
}

```

# Answer
> 0 votes
this worked for me in Drupal 8 https://www.drupal.org/project/views/issues/1907940

```
function utility_views_pre_view(\Drupal\views\ViewExecutable $view, $display_id, array &$args) {
    $view->getStyle()->options['grouping'][0]['field'] = 'field_category';
    }

```

---
Tags: 7, views, entities
---


# Question
Title: Create node by post Api call fail with message "Could not determine entity type bundle: \\u0022type\\u0022 field is missing."}
I'm trying to create a node via Drupal API but I get this error:

```
Got error 'PHP message: PHP Fatal error:  Uncaught GuzzleHttp\\Exception\\ClientException: Client error: `POST https://site.it/entity/node?_format=hal_json` resulted in a `422 Unprocessable Entity` response:\n{"message":"Could not determine entity type bundle: \\u0022type\\u0022 field is missing."}

```

This is my function:

```
public function createFaq($notes, $telegram_id){
  $url = "/entity/node?_format=hal_json";
  $opt = [
    'headers' => self::$baseHeader,
    'body' => json_encode([
      [
        'type' => [ ['target_id' => 'faq'] ],
        'title' => 'title',
        'utente' => [ [ 'target_id' => '123462' ] ],
        'field_domanda' => [ [ 'value' => $notes['domanda'] ] ],
        'field_presenza' => [ [ 'value' => $notes['presenza'] == "Si"? true : false ] ],
      ]
    ])
  ];

  $response = $this->client->request('POST', $url , $opt);
  $r = json_decode( $response->getBody());
  return $r;
}

```

But it's really strange, because this other function is working:

```
public static function createUser($title){
  $url= "/entity/node?_format=hal_json";
  $opt = [
    'headers' => self::$baseHeader,
    'body' => json_encode([
      'title' => [ [ 'value' => $title ] ],
      'type' => [ [ 'target_id' => 'article' ] ],
    ])
  ];

  $response = $this->client->request('POST', $url , $opt);
  $r = json_decode( $response->getBody());
  return $r;
}

```

Can someone understood my error?

# Answer
This is the code I used to create a node using rest api:

Endpoint: `/node?_format=hal_json`

Method: `POST`

Body:

```
{
  "title": [
    {
      "value": "This is a question"
    }
  ],
  "field_question": [
    {
      "value": "This is the question"
    }
  ],
  "field_options": [
    {
      "value": "This is the right option"
    },
    {
      "value": "This is not the right option"
    },
    {
      "value": "This is defenitely not the right option"
    },
    {
      "value": "This is the most silly option"
    }
  ],
  "type": [
    {
      "target_id": "question"
    }
  ]
}

```

Enable the Rest UI module to check if the endpoint exists. Actually I can't find the plugin proposing this endpoint but having Rest UI enabled I saw this URI for posting content types.
> 0 votes

---
Tags: 9
---


# Question
Title: Why do setter methods in an entity return $this?
Writing a custom entity type I noticed that all setter methods in entity classes are returning $this after changes, as methods modify the object and so object will definitely being modified, then

> what is the propose of returning the objects? is it a best practice?

# Answer
> 8 votes
It's for chaining, e.g.

```
$an_object
  ->doSomething()
  ->doSomethingElse()
  ->andSomethingElse();

```

Whether it's best practice is up for debate, there's no right or wrong answer to that. Some like it because it looks nice (so called fluent interface), some don't like it because, well because many reasons.

See https://stackoverflow.com/questions/1103985/method-chaining-why-is-it-a-good-practice-or-not for some interesting opinions.

# Answer
> 5 votes
The benefit is, you can chain methods, like saving the entity after you have set values:

```
$entity->set('label', 'foo')->save();

```

Caveat: save() doesn't return the object, but the result of the save operation as integer.

---
Tags: entities, 9
---


# Question
Title: How to print alt or title field image in twig node template?
I want to print alt or title field image file in node twig template Drupal 8. I tried use `{{ node.field_images.entity }}` to debug get value title or alt but in class `\Drupal\file\Entity\File` not function get those ! I saw `{{node.field_images.entity.fileuri}}` in link

So how to used `{{node.field_images.entity}}` to get value alt or title file images ?

Thanks !

# Answer
The alt and title properties are stored in the image field, not in the file entity. You can access them by replacing the `entity` property with `alt` or `title`:

```
{{ node.field_image.title }}
{{ node.field_image.alt }}

```
> 19 votes

# Answer
In the field template (field.html.twig) this will work.

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

```

In node.html.twig or paragraph.html.twig, this will work.

```
{{ content.field_image['#items'].alt }}

```
> 10 votes

# Answer
In the node template:

```
{{ content.field_image[0]['#attributes']['alt'] }}

```
> 0 votes

---
Tags: theming, 8
---


# Question
Title: How to cache View block by content language?
I have a very simple (block) view to list a node's title. This view has an id from url contextual filter and a single filter to filter on Content language set for the page (by URL prefix). This block is then placed using Layout Builder on the Full Content view mode for this node type. The view is set to use Tag based caching. When I switch the page back and forth between languages; the title language does not change.

Disabling views caching fixes this.

A little digging and I see that Views cache context is based on Interface language but the Title is content; so it needs to be based on Content language. I have seen a few posts on setting cache context and cache tags but those don't seem to work.

So far I have tried this:

```
function mycustom_views_pre_view(ViewExecutable $view, $display_id, array &$args) {
  $language_manager = \Drupal::languageManager();
  $langcode = $language_manager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId();
  if (isset($view->element['#cache']['contexts']) && is_array($view->element['#cache']['contexts'])) {
    foreach ($view->element['#cache']['contexts'] as $key => $context) {
      if (stristr($context, 'language_interface')) {
        unset($view->element['#cache']['contexts'][$key]);
      }
    }
    $view->element['#cache']['contexts'][] = 'languages:language_content';
    $view->element['#cache']['tags'][] = 'language:' . $langcode;
  }
}

```

None of this seems to help.

Is it possible I have fixed the view caching but the block is still not cached properly?

# Answer
For Views rendering fields you can add the cache metadata to the field, so that it can be used already for the cached rows and then bubble up to the rendered view and block.

```
/**
 * Implements hook_preprocess_views_view_field().
 */
function mymodule_preprocess_views_view_field(array &$variables) {
  // target specific view and field
  $variables['#cache']['contexts'][] = languages:language_content';
}

```
> 1 votes

# Answer
You can add a backend class for the block, then add a cache context on language to that block.

First, you need to get the config key for the view block. I believe it is `views.view.[BLOCK_ID]`. You can get the block ID in the advanced section of the view.

Next, you add a custom class to the block. Here is how that is done for the system branding block.

```
/**
 * Implements hook_block_alter().
 *
 * Changes the class for the system branding block to add a cache
 * context for language.
 */
function [MODULE]_block_alter(array &$definitions) {
  // Set custom callback for system menu block
  $definitions['system_branding_block']['class'] = 'Drupal\[MODULE]\Plugin\Block\SystemBrandingBlockOverride';
}

```

Then you can add a cache context on language to in the class:

```
namespace Drupal\[MODULE]\Plugin\Block;

use Drupal\system\Plugin\Block\SystemBrandingBlock;

/**
 * Adds group caching to the system branding block.
 */
class SystemBrandingBlockOverride extends SystemBrandingBlock {

  /**
   * {@inheritdoc}
   */
  public function getCacheContexts() {
    $contexts = parent::getCacheContexts();

    $contexts[] = 'languages';

    return $contexts;
  }

}

```

Note that you may want to use one one of the following cache contexts instead:

* `languages:language_interface`
* `languages:language_content`
> 0 votes

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


# Question
Title: How to check if (unmanaged) file exists?
I can't find a Drupal API function in D7 that tells me if an (unmanaged) file exists. D6 had a file\_check\_location but not for 7.

How to check if (unmanaged) file exists?

# Answer
> 44 votes
You could just use the old bog standard PHP function `file_exists()` if I understand you right:

```
$uri = 'public://images/an-image.jpg';
if (file_exists($uri)) {
  // Do something
}

```

This also works for normal (absolute) paths as well, e.g.:

```
$path = '/var/www/drupal/sites/default/files/images/an-image.jpg';
if (file_exists($path)) {
  // Do something
}

```

# Answer
> 7 votes
If you want a Drupal way to do this, you can in Drupal 8/9/10 using the file\_system service.

```
/** @var \Drupal\Core\File\FileSystemInterface $file_system */
$file_system = \Drupal::service('file_system');
$file_exists_error = $file_system->getDestinationFilename($file_uri, \Drupal\Core\File\FileSystemInterface::EXISTS_ERROR);

```

If the file does not exist in the file system $file\_exists\_error will return the file path, otherwise it will return false, denoting there was no error.

@see https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21File%21FileSystemInterface.php/function/FileSystemInterface%3A%3AgetDestinationFilename/9.3.x

# Answer
> 4 votes
I don't know what your specific use case is, but you may not need to check to see if the file exists.

The functions file\_unmanaged\_copy, file\_unmanaged\_move, file\_unmanaged\_delete, file\_unmanaged\_delete\_recursive, and file\_unmanaged\_save\_data check to see if the file exists and return false if it does not.

You can find the source code in drupal/includes/file.inc and have a look.

# Answer
> 4 votes
You should use the drupal function:

file\_destination($uri, FILE\_EXISTS\_ERROR)

and check

```
if (!file_destination($uri, FILE_EXISTS_ERROR)) {
  // The file exist
  // Do something
}

```

---
Tags: 7, files
---


title: How to completly remove a field?

text:
# Question
Title: How to completly remove a field?
I have removed a field from a bundle (it is not used somewhere else) by using the graphical UI.

But it is still listed when I run the following command (after cache clear)

```
$this->entityFieldManager->getFieldDefinitions('node', $bundle);

```

What should I do to completely remove it (as I use the previous command to display some list)

**edit to add**:

Following the proposal of Clive, I ran the `field_cron()` without success. Looking at the code of this function, I tried the following code to have more information:

```
$deleted_fields_repository = \Drupal::service('entity_field.deleted_fields_repository');
$fields = $deleted_fields_repository->getFieldDefinitions(NULL);

```

As you can imagine, `$fields` is empty. Maybe some kind of corruption?

**edit to add 2**

Following the proposal of 4k4 I ran this code:

```
$field_storage = \Drupal\field\Entity\FieldStorageConfig::loadByName('node', 'the_field_that_must_be_deleted');
dpm($field_storage->get('persist_with_no_fields'));

```

And the result is `FALSE`

Thus the question is: how to manually remove a field?

# Answer
> 0 votes
Usually you would just run cron for this, because `field_cron()` clears the deleted data.

If you need to do it manually for whatever reason, you can call `field_purge_batch()` manually.

---
Tags: entities
---


# Question
Title: Redirect Page on Change of Exposed Filter
We have an `All Articles` view that is added to the `http://www.example.com/articles` page that is supposed to display all pages where content type is `Article`. The content type has a taxonomy term, `Category`, which has several filter values such as `IoT`, `Security`, and `Cloud`. On the view, the `field_category` is exposed for visitors to change the value and it will automatically update the results (`Use Ajax = true`).

**Goal:**

* On change of the exposed filter to `Cloud`, we would like to redirect the user to another page (`http://www.example.com/some-page`).

**Question:**

* **How would we redirect a user to the other page when the exposed filter is set to `Cloud`?**

View Settings:

Format

* Format: Unformatted List | setting (`default settings`)
* Show: Content | Listing (`custom view mode`)

Filter Criteria

* content: published (= yes)
* content: content type (= Article)
* content: category (exposed)

Advanced

* Use Ajax: `Yes`
* Query Option: `Distinct = true`

Here is what we tried, but it does not redirect with no errors.

**mymodule.module**

```
function mymodule_form_alter(&$form, $form_state, $form_id) {
  if($form_id == 'view_exposed_form' && $form['#id'] == 'views-exposed-form-articles-page-1') {

   if($form['field_category_target_id'] == '123') {
     $form['field_category_target_id']['#ajax] = [
       'callback' => 'cloud_ajax_callback',
       'wrapper' => 'category_cloud',
     ],
   }
  }
}

function cloud_ajax_callback($form, FormStateInterface $form_state) {
  $response = new AjaxResponse();
  $cloud_cmd = $new RedirectCommand('http://www.example.com/some-page');
  return $response->addCommand($cloud_cmd);
}

```

# Answer
You just need to change `#action` in the form.

so

```
function mymodule_form_alter(&$form, $form_state, $form_id) {
  if($form_id == 'view_exposed_form' && $form['#id'] == 'views-exposed-form-articles-page-1') {
       $form["#action"] = "THE_PATH_YOU_WANT_TO_REDIRECT";
  }
}

```
> 1 votes

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


# Question
Title: What's the difference between creating a multisite vs development and production site?
Can I set up a multisite to perform the dev, production site, and eventually deployment ? Are they the same?

# Answer
These are different things. Multi-site means that a single drupal codebase is used to create multiple sites. A Drupal codebase is hosted in an environment like dev, staging or production. So you could have:

local

* Multisite A
* Multisite B
* Multisite C

Dev

* Multisite A
* Multisite B
* Multisite C

Staging

* Multisite A
* Multisite B
* Multisite C

Production

* Multisite A
* Multisite B
* Multisite C
> 1 votes

---
Tags: version-control, staging
---


title: Error when trying to view revisions

text:
# Question
Title: Error when trying to view revisions
Using Drupal 8/9. When trying to view previous revisions I am getting the following error:

```
Error: Call to a member function getType() on string in clc_d8_theme_theme_suggestions_page_alter() (line 13 of /var/www/html/wrc/web/themes/clc_d8_theme/clc_d8_theme.theme)

```

It refers to this code:

```
function clc_d8_theme_theme_suggestions_page_alter(array &$suggestions, array $variables) {
  // Add content type suggestions.
  if ($node = \Drupal::request()->attributes->get('node')) {
    array_splice($suggestions, 1, 0, 'page__node__' . $node->getType()); <-- error at this line
  }
}

```

I need the type suggestions for my theme. How do I fix this? I thought the check on the node would be enough to avoid issues.

# Answer
"`$node`" can vary a bit by context, but here are some ways to set `$node`:

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

$node = NULL;

// $variables['node'].
if (isset($variables['node'])) {
  $node = $variables['node'];
  if (is_numeric($variables['node'])) {
    $node = \Drupal::entityTypeManager()->getStorage('node')->load($variables['node']);
  }
}

// $variables['row'].
if (isset($variables['row']) && !empty($variables['row']->nid)) {
  $node = \Drupal::entityTypeManager()->getStorage('node')->load($variables['row']->nid);
}

// $routeName === 'entity.node.canonical'.
if ($routeName === 'entity.node.canonical') {
  $node = \Drupal::routeMatch()->getParameter('node');
}

// $routeName === 'entity.node.revision'.
if ($routeName === 'entity.node.revision') {
  $revisionId = \Drupal::routeMatch()->getParameter('node_revision')->getRevisionId();
  $node = node_revision_load($revisionId);
}

// $routeName === 'entity.node.preview'.
if ($routeName === 'entity.node.preview') {
  $node = \Drupal::routeMatch()->getParameter('node_preview');
}

if ($node) {
  // run your code...
}

```

Specifically, it looks like you're after:

```
// Get route name.
$routeName = \Drupal::routeMatch()->getRouteName();

// Check if route is node revision.
if ($routeName === 'entity.node.revision') {
  $revisionId = \Drupal::routeMatch()->getParameter('node_revision')->getRevisionId();
  $node = node_revision_load($revisionId);
}

```

This will fully load your node object and `->getType()` should work without error.
> 3 votes

---
Tags: 8, nodes
---


# Question
Title: Why does Programmatic Node Unpublish not Work?
We recently upgraded to Drupal 9.3.0 using a Composer file layout. The resulting website is working correctly and is now running in the publish domain. We have a set of utilities that we run as Drush scripts. One of these unpublishes content that we do not want google and other search engines to find -- yet.

I moved into the directory that contains composer.json -- one level above the webroot. I ran `composer require drush/drush` which added `"drush/drush": "^11.0",` to composer.json and updated the vendor directory accordingly. I then created a small php script to unpublish a node -- named x.php:

```
<?php

use Drupal\node\Entity\Node;

print "Top\n";
  $node = Node::load('1881');
  $node->setPublished(FALSE);
  $node->save();
print "Bot\n";

```

I ran `vendor/drush/drush/drush scr x.php`. The script runs without error and prints "Top" and "Bot" as expected. However, running this commend Did Not unpublish nid = 1881. I ran the command again with the `-d` switch which gave me lots of output -- but no error messages to work with. I checked the error\_log for the website -- nothing. I added a `var_dump($node);` after the `$node = Node::load('1881');` and can see the node is being loaded.

I need to unpublish over 700 nodes and do not want to do this manually. Any suggestions on how to proceed?

# Answer
In Drupal 9 `setPublished(FALSE)` doesn't work anymore, the boolean argument is ignored. This was split into two methods:

```
// publish entitiy
$entity->setPublished();

// unpublish entity
$entity->setUnpublished();

```

The change record: https://www.drupal.org/node/2830201

See the linked issue:

**API changes**

* New EntityPublishedInterface added and implemented by Node and Comment
* The parameter for setPublished() is now optional. No parameter will just set the entity as published, but the old TRUE or FALSE parameters will work as they always have for backwards compatibility. This parameter will be removed in 9.0.0.
> 8 votes

---
Tags: nodes, 9
---


# Question
Title: How to get the description text from metatag field
A content type in my Drupal 9 instance uses the Metatag module. I want to extract the 'description' metatag value and include it in a twig template (for the node).

But when I look at the variables available, it looks like `field_metatag` contains PHP `serialize()`-ed code.

I want to do something like

```
<div class="the-description">
  {{ node.field_metatag.description|e('html') }}
</div>

```

# Answer
You can get the serialized data via `node.field_metatag.value`.

But seems there's no ready-made unserialize Filter for Twig. And the tags are hidden from the node because they are supposed to be used on page-level instead. So you either write an unserialize filter yourself or preprocess the description into the template.

I found the following preprocess to be working.

```
/**
 * Implements template_preprocess_node().
 */
function MYTHEME_preprocess_node(&$variables) {
  $node = $variables['node'];

  $tags = \Drupal::service('metatag.manager')
    ->tagsFromEntityWithDefaults($node);

  if (!empty($tags['description'])) {

    $description = \Drupal::service('metatag.token')
      ->replace($tags['description'], ['node' => $node]);

    $variables['my_description'] = strip_tags($description);
  }
}

```

```
{% if my_description %}
  {{ my_description }}
{% endif %}

```
> 3 votes

---
Tags: 9, meta-tags
---


# Question
Title: Autoload helper classes in tests/src/ for phpunit in contrib module
I am working on a contrib module with phpunit tests.

Currently there is no composer.json or phpunit.xml or installation routine in the module itself, instead one has to run the functional and browser tests from a custom drupal site, where the module is installed in web/modules/contrib/\*. So far this works.

Now I want to use helper classes in `tests/src/Helper/`, in namespace `"Drupal\\Tests\\$modulename\\Helper\\"` and possibly elsewhere.

However, I noticed that `drupal_phpunit_get_extension_namespaces()` only registers some select namespaces within `"Drupal\\Tests\\$modulename\\"`, instead of the entire namespace.

My questions:

* Why does Drupal phpunit integration behave this way, instead of registering the entire `tests/src/` namespace directory?
* What is a good way to register the entire `tests/src/` directory in the class loader? I still want to be able to run the tests from Drupal installation outside the module itself.

---

EDIT: New issue on drupal.org: #3258817: Why don't we register all of /tests/src/ for class loading?

# Answer
> 0 votes
I will provide a dirty workaround here, that can be easily copied without adjusting any code.

There might be better solutions, I am open for other answers!

Also, I won't promise 100% that this works in all circumstances. Perhaps opcache can bring nasty surprises?

Create the following file in `"tests/src/$modulename/Traits/AutoloadHelperTrait.php"`. Replace `<MODULENAME>` with the real module name.

```
<?php

/**
 * @file
 * Registers the entire 'tests/src/' directory in the class loader.
 *
 * By default, Drupal phpunit integration registers only _some_ namespace
 * directories within 'tests/src/' in the class loader. One of them is
 * '/Traits/'.
 * This workaround registers the top-level namespace.
 *
 * The code is written in a way that can easily be copied to other modules:
 * - It is independent of the module name.
 * - It is independent of where the module is placed in the filesystem.
 *
 * See https://drupal.stackexchange.com/questions/309143/autoload-helper-classes-in-tests-src-for-phpunit-in-contrib-module
 *
 * @see \drupal_phpunit_populate_class_loader()
 * @see \drupal_phpunit_get_extension_namespaces()
 */

declare(strict_types=1);

namespace Drupal\Tests\<MODULENAME>\Traits;

use Composer\Autoload\ClassLoader;

\call_user_func(static function (): void {
  // The Composer ClassLoader class is always present in the same location
  // within the vendor directory. From there we can work our way to the
  // autoload.php to get the real class loader.
  $rc = new \ReflectionClass(ClassLoader::class);
  /** @var \Composer\Autoload\ClassLoader $classLoader */
  $classLoader = require dirname($rc->getFileName(), 2) . '/autoload.php';
  // Determine the namespace and directory from magic constants.
  // This allows the code to be copied elsewhere.
  $level = \substr_count(__NAMESPACE__, '\\');
  $dir = dirname(__DIR__, $level - 2);
  // The namespace always starts with 'Drupal\Tests\', independent of the
  // module name.
  $nspos = \strpos(__NAMESPACE__, '\\', 13);
  $namespace = \substr(__NAMESPACE__, 0, $nspos + 1);
  $classLoader->addPsr4($namespace, $dir);
});

/**
 * Include this trait to register the entire tests/src/ for class loading.
 */
trait AutoloadHelperTrait {}

```

Now include the trait in any test class that needs this autoloading enabled. Or include it from a test base class.

---
Tags: 9, testing
---


# Question
Title: How to add different GTM snippets per environment?
We have multiple environments such as Dev, Stage, QA, and Production. Rather than having one GTM snippet that is loaded on every page request in all the environments, we wanted to separate the GTM snippets so that the GTM snippet for Dev is only loaded for Dev, the GTM snippet for Stage is only loaded for Stage, and the production GTM script is only loaded on production.

Currently we add the GTM snippet through the use of our custom theme's `html.html.twig` template file.

How would I be able to conditionally add different scripts in a Drupal way (e.g. custom module, custom JS)?

We initially thought to create custom modules that would a load `mymodule.html.html.twig` when enabled per environment. For example, the dev custom module would only be enabled on Dev, Stage custom module would only be enabled on. However that is not working.

# Answer
> 1 votes
In my opinion adding a GTM snippet should be handled by a module, and not theme dependent. The GoogleTagManager can be used to accomplish this.

In your settings.php file you can indicate which snippet to use: `$config['google_tag.settings']['container_id'] = 'GTM-000000';`

When you want these snippet variants stored in you version control system, in that case every environment should have some kind of indicator allowing to implement something like:

```
if ($_ENV('ENVIRONMENT') == 'dev') {
    $config['google_tag.settings']['container_id'] = 'GTM-000000';
} elseif ($_ENV('ENVIRONMENT') == 'stage') {
    $config['google_tag.settings']['container_id'] = 'GTM-AAAAAA';
}

```

Another option to indicate which snippet to use depending on the current environment (i.e., Dev, Stage, QA or Production), is to use the Configuration Split module. This module contains functionality to create conditional splits.

# Answer
> 0 votes
Since google\_tag started using containers, the format has changed a bit for the GTM settings, so you should now use the following:

```
$config['google_tag.container.label_machine_name_here']['container_id'] = 'GTM-000000';

```

`label_machine_name_here` is the machine name from whatever you called the GTM container in the module settings.

You can use the above method to change the GTM environment settings per development environment too, while keeping your GTM container id the same. The settings for that are:

```
$config['google_tag.container.label_machine_name_here']['environment_id'] = 'env-x';
$config['google_tag.container.label_machine_name_here']['environment_token'] = 'xxxxxx';

```

The quick way to know what the $config key is, is to look at the exported config filenames (from drush cex) - the filename for GTM is `google_tag.container.label_machine_name_here.yml`.

---
Tags: 8, theming, nodes
---


# Question
Title: Twig\Error\LoaderError: Template "@theme/footer.html.twig" is not defined
I know there are similar questions to this that have been asked but none of the solutions are working for me and I've been at this all day so I thought I'd give this a try.

I've created a sub-theme of Bartik for Drupal 9. I've copied the page.html.twig and I'm trying to include a templates/includes/footer.html.twig and nothing I have tried has worked.

1. I installed the components module and updated DB
2. Declared the following in subbartik.info.yml:

```
components:
  namespaces:
    includes: includes

```
3. Input the following into page.html.twig

```
{% include '@includes/footer.html.twig' %}

```

Cleared cache with drush, and I get error:

```
    Twig\Error\LoaderError: Template "@includes/footer.html.twig" is not defined in "sites/default/themes/custom/subbartik/templates/page.html.twig" at line 125. in Twig\Loader\ChainLoader->getCacheKey()

```
1. I've tried a relative path from web folder root

```
{% include 'sites/default/themes/custom/subbartik/templates/includes/footer.html.twig' %}

```

Same error:

```
    Twig\Error\LoaderError: Template "sites/default/themes/custom/subbartik/templates/includes/footer.html.twig" is not defined in "sites/default/themes/custom/subbartik/templates/page.html.twig"

```
2. I tried the old:

```
{% include '@subbartik/includes/footer.html.twig' %}

```

Same error:

```
    Twig\Error\LoaderError: Template "@subbartik/includes/footer.html.twig" is not defined in "sites/default/themes/custom/subbartik/templates/page.html.twig"

```

Any suggestions would be appreciated. Thanks!

**UPDATE**

File structure (figured it would just be easier to take a screen shot):

# Answer
> 1 votes
There was a caching problem that had nothing to do with the template itself. Not sure exactly what happened but I turned off MAMP, did something else for awhile, came back and it was working fine. Thanks!

---
Tags: theming
---


# Question
Title: How to add a new field in a feed AfterParseBase?
Parsing a CSV file, and the goal is to take an input column and turn it into two Drupal fields. The last 3 characters of the BondId field becomes a new field called TrancheId.

The BondID field looks like

The CSV source field that is not in the input data is mapped

Code to add a field

```
class CbiFeedAlterSubscriber extends AfterParseBase {

 /**
  * {@inheritdoc}
  */
 public function applies(ParseEvent $event) {
    return $event->getFeed()->getType()->id() === 'bond';
 }

 /**
  * {@inheritdoc}
  */
 protected function alterItem(ItemInterface $item, ParseEvent $event) {
   $old_tranche_id = $item->get('TrancheId');
   if ($old_tranche_id) {
     return;
   }

   // Tranche ID is a new data item derived from BondID
   $bond_id = $item->get('bondid');
   $tranche_id = substr($bond_id, strlen($bond_id) - 3, 3);

   $item->set('TrancheId', $tranche_id);
 }
}

```

The service is defined

```
services:
  cbi_feed_alter.feed_alter_event_subscriber:
    class: Drupal\cbi_feed_alter\EventSubscriber\CbiFeedAlterSubscriber
    tags:
      - { name: event_subscriber }

```

# Answer
Lower case field names and it works

```
$item->set('trancheid', $tranche_id);

```

Similarly for BondID

```
$item->set('bondid', $tranche_id);

```

sets the value, mixed case doesn't work.
> -1 votes

---
Tags: feeds
---


title: Drush failing to load drush.php file

text:
# Question
Title: Drush failing to load drush.php file
I have Drupal 8 project on my local machine, which is set up with composer and I got drush included. When I'm in project root I can call drush like:

```
vendor/bin/drush -v

```

And that work well (initialized it so I can call it without typing full path):

```
Drush Commandline Tool 9.7.2

```

...

But when I moved the same project to staging server, when I try to run the same command I get error message:

```
PHP Warning:  require(/path_to_project/vendor/bin/drush.php): failed to open stream: No such file or directory in /path_to_project/vendor/bin/drush on line 4
PHP Fatal error:  require(): Failed opening required '/path_to_project/vendor/bin/drush.php' (include_path='.:/usr/local/share/pear') in /path_to_project/vendor/bin/drush on line 4

```

Inside drush file I'm executing from bin there is only one line (line 4):

```
require __DIR__ . '/drush.php';

```

But that require fails and triggers this error. drush.php file is located (in both cases) inside: `vendor/drush/drush/drush.php`

I have another project with the same setup and drush there works well on local box and on that other staging server, so I know problem is in server setup somewhere, but don't know where exactly? That include path from error message "`include_path='.:/usr/local/share/pear'`" looks suspicious to me.

Since I'm not server admin do I need his help to solve this?

# Answer
Yes, what @remy said is true.

Inside /vendor/bin all "files" are actually symlinks. Real files are located elsewhere. However when copying those files (i.e. with Filezilla) instead of copying symlinks original files were copied. I solved this by zipping whole bin dir, copying archive and unzipping in on remote server.

Zipping it with mac finder keeps sym links well. However, when zipping form command line most likely option --symlinks should be set:

```
zip --symlinks -r foo.zip foo/

```

https://serverfault.com/questions/265675/how-can-i-zip-compress-a-symlink
> 2 votes

# Answer
As mentioned by @MilanG that the symlinks is missing.

So, to fix this you will need to remove the `vendor` folder and installing the packages from composer again.

1. `rm -rf ./vendor`
2. `composer install`
> 1 votes

---
Tags: 8, drush
---


# Question
Title: How to apply nofollow and target_blank on external links in text created with CKEditor?
When I create a node, I often need to add links to external websites in the text.

I want all the external links to open in a new tab and I want them to have a nofollow.

The body field uses CKEditor.

How do I apply `nofollow` and `target_blank` on external links in text created with CKEditor?

# Answer
You can do this automatically by creating your own text filter in a custom module.

Note that the `/** @Filter ... */` in front of the class is not a comment, but an annotation, it has to be included in the file. Replace all fancy uppercase stuff with your own code.

`src/Plugin/Filter/MYFANCYFILTER.php`

```
<?php

namespace Drupal\MY_MODULE\Plugin\Filter;

use Drupal\filter\FilterProcessResult;
use Drupal\filter\Plugin\FilterBase;
use Drupal\Component\Utility\Html;

/**
 * @Filter(
 *   id = "MY_FANCY_FILTER",
 *   title = @Translation("My fancy filter"),
 *   description = @Translation("Makes HTML even more fancier"),
 *   type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_REVERSIBLE
 * )
 */
class MYFANCYFILTER extends FilterBase {

  public function process($text, $langcode) {
    $result = new FilterProcessResult($text);
    $dom = Html::load($text);
    $xpath = new \DOMXPath($dom);

    // to select all links you have to create a XPath query
    // the example query below selects all <a> tags which have a "href" attribute
    // see https://www.w3schools.com/xml/xpath_syntax.asp
    foreach ($xpath->query("//a[@href]") as $element) {
      // the example logic below accepts all links starting with "http://" or "https://" or "//"
      if (preg_match('|^(https?:)?//.+|', $element->getAttribute('href')) === 1) {
        // see https://www.php.net/manual/de/class.domelement.php
        // for docs about manipulating HTML markup
        $element->setAttribute('MY_ATTRIBUTE', 'MY_VALUE');
      }
    }
    $result->setProcessedText(Html::serialize($dom));
    return $result;
  }
}

```

Then enable your new text filter for the corresponding text format in
`Configuration > Content authoring > Text formats and editors`
> 1 votes

# Answer
I have tried to add target="\_blank" by using Text Format=Full HTML using Source button.

It worked for me.

If you do not want manually then you can try following module https://www.drupal.org/project/editor\_advanced\_link
> 0 votes

---
Tags: nodes, uri, 9
---


# Question
Title: Error: Call to undefined function drush_shift()
We recently moved to Drupal 9.3.0 with a composer file layout and Drush 11.0. We make use of Drush Scripts to execute website functions from Crontab. One specific case is sending a newsletter email early each morning.

I receiving the subject error from a Drush Script that has been running for years. The script is executed by moving into the webroot directory of the website and running `drush scr email_script.php arg1 arg2`. The first thing the Drush Script does is pull the arguments from the command line using `drush_shift()` but this function is not defined. I'm not sure how to proceed in debugging this.

# Answer
> 3 votes
`drush_shift()` has been deprecated and removed per @Clive -- Thanks!

In my case I changed:

```
$arg1 = drush_shift();
$arg2 = drush_shift();

```

to

```
$arg1 = $_SERVER['argv'][3];
$arg2 = $_SERVER['argv'][4];

```

---
Tags: drush, 9
---


# Question
Title: How To Force Search API To Reindex a Node / an Entity
I'm working on Sear API. My entity has many items and data change by action of the user. I don't want to reindex all items of data. So I want to reindex an entity after user does the action. I found the topic but just for Drupal 7. So with search API for Drupal 8, how to I can implement force search API to reindex an entity? The way or snippet code I can use? Please help!

e.g. I have search index with some basic field like this:

I want to update the number of comment value after use add a new comment. Default search api doesn't not support that. And I don't want to wait for a cron to update value. Imagine one field very important not like the number of comment. That field needs to update immediately.

# Answer
You can dive deep into the code of search\_api to find solution for issue. See function search\_api\_entity\_update() and search\_api\_search\_api\_index\_update(). In case reindex number of comment, you can try this code:

```
// Example reindex after has new comment at node article id 1
$entity = Node::load(1);
$indexes = ContentEntity::getIndexesForEntity($entity);

foreach ($indexes as $index) {
    // Becarefull with indexes. Just for this case.
    // $datasource_id: entity:node (entity type)
    // $updated_item_ids: 1:en (node ID and Language)
    $index->trackItemsUpdated('entity:node', ['1:en']);
}

```

You can debug in **search\_api.module** to more info.
> 15 votes

# Answer
Same as D7, you do not need to implicitly mark the entity to be reindexed by Search API. It already does the work for you.

In the module file, there is an implementation of hook\_entity\_update(), which takes care of reindexing the items immediately. Not required to wait for the cron run.

I have created a site on simplytest https://du6hi.ply.st (admin/admin) to confirm.
> 3 votes

# Answer
I've found that the solution by MrD does not index immediately. I assume it adds the item to a queue which will process on cron.

If you need the item to be indexed immediately try this:

```
$node_id = 123;
$index = Index::load('my_index');
$language = \Drupal::languageManager()->getCurrentLanguage()->getId();
$item_id = 'entity:node/' . $node_id . ':' . $language;
$items = [];
$items[$item_id] = $index->loadItem($item_id);
$index->indexSpecificItems($items);

```

You'll have to modify if you're indexing something other than a node.
> 3 votes

# Answer
As remarked by @Duncanmoo (D7), there are various use-cases where you may want to re-index a page or entity yourself in custom code.

In my case the relevant node entity updates were implemented like this :

```
$node = node_load($nid);
$node->field_search_rank[LANGUAGE_NONE][0]['value'] = $movie->order;
field_attach_presave('node', $node);
field_attach_update('node', $node);
entity_get_controller('node')->resetCache([$node->nid]);

```

Yet, search\_api\_entity\_update() was not triggered to have the updated field re-indexed to Solr, since the hook doesn't listen to field\_attach\_update()

Instead, I applied this suggested additional custom code to complete the re-indexation on each item.

```
$node = node_load($nid);
$node->field_search_rank[LANGUAGE_NONE][0]['value'] = $movie->order;
field_attach_presave('node', $node);
field_attach_update('node', $node);
entity_get_controller('node')->resetCache([$node->nid]);
// Re-index the node updates :
search_api_track_item_change('node', array($node->nid));
$combined_id = 'node/' . $node->nid;
search_api_track_item_change('multiple', array($combined_id));

```
> 1 votes

---
Tags: 8, search
---


# Question
Title: Disable certain rows of a Entity Reference Source view
I have a field that is an entity reference on a piece of content. I created a view that is an `Entity Reference Source` and set the reference type on the field to that view. When editing the content, I see my list of checkboxes using that `Entity Reference Source` view.

The data in the list are tournaments. Once a tournament is completed, I do not want the user to be able to uncheck that tournament when editing the content. They can only toggle "upcoming" tournaments.

I have tried doing a form alter, but each `option` in `$form['field_tournament']['widget']['#options']` appears to be a `Drupal\Core\Field\FieldFilteredMarkup` so I cant actually disable the row since its just HTML markup which only includes the label, not the checkbox.

```
function MYMODULE_form_group_league_edit_form_alter(&$form, FormStateInterface $form_state) {
  foreach ($form['field_tournaments']['widget']['#options'] as $key => $option) {
    // disable here if the tournament is set to completed.
  }
}

```

I understand in the view, I can set to only show "upcoming" tournaments, but I want the ability for them to see which ones have been completed while editing.

# Answer
> 0 votes
So I figured it out using a custom widget and the Form Options Attributes module, although now that I think of it I could have probably achieved the same thing in the form alter since I am just loading the term via the key which I had access to before. Anyway, I searched the code base of how the `Check boxes/radio` widget was built and copied that and modified the code to add a disabled attribute to the option.

```
<?php

namespace Drupal\pick_dynasty_golf\Plugin\Field\FieldWidget;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsButtonsWidget;
use Drupal\Core\Form\FormStateInterface;

/**
 * Defines the 'pick_dynasty_golf_tournament_selection' field widget.
 *
 * @FieldWidget(
 *   id = "pick_dynasty_golf_tournament_selection",
 *   label = @Translation("Tournament Selection"),
 *   field_types = {
 *     "boolean",
 *     "entity_reference",
 *     "list_integer",
 *     "list_float",
 *     "list_string",
 *   },
 *   multiple_values = TRUE
 * )
 */
class TournamentSelectionWidget extends OptionsButtonsWidget {

  /**
   * {@inheritdoc}
   */
  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $element = parent::formElement($items, $delta, $element, $form, $form_state);
    // Get all options.
    $options = $this->getOptions($items->getEntity());
    // Get already selected options.
    $selected = $this->getSelectedOptions($items);
    $tids = [];
    // Use the key from the $options to get term IDs (the tournaments).
    foreach ($options as $tid => $option) {
      $tids[] = $tid;
    }
    // Load all the tournaments.
    $term_storage = \Drupal::entityTypeManager()->getStorage('taxonomy_term');
    $terms = $term_storage->loadMultiple($tids);
    $disabled = [];
    // Loop through them and disable any tournament with a status of 'post'
    foreach ($terms as $term) {
      $status = $term->get('field_tournament_status')->value;
      if ($status == 'post') {
        $disabled[$term->id()] = [
          'disabled' => TRUE,
        ];
      }
    }

    $element += [
      '#type' => 'checkboxes',
      '#default_value' => $selected,
      '#options' => $options,
      '#options_attributes' => $disabled, // This is from the Form Options Attributes module.
    ];

    return $element;
  }

}

```

One **BIG** issue I did not consider was if the field is disabled (even if previously selected) it does not get submitted so I lose the value. `readonly` on check boxes is not an option. I basically have to disable it in JS unfortunately and write a custom validator on the backend that checks that no disabled items were added/removed

---
Tags: views, 9
---


# Question
Title: Why don't trusted host settings change in my site?
I decided to change the URL of my Drupal site since it's not secure to include the IP address in it. So in my settings.php I have:

```
$settings['trusted_host_patterns'] = array(
  '^forms\.org$',
  '^www\.forms\.org$',
);

```

I cleared the cache using `drush cr` but the trusted host settings in the status report are still not updated. I even checked the permissions and everything is fine.

# Answer
*However, the site loads when I use the old URL, which is the ip address one even after I commented it out*

When you have commented the trusted host setting out the site works normally for all domains or IPs, you only get a warning if you open the status page.

*whereas the new address says "files not found"*

This error is not connected to this issue and it's unlikely a Drupal issue at all. Check the VirtualHost of the new address in your web server configuration. You can also test the new domain name with a static HTML file before you start to debug Drupal.
> 1 votes

---
Tags: 9
---


# Question
Title: Override a access check but also pass control back to the primary controller under certain conditions?
I use a contrib controller that has a `_custom_access` function that I need to override.

I add a RouteSubscriber, and point the access check to my own controller. Now I want something like:

```
if ($condition) {
  return $new_access_decision;
}
return $original_controller->accessCheck()

```

so I can contrinue to rely on the original logic for most cases, and just override for a small subset of cases.

I don't know how to inject the original controller into my mine though, and if I try to add it as a paramter to the RouteSubscriber service, I get

> has dependency on a non-existing service \[original controller\]

which I take to mean that controllers aren't services.

# Answer
Inject the `class_resolver` as a regular service, and then call

```
$this->class_resolver->getInstanceFromDefinition('\Drupal\example\ExampleController');

```
> 1 votes

---
Tags: page-controller
---


title: Rebuild node access permissions

text:
# Question
Title: Rebuild node access permissions
How can I rebuild the node access permissions?

`drupal node:access:rebuild` returns the following error message.

> \[Symfony\Component\Console\Exception\CommandNotFoundException\] There are no commands defined in the "node:access" namespace.

I am using Drupal Console 0.11.3 and Drupal 8.2.0-rc2.

# Answer
> 8 votes
If you're having issues with Drupal Console, you don't have access to it, or you're not using Drush, you can also do it via the UI.

* Login as an administrator
* Visit */admin/reports/status* (also located via the menu at *Reports-\>Status report*
* Find the *Node access permissions* section
* Click on the *Rebuild Permissions* link (which is also located on */admin/reports/status/rebuild*)

# Answer
> 17 votes
With Drush:

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

With Drupal Console:

`drupal node:access:rebuild`

# Answer
> 1 votes
For those people for whom running node\_access\_rebuild function using drush is not working.

I'm not very familiar with drush internals, but the code `drush php-eval 'node_access_rebuild();'` won't trigger batch processing. At least on the next drupal/drush versions (9.2.8, 10.6.1).

The thing is `node_access_rebuild` function do not call batch processing immediaetly.

What worked for me is writing drush script to call batch processing explicitly:

```
<?php
// filename: rebuildPermissions.drush.php
// usage: drush scr ./rebuildPermissions.drush.php
// based on topic https://www.drupal.org/node/873132
node_access_rebuild($batch_mode = TRUE);

$batch =& batch_get();
$batch['progressive'] = FALSE;
drush_backend_batch_process();

```

and then just run it: `drush scr rebuildPermissions.drush.php`

But in the end of the day I've used node\_access\_rebuild\_progressive module for my needs and rebuilt 12K rules for 92K nodes in 5 minutes using drush.

---
Tags: 8, console
---


# Question
Title: Get class on item.below (child item of menu) inside <li> tag in menu--main.html.twig
Hi I can't insert class in child item of main menu and remove existing. Part of my code looks like this:

```
{% for item in items %}
  {%
    set item_classes = [
    'menu-item-edot',
    item.is_expanded ? 'dropdown',
    item.is_collapsed ? '',
    item.in_active_trail ? 'is-active',
  ]
  %}
  <li{{ item.attributes.addClass(item_classes) }}>

    {%
      set link_classes = [
      'nav-link',
      item.in_active_trail ? '',
    ]
      %}

    {{ link(item.title, item.url, attributes.addClass(link_classes)) }}
    {% if item.below %}
      {{ menus.menu_links(item.below, attributes.removeClass('nav-link'), menu_level + 1)  }}
    {% endif %}
  </li>

```

So all li tags return:

```
<li class="menu-item-edot">

```

But I need just top menu items return upper code and all other child menu items to return:

```
<li class="dropdown-item">

```

I didn't find way to remove class "menu-item-edot" and add "dropdown-item" to menu child items.

Please help

# Answer
Thank you sonfd this my code now and it's working!

```
{% for item in items %}

  {% if menu_level == 0 %}

    {%
      set item_classes = [
      'menu-item-edot',
      item.is_expanded ? 'dropdown',
      item.is_collapsed ? '',
      item.in_active_trail ? 'is-active',
    ]
    %}

    <li{{ item.attributes.addClass(item_classes) }}>

    {% elseif  menu_level == 1 %}

      {%
        set item_classes = [
        'dropdown-item',
        item.is_expanded ? 'dropdown',
        item.is_collapsed ? '',
        item.in_active_trail ? 'is-active',
      ]
      %}

      <li{{ item.attributes.addClass(item_classes) }}>
  {% endif %}
    {%
      set link_classes = [
      'nav-link',
      item.in_active_trail ? '',
    ]
      %}

    {{ link(item.title, item.url, attributes.addClass(link_classes)) }}
    {% if item.below %}

      {{ menus.menu_links(item.below, attributes.removeClass('nav-link'), menu_level + 1)  }}

    {% endif %}
  </li>

```
> 0 votes

---
Tags: theming, navigation, 9
---


# Question
Title: How can I load a template from a custom module on a certain page?
I have a page at path `/user/{id}/module`, and I'm trying to have Drupal load a custom template from my module when this page is accessed.

The twig debug output shows suggestions for the template name like below, but it doesn't seem to pick the template up even after cache rebuilds. The page needs to show for all users so cannot pin it to a specific id, but `html--user--module.html.twig` is not respected.

```
<!-- FILE NAME SUGGESTIONS:
   * html--user--module.html.twig
   * html--user--123456.html.twig
   * html--user--%.html.twig
   * html--user.html.twig
   x html.html.twig
-->

```

Is there some syntax I've not been able to find like `html--user--wildcard-id--module.html.twig`?

# Answer
> 2 votes
**Use template from a module**

You have to specify the template in `hook_theme()` with the correct base hook.

Here is example for hook 'node':

```
function MY_MODULE_theme($existing, $type, $theme, $path) {
  return [
    'node__custom-type__full' => [
      'template' => 'node--custom-type--full',
      'base hook' => 'node',
      'path' => drupal_get_path('module', 'MY_MODULE') . '/templates/content', // if custom
    ],
  ];
}

```

**Other solution : create new suggestion**

You can do this in `theme_suggestions_alter()`

Check theme\_suggestion\_alter

Here is a example, this is a solution **to create template suggestion for form with id form** :

```
function MY_THEME_theme_suggestions_alter($existing, $type, $theme, $path) {
  if ($hook === 'form' && !empty($variables['element']['#id'])) {
    $suggestions[] = 'form__' . str_replace('-', '_', $variables['element']['#id']);
  }
}

```

(Create for me the form--**user-login-form**.html.twig)

In you case, replace `$hook` by `html` and add id user

---
Tags: theming, 9
---


# Question
Title: Product parameters on add to cart form which not changing product variation
I have a phisycal product with many many combinations. E.g.: a mug which is available in 20 different colors and with 30 different prints. This means 600 combinations. We don't have stock. We don't have different SKU for different color-print combinations. We don't have pictures for all combinations, prices are same etc so there is no reason why the 600 products should be upload one-by-one as 600 different commerce product variations.

I would like to handle this product as ONE single product (one SKU: one product in one product display) which have 2 special "parameters" show only in the add to cart form: color and print.

So a customer on the product page could choose these 2 parameters then add the product to a cart and these parameters are not not formed to product variations, the product variation is fixed.

In this case he add the one product to the cart and anywhere I shoud store his color and print choice in the cart item. But.. how? Is there any solution for this use-case? Can you hint some starting point for solving this task?

Thanks!

# Answer
This is a common use case in Commerce, and as you've suggested, it's resolved not by using a single variation per combination but through custom fields added to your line item type exposed on the Add to Cart form mode.

Your primary challenge will be determining which options should be available for which product, as in the case of a particular mug not being available in certain colors. If you don't have that use case, no worries, but if you do, I've suggested folks in the past add a field for the various options to the product itself and write custom code to alter the Add to Cart form to filter available options based on that product field.
> 0 votes

---
Tags: commerce
---


# Question
Title: How to bypass node_access when using EntityFieldQuery?
With the following code, if the current user does not have 'bypass node access' (see \_node\_query\_node\_access\_alter() for exact verifications), then the query checks for node\_access, even though I do not use the "node\_access" tag.

**How can I avoid the node\_access check with the following query for a non-admin user?**

I'm using this code from a module, so I can verify permissions myself, no need for node\_access checks.

```
  $query = new EntityFieldQuery;
  $result = $query
    ->entityCondition('entity_type', 'node')
    ->entityCondition('bundle', 'foo')
    ->fieldCondition('custom_id', 'value', $custom_id)
    ->execute();

```

# Answer
> 27 votes
Drupal 7.15 allows you to bypass the access on the node.

See DANGEROUS\_ACCESS\_CHECK\_OPT\_OUT query tag added to EntityFieldQuery for more information.

> A "DANGEROUS\_ACCESS\_CHECK\_OPT\_OUT" query tag has been added to `EntityFieldQuery` to allow bypassing access checks. Previously, queries executed through `EntityFieldQuery` would always be altered by the node access system, potentially causing unexpected behaviour and data loss.
>
> If you need to bypass access checks in an internal query within your module's API, you may add this tag, but you should only do so if it is necessary. If this query tag is added to a query whose results will be displayed to the user, it will bypass all access checks, potentially exposing sensitive information.
>
> ```
> function MYMODULE_field_query($field) {
>   $query = new EntityFieldQuery();
>   return $query
>     ->fieldCondition($field)
>     ->addTag('DANGEROUS_ACCESS_CHECK_OPT_OUT')
>     ->execute();
> }
>
> ```

# Answer
> 11 votes
The answer is that you cannot.

The only workaround I can think of it to add an `account` metadata:

```
$query = new EntityFieldQuery;
$result = $query
  ->entityCondition('entity_type', 'node')
  ->entityCondition('bundle', 'foo')
  ->fieldCondition('custom_id', 'value', $custom_id)
  ->addMetaData('account', user_load(1))
  ->execute();

```

EDIT: a `DANGEROUS_ACCESS_CHECK_OPT_OUT` option has been added as part of the Drupal 7.15 security release.

# Answer
> 3 votes
For Drupal 8 you can use:

```
$query->accessCheck(FALSE);

```

---
Tags: 7, entities, users
---


# Question
Title: How migrate rich text fields from outside Drupal without converting html tags to entities
I'm working on a migration from a non-Drupal site into Drupal 9. So far, I'm using migrate\_plus, migrate\_tools, and migrate\_source\_csv modules. The data I'm importing has `<br>` and other tags in some fields. When these import, the `<br>` tags are visible on site pages after the migration completes.

The source is a tab delimited file.

Looking at the page code, these are rendering as html entities instead of tags: so `<br>` is `<br>`

I've tried changing settings many different ways in the basic HTML filter these fields use. No change.

I added a plugin for each of these fields that is, I thought, supposed to call the basic\_html filter. This also had no impact.

The two fields are field\_perm\_contact\_info and body.

Here's the relevant portion of my import configuration yaml file...

```
process:
  type:
    plugin: default_value
    default_value: source
  field_source_id: srcid
  title: title
    field_source_country:
    plugin: entity_generate
    source: country
    value_key: name
    bundle: country
    entity_type: taxonomy_term
    ignore_case: true
  field_srcfax: fax
  field_main_link: mainlink
  field_manualyr: manual
  field_perm_contact_info:
    plugin: default_value
    default_value: basic_html
    source: permcontinf
  field_permpdfname: permpdf
  field_perm_scope: permscope
  field_perm_updated:
    plugin: format_date
    from_format: n/j/Y
    to_format: Y-m-d
    source: permupdated
  field_tpop: pop
  field_rev_dateleg:
    plugin: format_date
    from_format: n/j/Y
    to_format: Y-m-d
    source: revdate
  field_short_name: shortname
  field_source_iacp_id: srciacpid
  body:
    plugin: default_value
    default_value: basic_html
    source: srcnotes
destination:
  plugin: entity:node

```

My basic\_html filter has `<br>` in the allowed tags list.

If I open an imported node and and resave, boom, it looks fine. So the question is, how to do the import so that the end result is rendered HTML, not tags displayed as html entities?

A good bit of googling hasn't gotten me to the answer to that yet.

# Answer
One way is to set the value and format separately:

```
constants:
  text_format: basic_html
process:
  field_perm_contact_info/value: permcontinf
  field_perm_contact_info/format: constants/text_format
  body/value: srcnotes
  body/format: constants/text_format

```
> 2 votes

# Answer
I'm not familiar with the use of 'constant,' so the "set the value format separately" (thanks @Clive) for my two rich text fields looks like this in my yaml file...

```
  field_perm_contact_info/value: permcontinf
  field_perm_contact_info/format:
    plugin: default_value
    default_value: basic_html
  field_permpdfname: permpdf
  field_perm_scope: permscope
  field_perm_updated:
    plugin: format_date
    from_format: n/j/Y
    to_format: Y-m-d
    source: permupdated
  field_tpop: pop
  field_rev_dateleg:
    plugin: format_date
    from_format: n/j/Y
    to_format: Y-m-d
    source: revdate
  field_short_name: shortname
  field_source_iacp_id: srciacpid
  body/value: srcnotes
  body/format:
    plugin: default_value
    default_value: basic_html

```

The key concept is to handle the text field like two 'subfields' (this post also helpful), one of them being format.
> 1 votes

---
Tags: migrations
---


# Question
Title: Problem with database version for drupal 9 db upgrade
Hi I am trying to upgrade drupal 9 on godaddy and when I go to update.php I get this note on the screen...

DATABASE SYSTEM VERSION 5.6.51-cll-lve The database server version 5.6.51-cll-lve is less than the minimum required version 5.7.8.

Godaddy told me they support only 5.6 version. Is there a workaround or we need to change host?

# Answer
> 2 votes
There’s no need to change host right away, you can install the mysql56 module which gives support up to at least Drupal 9.3.

Support won’t continue forever, so it would be a good idea to start making plans to move to a host with more up to date software.

---
Tags: database
---


# Question
Title: drupal-scaffold composer append robots.txt
We recently upgraded to Drupal 9.3.0 with the composer layout. Each time we execute `composer update` the contents of robots.txt is overlayed with the file located in `core/assets/scaffold/files/robots.txt`. We would like to append the default `robots.txt` with project unique data.

I included the following in `composer.json` per the documentation I found:

```
    "extra": {
        "drupal-scaffold": {
            "locations": {
                "web-root": "web/"
            },
            "file-mapping": {
               "[web-root]/robots.txt": {
               "append": "assets/robots.txt.append"
               }
            }
        },

```

I hesitate to create the file `core/assets/scaffold/files/robots.txt.append` as we have been trained for sometime to not change/add any files in the `core/` directory. Where should `robots.txt.append` be placed to make this work?

# Answer
> 5 votes
The path is relative to your project root (where composer.json lives), so in your example create a folder called /assets in the root, i.e. a sibling of /web.

If your question is more whether there's a particular path you *should* place it at, then the answer is: not especially. The file isn't part of the web app itself, so common sense might say don't put it in /web, but really it's up to you.

Just make sure it's placed somewhere that won't be overwritten during composer updates, and that it's included with your git commits (so not sites/default/files etc), and you'll be fine.

---
Tags: 9, composer
---


# Question
Title: create subtheme: permission problem Bootstrap5
It is not possible to create a subtheme in Bootstrap5 in Drupal 9. An issue was opened on Drupal.org and it is supposed to have been resolved, but comments continue to arrive from users who continue with the same problem: https://www.drupal.org/project/bootstrap5/issues/3219767

drupal 9.3.2 fresh install with composer on Centos server

composer require 'drupal/bootstrap5:1.1.x-dev@dev'

if i press SUBTHEME create

**ERROR: Subtheme cannot be created. Check permissions.**

directory themes (drwxrwxr-x) change a chmod 777 themes

**ERROR: Subtheme cannot be created. Check permissions.**

mkdir custom

chmod 777 custom

if i press SUBTHEME create

**ERROR: The website encountered an unexpected error. Please try again later.**

Does anyone know the trick to install a subtheme or a guide to correctly manually create a Bootstrap 5 subtheme?

# Answer
I think this problem is due to security measures on the server where Drupal runs. In order not to touch anything in the server, what I have done:

1. Install a Xampp in Windows (or Mac or Linux).
2. Install Drupal & Bootstrap 5
3. I have created the sub-theme with the proper name, etc.
4. Upload the new folder to the production server to themes/contrib
5. Change owner: `chown -Rf myuser:myuser subthemename`
6. Activate subtheme in Drupal: /admin/appearance

It works perfectly.
> 0 votes

---
Tags: bootstrap-theme
---