# Question
Title: How can I render [webform_submission:values] in a table?
I am trying to figure out from where \[webform\_submission:values\] gets rendered. This is how it looks right now in the email submission.

```
Label 1
Value 1

Label 2
Value 2

```

I want this in a table format. Is there a possibility to change the render code to do this?

# Answer
> 1 votes
You can use the Webform tokens from submitted data as following guide:

```
[webform_submission:values:?]

```

> Omit the '?' to output all values. Output all values as HTML using \[webform\_submission:values:html\]. To output individual elements, replace the '?' with…

```
element_key
element_key:format
element_key:raw
element_key:format:items
element_key:delta
element_key:sub_element_key
element_key:delta:sub_element_key
element_key:sub_element_key:format
element_key:delta:sub_element_key:format
element_key:delta:format
element_key:delta:format:html
element_key:entity:*
element_key:delta:entity:*
element_key:delta:entity:field_name:*
element_key:sub_element_key:entity:*
element_key:sub_element_key:entity:field_name:*
element_key:delta:sub_element_key:entity:*
element_key:checked:option_value
element_key:selected:option_value

```
* All items after the 'element\_key' are optional.
* The 'delta' is the numeric index for specific value
* The 'sub\_element\_key' is a composite element's sub element key.
* The 'checked' or 'selected' looks to see if an 'option\_value' is checked or selected for an options element (select, checkboxes, or radios)
* The 'option\_value' is options value for an options element (select, checkboxes, or radios).
* The 'format' can be 'value', 'raw', or custom format specifically associated with the element
* The 'items' can be 'comma', 'semicolon', 'and', 'ol', 'ul', or custom delimiter
* The 'entity:\*' applies to the referenced entity
* Add 'html' at the end of the token to return HTML markup instead of plain text.

> For example, to display the Contact webform's 'Subject' element's value you would use the \[webform\_submission:values:subject\] token.

Then you can use your custom style by adding them into table or list

# Answer
> 0 votes
You could also implement `hook_tokens_alter` and then use the `[webform_submission:values:html]` token instead.

```
 * Implements hook_tokens_alter().
 */
function onset_cart_tokens_alter(array &$replacements, array $context, BubbleableMetadata $bubbleable_metadata) {
  $options = $context['options'];

  if ($context['type'] == 'webform_submission' && !empty($context['data']['webform_submission'])) {
    /** @var \Drupal\webform\WebformSubmissionInterface $webform_submission */
    $webform_submission = $context['data']['webform_submission'];
    // Now you have access to your webform submission and can retrieve any values.

    // Alter the [webform_submission:values] token.
    if (isset($context['tokens']['values:html'])) {
      $options['html'] = TRUE;

      $replacements[$context['tokens']['values:html']] = // call the function to crate a Table element;
    }
  }
}

```

---
Tags: webforms, emails
---


title: How do I use twig templates with views?

text:
# Question
Title: How do I use twig templates with views?
I'm trying to figure out how to use twig templates with views. at the moment I'm just using twig in the view itself but I'm sure I can use twig files to overwrite the styling of the view.

e.g.

```
<div class="editorHover">
<div class="editorInside">
        {{ field_category }}
        {{ title }}
 </div>
</div>

```

I'm using this in the rewrite field of the block view with one field hidden.

How can I translate this to a twig file?

Edit1; I'll try to explain my issue in more detail. I've been working with the page.html.twig file which overwrites the default homepage used by Drupal. I'm wondering if I can do the same with blockviews. Can I overwrite the default layout, meaning html layout, divs, classes, ID's using a Html.twig file for the view?

# Answer
> 4 votes
You can overwrite `views-view-fields.html.twig` or create your personal `views-view-fields--YourViewName.html.twig` and apply the div or any wrapper you want.
I advise you to activate the twig debug to follow the suggestions

# Answer
> 2 votes
To create custom template for view create a file called  **views-view-fields--view\_name--page/block.html.twig**. Save this file in your theme's template directory.

In this file define your html structure and specify the fields you want to display in your view like {{ fields.field\_name.content }}.

It is mandatory that the fields your specifying in template file must be added to view through admin view, otherwise it will not be displayed in custom view template. Once your template file is saved clear the cache to take effect the changes.

# Answer
> 0 votes
https://www.drupal.org/project/drupal/issues/2118743 causes missing file name suggestions when using views **as blocks**.

To style them, you have to know the pattern, and contrary to what would seem obvious, you don't need to create a template for a block, but for a view.

It is `views-view--<view-name-goes-here>.html.twig` in `<theme>/templates/views`

---
Tags: views, theming
---


title: How do I get a node by its ID?

text:
# Question
Title: How do I get a node by its ID?
Using `{{ drupal_entity('node', '123', 'body') }}` in a template file, I can get the node body and title.

Is there a way to get all the available node properties?

# Answer
The general solution is to preprocess the node.

If you want to avoid coding PHP, you can use Twig Tweak, which has a handy list of twig commands it adds:

## Drupal Entity

```
{# Print a content block which ID is 1. #}
{{ drupal_entity('block_content', 1) }}

{# Print a node's teaser. #}
{{ drupal_entity('node', 123, 'teaser') }}

{# Print Branding block which was previously disabled on #}
{# admin/structure/block page. #}
{{ drupal_entity('block', 'bartik_branding', check_access=false) }}

```

## Drupal Field

```
{{ drupal_field('field_image', 'node', 1) }}

{{ drupal_field('field_image', 'node', 1, 'teaser') }}

{{ drupal_field('field_image', 'node', 1, {type: 'image_url', settings: {image_style: 'large'}}) }}

```
> 2 votes

---
Tags: 8, nodes
---


# Question
Title: Show webform textfield conditionally based on "radio other"
I have a webform "radio other", with options like "1, 2, 3, more". For "more", "radio other" is configured to add a textfield for custom values.

Now the problem is that I want to hide the custom text-field until "other" is selected, and if it's possible to do so with the existing conditional logic I can't work it out.

I've tried to work out a way to add conditional logic to the "radio other" element, but it appears I can only do so to the whole element, and not just the other part. I've also tried adding another text-field, and have it's visibility be conditioned to the "more" choice, but I can't seem to chose that in the webform conditions dialog, as it only displays the 1,2,3 options.

# Answer
You need to set the condition for the text field: Edit the webform text field and under "Condition" (I am not sure about the label in English) you choose for the status "visible" and under "Element" you choose your radio button element and as "Trigger/value" you choose "value is" (in the select box) and in the field you then choose your value "other".

With this set your text field appears when you choose "other" from the radio buttons.
> 0 votes

---
Tags: webforms
---


# Question
Title: How can I to override a specific variable from a contributed module?
My goal:

* If a person select a start date the end date is 1 hour later, without the need of selecting the **end date (2)**

Normally the Form provides 2 selections of dates, **start date (1)** and **end date (2)**.

I am able to succesfully hide **end date** (2), in bee\_add\_reservation\_form, with hook\_form\_alter().

With hook\_form\_alter() in `mymodule.module` I modified a form render array.

`$end_date` is defined in class `AddReservationForm` of the bee module.

How to alter or override the `$end_date` in class `AddreservationForm`? I would like to modify it like so:

```
    $end_date = clone($start_date);
    $end_date->modify('+1 hour');

```

Although While doing this within the class this Error occurs:

*Error: Call to protected method Drupal\bee\Form\AddReservationForm::getAvailableUnits() from global scope*

mymodule.module:

```
<?php

/**
 * Implements hook_form_alter().
 */
function mymodule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'bee_add_reservation_form') {
 /**
   * Extends the AddReservationForm class.
   *
   */

    $form['end_date'] = [
        // hides end_date
      '#type' => 'hidden',
        ];
    $form['repeat'] = [
        // hides repeat option
        '#type' => 'hidden',
          ];
    // start date from protected method
   // $start_date = new \DateTime($start_date->format('Y-m-d H:i'));
    $start_date = AddReservationForm::getAvailableUnits($start_date);

    // end date should be always 1 hour later
    $end_date = clone($start_date);
    $end_date->modify('+1 hour');

  }

```

# Answer
> 1 votes
I think hook\_form\_alter is not the correct place for this. hook\_form\_alter is called everytime the form is built/created - at this moment your user haven't filled in any start date. So this hook is only helpful to hide the field as you have done.

Instead you should add a custom submit handler in your hook\_form\_alter

```
$form['#submit'][] = 'your_custom_submit_handler';

```

and there in your submit handler you can change the values as you need.

```
function your_custom_submit_handler(array &$form, FormStateInterface $form_state) {
  $input = $form_state->getUserInput();
  $start_date = $input['start_date'];
   ...
}

```

---
Tags: forms, 9
---


# Question
Title: Disable caching of attached css/js libraries for custom module?
I have been trying to disable caching during development so I followed drupals guide step by step: https://www.drupal.org/node/2598914

After doing this I would assume that the caching is completely disabled but when I am loading a js/css file for a specific module in mymodule/mymodule.libraries.yml I still have to clear all caches for me to see any updates.

**How do you disable caching for attached libraries in custom modules?**

**test\_module.routing.yml**

```
test_module.test:
  path: '/test-me'
  defaults:
    _title: 'Testing module css cache'
    _controller: 'Drupal\test_module\Controller\TestController::test'
  requirements:
    _permission: 'TRUE'

```

**test\_module.libraries.yml**

```
test:
  version: VERSION
  css:
    theme:
      test.css: {}

```

**TestController.php**

```
<?php

namespace Drupal\test_module\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Render\Markup;

class TestController extends ControllerBase
{
    public function test()
    {
        return [
            "#markup" => Markup::create("<div class='test-class'>Hello World</div>"),
            '#attached' => [
                'library' => ['test_module/test']
            ]
        ];
    }
}

```

**test.css**

```
.test-class {
    padding: 40px;
    background-color: blue;
}

```

If I change the background-color to red for example, and refresh the page (F5, Ctrl+F5, Ctrl+Shift+R, Right click refresh -\> Clear cache and Hard Rest), it will not change to red until I clear all caches.

What piece am I missing to make this work? Or is it just not possible?

Note: It doesn't matter if I clear my browser cache at all (I currently have it disabled with devtools open)

# Answer
You are on the wrong track. Caching of static assets (and CSS files are static assets when you disable CSS/JS aggregation) has nothing to do with Drupal's cache. Disable the caching of `*.js` and `*.css` files on your web server instead (e.g in `.htaccess` if you are using Apache).
> 2 votes

# Answer
You should simply remove the `version: VERSION` line, because this declares your library to be the same version as your Drupal core version, which does not change as often. By deleting this line, Drupal will add a default query string that changes after every cache rebuild/deployment, so it will naturally cache-bust.

See https://chromatichq.com/insights/drupal-libraries-version/ for more information on the VERSION value in libraries and why it shouldn't be used by anyone outside of core.
> 3 votes

# Answer
You can use the js\_cache\_buster module and add the `enable_buster: true` value to the js you want in your library.yml file. This will increment the `?v=` value each time the cache is cleared.
> 0 votes

---
Tags: 8, caching
---


title: How to theme a pager with twig?

text:
# Question
Title: How to theme a pager with twig?
I've added a pager to a custom page rendered programmatically from a controller. I want to customize the pager. How can I do it without overriding the standard pager twig?

This is the hook\_theme:

```
function module_theme()
{
     return [
          'custom_page' => ['variables' => ['data' => null, 'pager' => null]]
     ];
}

```

This is the render array in the controller:

```
public function customPage()
{
     return [
          '#theme' => 'custom_page',
          '#data' => $data,
          '#pager' => [
               '#type' => 'pager',
          ],
     ];
}

```

The template showing on 'core/modules/system/templates/pager.html.twig'.

How can I change the template for another custom template?

# Answer
I think you have 2 possibilities:

1.) Copy the original pager.html.twig in your theme folder and adjust the template for your needs. This will adjust every pager whenever this theme is active.

2.) Define your own template suggestion for your pager:

```
/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function your_module_theme_suggestions_pager_alter(array &$suggestions, array $variables) {
   ...
   here you do some magic like "when in the $variables array is something specific
   $suggestions[] = 'pager__your_template'
   ...
}

```

Then you can use your own template suggestion (in this case pager\__your\_template.html.twig) in this specific case. Hopefully this already helps you.
> 2 votes

---
Tags: 8, theming, paging
---


# Question
Title: Why isn't possible to save revisions of the form design as draft?
Apologies if this is repeating a previous post.

I have been using the webform module for a few years, mainly creating and managing web forms for clients.

The situation I have encountered with webforms, which is a feature available in other web-based form applications, is the ability to edit a form (add, edit and delete fields etc...) and then save a draft of the edited form instance, all while the live instance is still available for the public to complete. Practically, this can allow a client to test the draft instance of a form, and then publish once the client has reviewed the changes.

Although web forms can be closed to make changes, many clients require the form to remain available 24/7, so the idea would be to allow a backend user to edit and create a draft while the live instance is still available.

Overall, I just wondered why webforms have not incorporated this feature, or could this potentially be a feature to request put forward?

# Answer
The feature exists in the config entity revisions module. There is an experimental module which takes a different approach.
> 0 votes

---
Tags: webforms, 9
---


# Question
Title: How do I programmatically set the default value of an exposed filter?
I seen many answers for Drupal 7, but I can't find any information for Drupal 9.

In `hook_form_alter()`, `$form['field_assigned_location_target_id']['#default_value'] = '553';` doesn't alter the default value for an exposed filter, which uses the value in the settings.

`$form['field_assigned_location_target_id']['#value'] = '553';` changes the value initially displayed on the filter, but it's the value submitted from the exposed filter form, independently from the value the users want to submit.

# Answer
I know the question is old, but hopefully this will help someone else. After working extensively to use hook\_views\_pre\_view, I finally found the solution by switching to hook\_views\_pre\_build. This code allowed me to make the changes I needed.

```
/**
 * Implements hook_views_pre_build().
 */
function  msul_newsletter_helper_views_pre_build(Drupal\views\ViewExecutable $view){
  /*
   * to check the format of the argument for setExposedInput, view the results
   * of getExposedInput on your view WHICH HAS HAD EXPOSED FILTERS SUBMITTED.
   * I use dpm($view->getExposedInput());
   */

  //always check the view ID so you don't affect all views.
  if($view->id()=='newsletter'){
    //check display id if you don't want to affect all displays in view.
    if( $view->current_display == 'page_2') {
      if(empty($view->getExposedInput())){
        //in my case I get $editionList from a database query.

        // because I am putting this as a default, I don't worry about other input,
        // but if you are concerned about other input, modify the array
        // from $view->getExposedInput() instead of just placing the information.
        $view->setExposedInput(['newsletter_edition_public_filter'=>
            ['edition'=>$editionList]
        ]);
      }
    }

    //in this case, I affect 2 displays.
    if($view->current_display == 'page_4'
        || $view->current_display == 'block_1'
      ){
      if(empty($view->getExposedInput())){
        //in my case I get $latestEdition from a database query.
        $view->setExposedInput(['edition'=>['edition'=>[$latestEdition]]]);
      }
    }
  }
}

```
> 0 votes

---
Tags: views, forms, 9
---


# Question
Title: How to use the user profile photo as the default image in a content type image field?
I would like to pull the current user profile photo in a content type image field but the default image option only allows the admin to choose an image file. Is there a module that allows the admin to change this behavior?

# Answer
I do not think there is any module that does this.

Setting the user profile image as the default value for a content type image will result in data duplication because the image file will be copied for each instance.

To eliminate this duplication, you could use media images and set the user profile image as a reference to a media image (which would require some rewriting of the logic for handling user profile images), and then use a media image entity reference field on the content type instead of an image field. This could be a useful contrib module but it does not exist.
> 1 votes

---
Tags: 8, nodes, users
---


# Question
Title: How to access a property in twig that begins with a hash
I'm trying to get to the name of a media file in twig. The name is located at:

```
mediaitem[0]->#values[name][x-default]

```

in the rendered entity passed into the template with `field_media_item|field_value`.

# Answer
> 1 votes
You can access hash properties in Twig `{{ foo['#bar'] }}`, but not the internal (protected) `'#values` table of an entity. Look in the media entity for public methods starting with `get`.

In this case getName():

```
{{ media.getname }}

```

The question doesn't provide information about the context, but if it is for example a node then you can access media items like this:

```
{% for field_media_item in node.field_media %}
    {{ field_media_item.entity.getname }}
{% endfor %}

```

It's recommended to use a get method if the entity provides one, because they often contain extra logic. If you don't find a get method then access the field value directly:

```
{{ field_media_item.entity.name.value }}

```

---
Tags: theming, 9
---


title: How to create settings.php?

text:
# Question
Title: How to create settings.php?
I have installed Drupal with Drush this way

```
cd WEB_APPLICATION_ROOT
composer create-project drupal/recommended-project WEB_APPLICATION_DIR_NAME
cd WEB_APPLICATION_DIR_NAME
composer require drush/drush

```

I lack the file settings.php and I understand I need to create it.

Where and how should I create it?

Should I copy `/sites/example.settings.local.php` somehow?

# Answer
> 1 votes
You've only downloaded Drush but didn't use it yet to install Drupal:

```
vendor/bin/drush site:install

```

This creates the settings.php with the database credentials this tool asks for, the same as you are asked when you install Drupal in the web browser.

---
Tags: 9, installation
---


# Question
Title: Can't change PHP version during Drush update database command
My server currently is using PHP 7.1 but I need to run PHP 7.4 during my drush commands on one of my sites. The following works for almost all commands:

```
/path/to/my/php74 ../vendor/bin/drush cr
/path/to/my/php74 ../vendor/bin/drush cim -y

```

But when I run the update database command I get an error:

```
/path/to/my/php74 ../vendor/bin/drush updb -y

```

or:

```
export DRUSH_PHP=/path/to/my/php74 && /path/to/my/php74 ../vendor/bin/drush updb -y

```

I get the following error:

```
In Process.php line 266:

  The command "/home/releases/74/vendor/drush/drush/drush updatedb:status --yes --no-entity-updates --strict=0 --uri=default --root=/ho
  me/releases/74/web" failed.

  Exit Code: 255(Unknown error)

  Working directory:

  Output:
  ================

  Warning: Unsupported declare 'strict_types' in /home/releases/74/vendor/phpstan/phpstan/bootstrap.php on line 1

  Parse error: syntax error, unexpected ':', expecting ';' or '{' in /home/releases/74/vendor/phpstan/phpstan/bootstrap.php on line 12

  Error Output:
  ================

```

I'm guessing during the updb command it calls another command but it doesn't retain my php version.

# Answer
I was able to run `drush cr` and `drush cim` using a specific php version via the command:

`/opt/cpanel/ea-php74/root/bin/php ~/public_html/vendor/bin/drush cr` and

`/opt/cpanel/ea-php74/root/bin/php ~/public_html/vendor/bin/drush cim`

This was not working, though, to run `drush updb` for which I was getting the error mentioned in my other post:

`Your Composer dependencies require a PHP version ">= 7.4.0". You are running 7.3.31.`

I could make the command line use php7.4 also for drush updb by exporting the PATH variable first with:

`export PATH=/opt/cpanel/ea-php74/root/bin:$PATH:$HOME/bin`

Then running drush updb normally.
> 2 votes

# Answer
Maybe the configuration of your composer.json depends of old php-version, so your php-code is not fresh. Check it.

And... There is useful tool for using many versions of PHP on one computer - PhpBrew. You can try it for your software upgrade.
> 0 votes

---
Tags: drush
---


title: Distinct selection of a field in views

text:
# Question
Title: Distinct selection of a field in views
I created a view in the views module which displays the blogs posted on my site having ONE tag. (Each blog has only 1 tag)

Is it possible to do a 'distinct' argument to only display every tag in this list once?

Basically, I wish to get a view with each tag's latest post.

# Answer
> 0 votes
If I understand the question correctly, you need to select only tag field in field list, and then check "Distinct" in advance panel of view. Or use aggregation in that panel.

---
Tags: views, taxonomy-terms
---


# Question
Title: Provide condtional 403 response when a user tries to view a node
Use case:

I have two roles: "Teacher" and "Student". Each Teacher has been assigned a set of Students.

This relationship is tracked by a custom entity: "Students by teacher" which has two fields:

1. Teacher (single value) - a teacher.
2. Student (unlimited values) - the set of Students supervised by this teacher.

There is also a custom node content type called "Assignment". Upon completion of an assignment, a student will save it in the Drupal database as a published node.

The Teachers have the permission "View published content". This means that with my current setup, all Teachers can view *all* published assignments, whether the author is a student they supervise or not.

What I want is this: If the assignment is authored by a Student they supervise, they shall see it. If it is not, they get a 403 ("Access denied") response.

I've been looking for a Drupal extension to solve this, and the best one I've found is **Flexi Access**. That extension has not been upgraded to Drupal 9, so I cannot use it.

I've been thinking about solving this by means of some hook that is ran when a user tries to view a node. The logic inside the hook shall be this:

1. Check if the author of the node is supervised by the person trying to view the node.
2. If "Yes", show the node. If "No", show "Access denied".

However, I've searched the API, and have so far not been able to find a hook (or some other means) that let me do this.

Somewhere at the back of my brain, I have a notion that Drupal 9 provides some other mechanism than hooks for implementing access control.

Question: How do I provide a 403 response when a user tries to view a node and some specific criteria is not satisfied?

# Answer
> 1 votes
Found out just after posting this question.

One can use hook\_ENTITY\_TYPE\_access() like this:

```
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Session\AccountInterface;
use Drupal\node\NodeInterface;

function mymodule_node_access(NodeInterface $node, $op, AccountInterface $account) {
  if ('view' == $op && CONTITION NOT SATISFIED) {
    return AccessResult::forbidden();
  }
  return AccessResult::neutral();
}

```

---
Tags: 9
---


title: Custom HTML for a form widget

text:
# Question
Title: Custom HTML for a form widget
How can I change a node edit form so that boolean fields use a toggle switch instead of a checkbox? Currently they look like this

and I would like to update them to be more intuitive like this (https://codepen.io/alvarotrigo/pen/YzEdrKj)

I think what I need to do is implement a custom widget as described here (https://www.drupal.org/docs/creating-custom-modules/creating-custom-field-types-widgets-and-formatters/create-a-custom-field-widget) but there really aren't any good docs or guides on this.

The example given there just uses a regular text field, how do I alter the HTML & CSS markup to be a toggle switch?

# Answer
> 2 votes
The doc you've linked shows that you need to define a render array for you element. You can attach an asset to it using `['#attached']` array key. See https://www.drupal.org/docs/creating-modules/adding-assets-css-js-to-a-drupal-module-via-librariesyml#s-attaching-a-library-to-a-form.

---
Tags: theming, forms, 9
---


title: How do I import local po files?

text:
# Question
Title: How do I import local po files?
There is no /admin/config/regional/translate/import page in Drupal 9 now, which exists in Drupal 7. So I don't know how to import manually translated PO files.

# Answer
You must have forgot to enable the **Interface Translation** core submodule, which provides **Interface Translation Import** at `/admin/config/regional/translate/import`.

D9 and D7 have a nearly identical UI for translation import that works the same way.
> 0 votes

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


# Question
Title: Access denied in Drush but granted in GUI
I am trying to install Drupal on a CentOS based *shared server environment* (namecheap.com) with mysql, ssh and Composer.

I have created a database username and a database with the same name and a password and granted all user privileges.

I ran:

```
cd WEB_APPLICATION_ROOT
composer create-project drupal/recommended-project WEB_APPLICATION_DIR_NAME
cd WEB_APPLICATION_DIR_NAME
composer require drush/drush
vendor/bin/drush site:install

```

I prompted:

```
 Database name [drupal]:
 > DB_NAME

 Database driver [mysql]:
 > DB_NAME

 Database username [drupal]:
 > DB_NAME

 Database password [drupal]:
 > DB_PASSWORD

 Database host [127.0.0.1]:
 > 127.0.0.1

 Database port [3306]:
 > 3306

 [warning] Program UNKNOWN not found. Proceed if you have already created or emptied the Drupal database.

 > You are about to:
 * Create a sites/default/settings.php file

 Do you want to continue? (yes/no) [yes]:
 > yes

```

## Ouput

> \[notice\] Starting Drupal installation. This takes a while.
> \[notice\] Performed install task: install\_select\_language
> \[notice\] Performed install task: install\_select\_profile
> \[notice\] Performed install task: install\_load\_profile
> \[notice\] Performed install task: install\_verify\_requirements

> In install.core.inc line 971:

> Database name field is required. Database username field is required. Resolve all issues below to continue the installation. For help configuring your database server, see the installation handbook, or contact your hosting provider.
>
> * Failed to connect to your database server. The server repor ts the following message: SQLSTATE\[28000\] \[1045\] Access denied for user 'hanekudai'@'localhost' (using passw ord: NO).
>     + Is the database server running?
>     + Does the database exist or does the database user have sufficient privileges to create the database?
>     + Have you entered the correct database name?
>     + Have you entered the correct username and password?
>     + Have you entered the correct database hostname and port number?

## GUI

when I went to `example.com/web/` and used the GUI installation with the exact same DB credentials, I have installed Drupal successfully.

## My question

What is the problem in Drush installation?

# Answer
In

```
 Database driver [mysql]:
 > DB_NAME

```

I should have prompted

```
 Database driver [mysql]:
 > mysql

```

Then the installation finished without error.
> -2 votes

---
Tags: database, drush, 9, installation
---


# Question
Title: multisite not working: one site correctly redirected, the other one throwing 500 error
Using  `Ubuntu 16.04.7 LTS` and Drupal 7.

Installed Drupal on `/var/www/html/drupal`

Created folders

```
/var/www/html/drupal/sites/siteone.org.es
/var/www/html/drupal/sites/sitetwo.com

```

Added settings.php inside the folders above

Modified `/etc/apache2/apache2.conf` to include

```
<VirtualHost *:80>
DocumentRoot /var/www/html/drupal
ServerName sitetwo.com
SeverAlias *.sitetwo.com
</VirtualHost>

<VirtualHost *:80>
DocumentRoot /var/www/html/drupal
ServerName siteone.org.es
SeverAlias *.siteone.org.es
</VirtualHost>

```

When I go to Firefox and navigate to `sitetwo.com` it works fine and the Drupal site is loaded without issues. However, when I navigate to `siteone.org.es` I get a 500 error. These are the details from Firefox:

```
HTTP/1.1 500 Service unavailable (with message)
Date: Sun, 28 Aug 2022 09:58:46 GMT
Server: Apache/2.4.18 (Ubuntu)
X-Drupal-Cache: MISS
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Cache-Control: no-cache, must-revalidate
X-Content-Type-Options: nosniff
Content-Language: es
X-Frame-Options: SAMEORIGIN
Permissions-Policy: interest-cohort=()
X-Generator: Drupal 7 (http://drupal.org)
Content-Length: 0
Connection: close
Content-Type: text/html; charset=utf-8

```

any clue what am I missing?

# Answer
I figured out what the the issue was by visiting /update.php on the site and reading the detailed error message. Several not installed modules were the main reason, among others.
> -4 votes

---
Tags: multi-sites
---


# Question
Title: Custom display_extender not able to use custom ajax callbacks inside options form
i´m working on a custom display extender for Views.

The display extender itself works as expected, i´ve taken the code mostly from Studiogd The display extender plugin now i needed in the options form a fieldset with add more button, so i tried to implement/adapt \Drupal\form\_api\_example\Form\AjaxAddMore for my options form.

But i have a problem calling the submit and ajax callback.

Here is a subset of my display extender that is probalby relevant

```
namespace Drupal\foo\Plugin\views\display_extender;

use Drupal\views\Plugin\views\display_extender\DisplayExtenderPluginBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Foo display extender plugin.
 *
 * @ingroup views_display_extender_plugins
 *
 * @ViewsDisplayExtender(
 *   id = "foo",
 *   title = @Translation("Foo"),
 *   help = @Translation("Foo Bar."),
 *   no_ui = FALSE
 * )
 */
class Foo extends DisplayExtenderPluginBase {

  ...

  /**
   * Provide a form to edit options for this plugin.
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {

   ...

    $form['foo']['filters_fieldset']['actions']['add_filter'] = [
      '#type' => 'submit',
      '#value' => $this->t('Add an entry'),
      '#submit' => [
        '::addFilterEntry', // <---- Taken from example
      ],
      '#ajax' => [
        'callback' =>  '::filtersFieldsetCallback',
        'wrapper' => 'filters-fieldset-wrapper',
      ],
    ];

    ...
  }

  ...

  /**
   * Submit handler for the "add-one-more" button.
   *
   * Increments the max counter and causes a rebuild.
   */
  public function addFilterEntry(array &$form, FormStateInterface $form_state) {

    $filter_field = $form_state->get('num_filters');
    $add_button = $filter_field + 1;
    $form_state->set('num_filters', $add_button);

    // Since our buildForm() method relies on the value of 'num_filters' to
    // generate 'filter' form elements, we have to tell the form to rebuild. If we
    // don't do this, the form builder will not call buildForm().
    $form_state->setRebuild();
  }

  /**
   * Callback for both ajax-enabled buttons.
   *
   * Selects and returns the fieldset with the filters in it.
   */
  public function filtersFieldsetCallback(array &$form, FormStateInterface $form_state) {
    return $form['foo']['filters_fieldset'];
  }

  ...

}

```

Now when i click the add more button in the options form it Results in:

> call\_user\_func\_array() expects parameter 1 to be a valid callback, class 'Drupal\views\_ui\Form\Ajax\Display' does not have a method 'addFilterEntry'

So I tried to specify it like:

```
'#submit' => [
    [$this, 'addFilterEntry'],
],

```

which actually lets call\_user\_func try to call 'addFilterEntry' on my class and i get

> The specified #ajax callback is empty or not callable.

makes sense, now when I also change the ajax callback to

```
'#ajax' => [
   'callback' => [$this, 'filtersFieldsetCallback'],

```

I cant open the options form anymore resulting in a 5xx response

```
InvalidArgumentException: Recursion detected in Symfony\Component\HttpFoundation\JsonResponse->setData() (line 169 of /srv/www/htdocs/foo.dev/vendor/symfony/http-foundation/JsonResponse.php).

Drupal\Core\Ajax\AjaxResponseAttachmentsProcessor->processAttachments() (Line: 62)
Drupal\Core\EventSubscriber\AjaxResponseSubscriber->onResponse()
call_user_func() (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch() (Line: 191)
Symfony\Component\HttpKernel\HttpKernel->filterResponse() (Line: 179)
Symfony\Component\HttpKernel\HttpKernel->handleRaw() (Line: 80)
Symfony\Component\HttpKernel\HttpKernel->handle() (Line: 58)
Drupal\Core\StackMiddleware\Session->handle() (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle() (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle() (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle() (Line: 23)
Stack\StackedHttpKernel->handle() (Line: 708)
Drupal\Core\DrupalKernel->handle() (Line: 19)

```

i have a feeling that the difference is that the options form itself is already loaded with ajax but I have no clue how i can solve this or where to find example code

# Answer
The plugin class is not a form class. The method `buildOptionsForm` is called by the parent form to get additional form elements. Callbacks referencing `$this` will reference an instance of the form class, not the plugin class.

You can only define static plugin callbacks

```
public static function filtersFieldsetCallback(array &$form, FormStateInterface $form_state) {
  return $form['foo']['filters_fieldset'];
}

```

referenced by the form element:

```
'#ajax' => [
  'callback' => [static::class, 'filtersFieldsetCallback'],

```

This is true for most option forms defined in plugins. Specific to this Views plugin is that form caching is disabled, so we can't use $form\_state to store data between requests, only within the request. So try to count the fields in the submitted user input:

```
  // Gather the number of filters in the form already.
  $num_filters = $form_state->get('num_filters');

  if ($num_filters === NULL) {
    // Count the filter fields submitted. If none, start with one filter
    $input = $form_state->getUserInput();
    if (isset($input['foo']['filters_fieldset']['filter'])) {
      $num_filters = count($input['foo']['filters_fieldset']['filter']);
    }
    else {
      $num_filters = 1;
    }
    $form_state->set('num_filters', $num_filters);
  }

```
> 1 votes

---
Tags: views, 9
---


# Question
Title: Access (none related) entities from within twig without preprocessing
Within a nodes Twig template I am able to access e.g. referenced fields with...

```
{{ node.field_my_entity_reference.0.entity.field_my_field.0.value }}

```

With the help of Twig Tweak I am able to render fields from specific nodes by referencing their NID (here NID 1)...

```
{{ drupal_field('field_my_field', 'node', 1) }}

```

Now is it possible to directly access the fields of specific nodes by their NID, not just getting the rendered content, either by a way Drupal already provides or with the help of a module like Twig Tweak? I know this is possible through preprocessing, but I'm searching for a way to do this directly in Twig.

# Answer
> 0 votes
In addition to the solution provided by Andreas, I found a very easy and useful way to do this using a contrib module called Bamboo Twig. It will give you the ability to load any node within a twig template and access its fields.

```
{% set node_of_interest_nid = 1 %}
{% set node_of_interest_nid_content = bamboo_load_entity('node', node_of_interest_nid) %}
{{ node_of_interest_nid_content.field_myfield.value }}

```

Hope this helps.

# Answer
> 1 votes
Drupal twig prevents you from a few functions, but if it is a valid usecase, you can add custom functionality via a custom twig extension, let's say `get_any_node_field_value`

in twig:

```
<div>
  {{get_any_node_field_value(nodeId, 'field_my_custom_name')}}
</div>

```

This article appears to give a good introduction into setting up a custom twig extension. In a nutshell:

web/modules/custom/your\_module/src/Extension/TwigExtension.php:

```
<?php

namespace Drupal\your_module\Extension;

use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;

class TwigExtension extends AbstractExtension {

  public function getFunctions(): array {
    return [
      new TwigFunction('get_any_node_field_value', [$this, 'get_any_node_field_value']),
    ];

    public function get_any_node_field_value ($nodeId, $fieldName) {
      // your logic goes here
    }

}

```

Please keep in mind, that this does not effect your cache settings, so you will not get automatic template updates, if the unrelated node X changed. Depending on your usecase this might not be an issue, but it might fall on your toes later. If you need to care about caching, it's better to go via the preprocess and extend also the cache tags.

---
Tags: theming
---


title: How do I remove /web from the URL?

text:
# Question
Title: How do I remove /web from the URL?
I have a site using Drupal 8.5 I installed with Composer.
When users want to visit the site, they'd normally need to add /web after the domain to access it. I have a cpanel redirect that redirects users from domain abc.com to abc.com/web, so they don't have to add /web.
This solution is still a bit silly because the visitors still see the abc.com/web while I really want it to look like a regular website domain, domain.com.

I'm not allowed to use virtual hosts, but I am allowed to use htacces or symlinks. How do I "redirect" visitors from domain localhost/temp-project to localhost/temp-project/web/index.php without having /web in the URL?

--Update 2-- I've tried to add a .htaccess snippet (from GitHub) in my root (localhost/temp-project) to point to /web and browsed to localhost/temp-project:

```
#Redirect to www location with subdirectory
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} localhost/temp-project [NC]
RewriteRule ^(.*)$ /web/index.php[R=301,NC]

```

This just doesn't do anything, what's going wrong here?

# Answer
> 4 votes
You should have your host point directly to the "web" directory instead of your project root. I've run into this issue on webfaction hosting and my solution (actually my co-worker's) was to have 2 "apps." The first app is not web accessible and this is where my drupal-composer/drupal-project's root is. Then I create a second app that is web accessible, e.g. `domain.com` and is a symlink to the first app's `/web` directory. Maybe you can use this same approach.

# Answer
> 3 votes
If using cPanel:

1. Go to Domains \> Domains.
2. Click "Manage" for the domain you want
3. Edit the path to the "New Document Root".

# Answer
> 0 votes
If you can't change the project root, then I'd suggest either doing a Rewrite directive within .htaccess or just making an alias on Drupal (or setting the homepage to be /web).

# Answer
> -2 votes
I have a very simple way I solve this issue. Instead of reconfiguring server to set new document root or writing rewrites, I think it is so far easier to make a 'modified install'. It is simple, takes a few minutes to modify your composer.json and complete your installation, and for the life of the website, you don't have to tamper with any server settings nor .htaccess nor settings.php nor any of such. It very easily saves tons of headache getting round the 'web/' folder issue, it neatly avoids it and gets you to set whatever you want as your web-root.

Read more in this my answer, How to remove subdir from base URL after installing site with Composer on a shared host?

# Answer
> -2 votes
**Step 1**. You have to install Drupal using this command ***composer create-project --no-install drupal/recommended-project my\_site\_name\_dir*** with the help of composer.

**Step 2**. You have to make some changes in the ***composer.json*** file as per the code listed below and you have to save file.

```
    "extra": {
    "drupal-scaffold": {
        "locations": {
            "web-root": "./"
        }
    },
    "installer-paths": {
        "core": [
            "type:drupal-core"
        ],
        "libraries/{$name}": [
            "type:drupal-library"
        ],
        "modules/contrib/{$name}": [
            "type:drupal-module"
        ],
        "profiles/contrib/{$name}": [
            "type:drupal-profile"
        ],
        "themes/contrib/{$name}": [
            "type:drupal-theme"
        ],
        "drush/Commands/contrib/{$name}": [
            "type:drupal-drush"
        ],
        "modules/custom/{$name}": [
            "type:drupal-custom-module"
        ],
        "profiles/custom/{$name}": [
            "type:drupal-custom-profile"
        ],
        "themes/custom/{$name}": [
            "type:drupal-custom-theme"
        ]
    },

```

**Step 3**. After that you have to enter in ***my\_site\_name\_dir*** directory of the project and run this command ***composer install*** in composer.

**Step 4** Your code is ready you need to setup your project accordingly.

---
Tags: 8
---


title: Can't load form from my Install Profile

text:
# Question
Title: Can't load form from my Install Profile
I have a `WelcomeForm` inside my `src` folder in my install profile. My install profile is located inside web/profiles folder and is correctly selected by default during install.

However, I added an install task (inside my `business_profile.install` file) as so...

```
function business_profile_install_tasks_alter() {
  $new_task['install_welcome'] = [
    'display' => TRUE,
    'type' => 'form',
    'function' => '\Drupal\business_profile\src\Form\WelcomeForm'
  ];

```

But the installer shows an error -

```
InvalidArgumentException. Form \Drupal\business_profile\src\Form\WelcomeForm is not a valid form in... ->getFormId()

```

My `WelcomeForm` extends FormBase and implements `getFormId()` returning a valid string. Also implements `buildForm()` and returns a valid $form array. Nothing wrong anywhere.And here's my WelcomeForm...

```
<?php

namespace Drupal\business_profile\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class WelcomeForm extends FormBase {

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

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

    $form['#title'] = $this->t('Welcome');

    $form['actions'] = [
      '#type' => 'actions'
    ];

    $form['actions']['save'] = [
      '#type' => 'submit',
      '#value' => $this->t('Save and continue'),
      '#button_type' => 'primary',
      '#submit' => ['::submitForm'],
    ];
    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $form_state->setRedirect('<front>');
  }

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

}

```

And I can confirm the form is saved as `web/profiles/business_profile/src/Form/WelcomeForm.php`

What could possibly make Drupal installer not to see my Form then? Is this an autoload issue (just suspecting) - but I thought files in a selected install profile (distribution) are autoloaded?

Spent a few days on this, any help pls guys?

# Answer
> 3 votes
Ok, guys - I just sorted this out! But you have all been awesome, thanks a bunch! Following leymanxx suggestions, I replaced `'function' => '\Drupal\business_profile\src\Form\WelcomeForm'` with `'function' => WelcomeForm::class`, and then made an import on top.

I also had to add an autoload entry to my `web/profiles/business_profile/composer.json` file like this...

```
    "autoload": {
        "psr-4": {
            "Drupal\\business_profile\\": "src"
        }
    },

```

I then did a composer update and saw `Generating autoload files` message on my terminal. And bam!! Form shows up.

Now I get to design my form. Thanks a bunch @leymanxx, @cilefen, @Tritof and everyone else that helped out on this.

# Answer
> 1 votes
See #2965929; it's probably the class name not matching the file name. The file needs to be named WelcomeForm.php.

Please also remove the `src` from the function assignment. It needs to be `'function' => '\Drupal\business_profile\Form\WelcomeForm'`.

---
Tags: 9, installation-profiles
---


title: Error migrating files from CSV

text:
# Question
Title: Error migrating files from CSV
I'm trying to migrate a csv file that I build from a drupal 6 site.

I have create a view to export those fields: `"fid","filemime","filename","image_path","changed","estado"`  , "estado" is "status" field.

I have check the /web/core/file/migratrions/, also I have read: https://understanddrupal.com/lessons/migrating-files-and-images-drupal/, and some other blog post.

```
My file.yml is:

# Every migration that references a file by Drupal 6 fid should specify this
# migration as an optional dependency.
id: project_files
label: Public files
audit: true
migration_group: files
audit: true
migration_tags:
  - Drupal 7
  - Files
source:
  plugin: 'csv'
  path: public://csv/files/files.csv
  delimiter: ','
  enclosure: '"'
  header_offset: 0
  constants:
    # The tool configuring this migration must set source_base_path. It
    # represents the fully qualified path relative to which URIs in the files
    # table are specified, and must end with a /. See source_full_path
    # configuration in this migration's process pipeline as an example.
    source_base_path: 'https://domain.es/sites/domain.prod1.domain.es/files/'
    file_directory_path: 'public://old_yaq'
    temp_directory_path: '/tmp'
    is_public: true
  ids:
    - fid
process:
  # If you are using this file to build a custom migration consider removing
  # the fid field to allow incremental migrations.
  fid: fid
  filename: filename
  source_full_path:
    -
      plugin: concat
      delimiter: /
      source:
        - constants/source_base_path
        - image_path
    -
      plugin: urlencode
  destination_full_path:
    plugin: file_uri
    source:
      - image_path
      - constant/file_directory_path
      - constant/temp_directory_path
      - constant/is_public
  uri:
    plugin: file_copy
    source:
      - '@source_full_path'
      - '@destination_full_path'
  filemime: filemime
  # No need to migrate filesize, it is computed when file entities are saved.
  # filesize: filesize
  status: estado
  # Drupal 7 didn't keep track of the file's creation or update time -- all it
  # had was the vague "timestamp" column. So we'll use it for both.
  created:
    plugin: date_2_timestamp
    source:
      - changed
  changed:
    plugin: date_2_timestamp
    source:
      - changed
  uid: uid
destination:
  plugin: entity:file

```

And this is my plugin

```
<?php

namespace Drupal\yaq_migration\Plugin\migrate\process;

use Drupal\migrate\MigrateExecutableInterface;
use Drupal\migrate\ProcessPluginBase;
use Drupal\migrate\Row;

/**
 * Perform custom value transformations.
 *
 * @MigrateProcessPlugin(
 *   id = "date_2_timestamp"
 * )
 *
 * To do custom value transformations use the following:
 */
class DateToTimestamp extends ProcessPluginBase {

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {

    if (empty($value[0])) {
      return time();
    }
    return strtotime($value[0]);
  }

}

```

I get this output:

```
wodby@php.container:/var/www/html $ drush migrate:import project_files
 [notice] Processed 2546 items (0 created, 0 updated, 2546 failed, 0 ignored) - done with 'project_files'

In MigrateToolsCommands.php line 971:

  project_files Migration - 2546 failed.

```

I don't find what it's wrong.

Oskar.

# Answer
> 0 votes
My error was here:

```
    source:
      - image_path
      - constant/file_directory_path
      - constant/temp_directory_path
      - constant/is_public

```

It should be `constants` this s at the end.

---
Tags: migrations, 9
---


# Question
Title: Issues with updating modules on Drupal 7
I have a Drupal 7 website that I upgraded from Drupal 6 awhile ago. I am trying to upgrade some of the modules that have had updates since then, but I am having issues doing so. When I click the "Continue" button on the "ready to update" screen, I receive the following unformatted text on a blank white background:

> Installing updates
>
> Status message
>
> Operating in maintenance mode.Go online.

The url of the page is example.com/authorize.php?batch=1&op=start&id=4206

I checked the error logs in Drupal, and there are a few errors reports:

> Notice: Undefined variable: finished in \_batch\_process() (line 344 of /home/mysite/public\_html/includes/batch.inc).
>
> Notice: Undefined variable: old\_set in \_batch\_process() (line 339 of /home/mysite/public\_html/includes/batch.inc).
>
> Notice: Undefinedvariable: old\_set in \_batch\_process() (line 338 of /home/mysite/public\_html/includes/batch.inc).
>
> Notice: Undefined variable: old\_set in \_batch\_process() (line 337 of /home/mysite/public\_html/includes/batch.inc).
>
> Notice: Undefined index: init\_message in \_batch\_progress\_page\_js() (line 136 of /home/mysite/public\_html/includes/batch.inc).
>
> Notice: Undefined index: error\_message in \_batch\_progress\_page\_js() (line 135 of /home/mysite/public\_html/includes/batch.inc).
>
> Notice: Undefined index: title in \_batch\_progress\_page\_js() (line 127 of /home/mysite/public\_html/includes/batch.inc).

Any ideas on what might be causing this and how I an fix it?

# Answer
I have encounted this in the past and usually you get a module that causes an issue with AJAX.

What I would suggest is to update modules manually (download from drupal.org, extract and upload then run update.php) or via drush one by one.

If you are doing multiple modules at once this can happen quite often.

Also make sure you have Overlay module disabled as for some odd reason this can cause the same error.

Your best bet is to update modules one by one to isolate which module is causing the issue.
> 2 votes

# Answer
This is a bit tangential, but I mention it to help anyone searching specifically for this error:

> Undefined variable: finished in \_batch\_process() (line 303 of /htdocs/includes/batch.inc)

...whilst using the *Editable Views* (editableviews) module. The symptom for the user is saving the form and then it getting stuck on 'Initialising' on the batch screen, when you're just updating a single record, and manually refreshing the page will show the update has gone through.

In the view's Format \> Settings page, if you scroll down, there's a checkbox right at the bottom labelled "Enable batch support" ("Use Batch API to save huge data.")

Just turn that off and the problem will go away.
> 0 votes

---
Tags: 7, updating, upgrading
---


# Question
Title: What to set up in a Kernel test to get custom content type to be available
I have a custom module that defines a service and a custom content type. I have successfully written a Functional test for the service. Now, I'm seeing if I can write a Kernel test instead.

The issue that I'm encountering is that my custom content type has custom fields (naturally). When I create a piece of content of that type in the Kernel test environment, Drupal is not recognizing the custom fields.

* I am using the EntityKernelTestBase.
* I have set `public static $modules = array('my_custom_module', 'node');`

What piece(s) am I missing? I'm guessing there is some schema I need to say to install or some other method I need to call so that those custom fields are recognized.

```
<?php

namespace Drupal\Tests\my_custom_module\Kernel;

use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Drupal\node\Entity\Node;

/**
 * Tests the my custom service.
 *
 * @group my_custom_module
 */
class MyCustomServiceKernelTest extends EntityKernelTestBase {

  /**
   * Modules to install.
   *
   * @var array
   */
  public static $modules = array('my_custom_module', 'node');

  /**
   * {@inheritdoc}
   */
  public function setUp() {

    parent::setup();

    $user = $this->createUser();

    $container = \Drupal::getContainer();
    $container->get('current_user')->setAccount($user);

    // Create some aquifer pieces of content
    $node = Node::create(array(
      'title' => t('Some title'),
      'type' => 'my_custom_content_type',
      'language' => 'en',
      'field_my_custom_field_1' => 'Put stuff here',
      'field_my_custom_field_2' => 'more stuff',
      'field_my_custom_field' => 1000000,
    ));
    $node->save();
    $reloaded_entity = $this->reloadEntity($node);
    $this->assertSame('debug', $reloaded_entity);
  }
}

```

The debug assert statement shows that the reloaded entity does not contain my custom fields.

If I put a `$node->set('field_my_custom_field_1', 'some value')` statement in the code instead of passing those fields in the `Node::create` logic I get an error that the field name is not valid.

# Answer
For kernel tests you need to specify which configurations you want installed. For instance, you'll need something like this in your test's `setUp()` method:

```
$this->installConfig(['my_custom_module']);

```

That takes an array of modules, so you'll probably need to specify additional modules (like `filter`, `node`, and `field` potentially).

This assumes your field configurations are bundled in your module's `config/install` directory.
> 10 votes

# Answer
1. It's not necessary to put your modules configs to `config/install`. Let the config in `config/optional`
2. Important: check the module dependencies

a) for your content type (`'my_custom_content_type'`) by opening the config file `node.type.my_custom_content_type.yml`,

b) for the special fields like `'text'` (that need additional modules) by opening `field.storage.node.MY_SPECIAL_FIELD.yml`

yaml field

```
dependencies:
  module:
    - DEP_MODULE_N

```
3. Add installing modules 'DEP\_MODULE\_N' and 'my\_custom\_module' and needed schema:

```
class ImportBatchKernelTest extends KernelTestBase {

  protected static $modules = [
    'system',
    'user',
    'DEP_MODULE_1',
    'field',
    'node',
    'DEP_MODULE_2',
    'my_custom_module',
  ];

protected function setUp() : void {
    parent::setUp();

    $this->installEntitySchema('user');
    $this->installEntitySchema('node');
    $this->installSchema('node', 'node_access'); // <-- needed at least for entity reference fields, just test :-)
    $this->installConfig(['node', 'my_custom_module']);
  }

...
...

```
4. The modules `'system'`, `'user'`, `'field'`, `'node'` are needed for testing manipulations of nodes.
> 1 votes

---
Tags: 8, testing
---


# Question
Title: Template suggestions not showing in markup
I can't get the Twig file name suggestions in the markup. I'm on D9, ddev and multisite. I have tried all kinds of cache rebuilds.

When running `drush php:eval "var_export(\Drupal::getContainer()->getParameter('twig.config'));"` in the terminal, I get:

```
array (
  'debug' => true,
  'auto_reload' => true,
  'cache' => false,

```

So when clearing caches doesn't help, what is the next step?

Edit: I just found out that it somehow actually shows suggestion deeper into the markup but it should show at least in the beginning at `<html>` too.

These two screenshots are from different projects showing the difference:

*^ What I expect to see*

*^ What I see*

# Answer
> -1 votes
Turned out that there was a module called MinifyHTML that stripped all comments.

---
Tags: 9
---


title: How do I divide two numbers?

text:
# Question
Title: How do I divide two numbers?
I seem to be doing something wrong. I am trying to divide the price by 1.2 in commerce-invoice.html.twig.

With `{{ invoice_item.getTotalPrice|commerce_price_format / 1.2}}`, when `invoice_item.getTotalPrice|commerce_price_format` is 10, I get 8.33; when `invoice_item.getTotalPrice|commerce_price_format` is 10.5, I get 8.33 instead of 8.75.

# Answer
> -3 votes
without commerce\_price\_format any number divisible by 1.2 = 0.83333333333333 divide by 1.5 is = 0.66666666666667

On division takes {{ invoice\_item.getTotalPrice }} = 1

---
Tags: commerce, 9
---


title: How do I implement an AJAX callback?

text:
# Question
Title: How do I implement an AJAX callback?
Given is a Drupal 9 project.

How can I make use of Drupal functionality through an AJAX call?

`web/modules/custom/mymodule/src/Appointment.php`

```
namespace Drupal\mymodule;

class Appointment {
  public function getUser() {
    return \Drupal::currentUser()->id();
  }
}

```

`web/modules/custom/mymodule/src/ajax/getUser.php`

```
<?php

namespace Drupal\mymodule;

require_once '../Appointment.php';

$appointment = new Appointment();

echo $appointment->getUser();

```

`theme-source/my-theme/js/script.js`

```
(function ($, Drupal) {

  body.on('click', '#get-user', function(e) {
    $.ajax({
      url: '/modules/custom/mymodule/src/ajax/getUser.php',
      type: 'post',
      success: function (response) {
        $('#get-user').after(response);
      },
      error: function (jqXHR, textStatus, errorThrown) {
        console.error(textStatus + ' - Unable to get user');
        console.error(errorThrown);
      }
    });
  });

})(jQuery, Drupal);

```

Error that is returned:

> **Fatal error:** Uncaught Error: Class 'Drupal' not found in /var/www/html/web/modules/custom/mymodule/src/Appointment.php:318 Stack trace: #0 /var/www/html/web/modules/custom/mymodule/src/ajax/getUser.php(9): Drupal\mymodule\Appointment-\>getUser() #1 {main} thrown in **/var/www/html/web/modules/custom/mymodule/src/Appointment.php** on line **318**

When testing, the `getUser()` function works and I can `dpm` the ID. When replacing the `\Drupal::currentUser()->id();` call with a string, the AJAX call works properly. So I assume that through AJAX, Drupal is not accessible in this way.

`web/modules/custom/secondmodule/secondmodule.module`

```
function secondmodule_form_alter(&$form, &$form_state, $form_id) {
    $appointment = new \Drupal\mymodule\Appointment();
    dpm($appointment->getUser(), 'User');
}

```

# Answer
> 1 votes
Thank for the directions Kevin. After creating a route and call its URL with jQuery allowed me to continue.

`web/modules/custom/mymodule/mymodule.routing.yml`

```
mymodule.get_available_times:
  path: /admin/config/mymodule/getuser
  defaults:
    _controller: '\Drupal\mymodule\Controller\GetUser::getUser'
  requirements:
    _access: 'TRUE'

```

`web/modules/custom/mymodule/src/Controller/GetUser.php`

```
<?php

namespace Drupal\databride\Controller;

use Drupal\databride\Appointment;
use Symfony\Component\HttpFoundation\Response;

class GetUser {
  public function getUser() {
    $appointment = new Appointment();
    $userdata = $appointment->getUser();

    return new Response($userdata);
  }
}

```

---
Tags: javascript, ajax
---


# Question
Title: Extracting content from a broken site database
I am working on a broken Drupal site which doesn't load.

Is it possible to extract the node data from the database and import them into a fresh Drupal installation?

# Answer
> 1 votes
You can use the Migrate API to connect to the legacy DB and import the data into a different Drupal instance. See Migrate API overview.

---
Tags: migrations, importing-exporting
---


# Question
Title: TFA Module not providing place to enter code, email is sent
I am having trouble getting TFA working on a new site -- Drupal 9.4.

My key's in place, I have email enabled, as well as trusted browser, etc. But when I go to login, after I enter the username and password, I am just returned back to the login page. The mail with the code gets sent -- I just have nowhere to enter that code.

I have another site, in the same multi-site, where it is working as expected. I enter my username and password, and it takes me to a page to enter my code. I did set the other one up a while back, but I can't find any significant differences between the two setups (the one minor thing is that the order to plugins is different on the settings page).

Feel like there must be something simple I am missing, a companion module I haven't installed, but I have yet to find it.

Permissions are set up the same on the two sites. I don't see any related errors logged.

Update:

* The code seems to be firing through TFA.
* It looks like it gets to the right route tfa/{userid}/{hash}
* The formstate redirect seems to be set correctly
* but it ends back on user/login

# Answer
The problem here was that I had a module with a **hook\_user\_login\_form\_submit** redirecting the user to **/user** which was overwriting the redirectURL of the submit form.

The good news is that I understand forms a bit better! It was pretty difficult to know that the redirect was being overridden... and I didn't know enough to look for it until I'd understood how the form worked.
> 0 votes

---
Tags: authentication-authorization
---


# Question
Title: How to print paragraphs in twig template?
I have a content type, basic, where i have added a Paragraph field `field_pr` that has two fields: `field_text`, `field_color`. I have a twig template `node--basic--full.html.twig` where I want to print the value of the paragraph field `node.field_pr`.

`node.field_pr` can have between one and ten paragraph values.

When I print the array for `content.field_pr`, I get a huge array. However, I only want the values from the `field_pr.field_text` and field\_pr.field\_color. How would I be able to do this from the node twig template?

I have tried the following but cannot seem to access the values. What am I missing?

```
{% for field in content.field_pr %}
   {{ field[loop.index0].entity.field_text.value }}
   {{ field[loop.index0].entity.field_color.value }}
{% endfor %}

{% for field in content.field_pr %}
   {{ field[loop.index0]['#paragraph'].field_text.value }}
   {{ field[loop.index0]['#paragraph'].field_color.value }}
{% endfor %}

```

Here is an image of the array that is printed for the `node.field_pr` field.

# Answer
Not sure if it's possible with your current approach. Here is how I would approach this.

In your node template file just do a `{{ content.field_pr }}`

Create a template file for your paragraph.

> paragraph\__\[view\_mode\] (e.g. paragraph--default.html.twig)
>
> paragraph\__\[type\] (e.g. paragraph--image.html.twig)
>
> paragraph\__\[type\]\__\[view\_mode\] (e.g. paragraph--image--default.html.twig)
>
> source: Theming in Paragraphs for Drupal 8

In **paragraph--\[type\].html.twig** you do `{{ content.field_text }}` and `{{ content.field_color }}`
> 8 votes

# Answer
To print paragraph fields in a loop (for sliders, etc.) in `page--content-type.html.twig` use below snippet:

```
{% for item in node.field_paragraph_mac_name %}
  {{ item.entity.field_title.value }}
  <img src="{{ file_url(item.entity.field_image.entity.fileuri) }}" />
{% endfor %}

```
> 8 votes

# Answer
I figured this one out. With Twig Tweak enabled you can print paragraphs from the node object without using content:

```
{% for item in node.field_my_paragraph_field %}
     {{ drupal_entity('paragraph', item.target_id) }}
{% endfor %}

```
> 4 votes

# Answer
Building on the answer by user33560. If you have have nested paragraphs and you want to print or get the 2nd-level paragraph fields from within the 1st-level `paragraph.html.twig`:

```
{% set paragraph_name = content.field_paragraph_name %}

{% for item in paragraph_name['#items'] %}
    {{ drupal_entity('paragraph', item.target_id) }}
{% endfor %}

```

You can also use `{{ content.field_paragraph_name }}` to print all paragraph items, or print a subset such as `{{ content.field_paragraph_name.field_example }}`. Use `{{ content.field_paragraph_name|without('field_example') }}` to temporarily suppress the printing of a given child element.
> 2 votes

# Answer
You can use `{{ node.ref_field_name.entity.field_name.value }}`
> 0 votes

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


# Question
Title: How do I make an FTP connection from a module?
I'm trying to create a custom module that would connect to an external FTP and grab an XML file (provided by third party). This file can't be accessed through http.

In Drupal 8, there is the `Drupal\Core\FileTransfer\FTP` class, but I'm not sure as of how I could use it inside my custom module. I don't see any service I could use.

Do I use that class directly, or is there a service I need to use?

# Answer
> 1 votes
The information about the classes that extends `FileTransfer()` are returned from `hook_filetransfer_info()`, and altered by `hook_filetransfer_info_alter()`. There isn't any service to use.
As such, the code that uses that class should be similar to the following one.

```
$info = drupal_get_filetransfer_info();

if (!empty($info['ftp']) && $class = $info['ftp']['class']) {
  $ftp = $class::factory($jail, $settings);
}

```

Notice that when the patch in Convert hook\_filetransfer\_info() to plugin system will be applied to Drupal 8.x.3, the code I wrote will probably need to be changed, if the change is not going to be backward-compatible.

# Answer
> 0 votes
As mentioned by @apaderno there is a `FileTransfer` class, however, it performs uploads **only**. @see https://www.drupal.org/forum/support/module-development-and-code-questions/2011-05-24/filetransferftp-error

Upload example (not tested)

```
use Drupal\Core\FileTransfer\FileTransferException;

$info = drupal_get_filetransfer_info();

if (empty($info['ftp'])) {
  \Drupal::messenger()->addError('FTP php extension not available.');
  return;
}
$class = $info['ftp']['class'];
$ftp = $class::factory(DRUPAL_ROOT, [
  'advanced' => [
    'hostname' => 'ftp.my.site.com',
  ],
  'username' => 'myusername',
  'username' => 'mypassword',
  'port' => 21,
]);
try {
  // Uploads - @see ftp_put().
  // Where local is inside $jail which is $class::factory($jail, [...]);
  // Where remote is `ftp.my.site.com/path/to/remote/file/name.txt`.
  $ftp->copyFile('/path/to/local/file/name.txt', '/path/to/remote/file/name.txt');
}
catch (FileTransferException $e) {
  \Drupal::messenger()->addError($e->getMessage());
}

```

Sample download - tested (to a variable so binary / text)

```

use Drupal\Core\FileTransfer\FileTransferException;

$info = drupal_get_filetransfer_info();

if (empty($info['ftp'])) {
  \Drupal::messenger()->addError('FTP php extension not available.');
  return;
}

$class = $info['ftp']['class'];
$ftp = $class::factory(DRUPAL_ROOT, [
  'advanced' => [
    'hostname' => 'ftp.my.site.com',
  ],
  'username' => 'myusername',
  'username' => 'mypassword',
  'port' => 21,
]);
$data = NULL;
try {
  // Login, throws exception if login error, else defines `$ftp->connection`.
  $ftp->connect();
  // Optional - set passive connection..
  ftp_pasv($ftp->connection, TRUE);
  ob_start();
  $result = ftp_get($ftp->connection, 'php://output', '/path/to/remote/file/name.txt', FTP_BINARY);
  $data = ob_get_contents();
  // File size if needed.
  // @see https://stackoverflow.com/a/47240733/5150644
  $datasize = ob_get_length();
  ob_end_clean();
  ftp_close($ftp->connection);
}
catch (FileTransferException $e) {
  \Drupal::messenger()->addError($e->getMessage());
}
// Do something with the date, e.g. save it.
if ($data) {
  file_put_contents('public://myfile.txt');
}

```

---
Tags: 8, files
---


title: Theming embeded entities

text:
# Question
Title: Theming embeded entities
I'm using the **entity\_embed** contrib module (8.x-1.2) in drupal 9.4. I embedding entities inside a node body in ckeditor.

The function `mytheme_theme_suggestions_block_alter()` is not called for block entities.

For embedded nodes it's working fine, I have a `node.html.twig` template inside the entity-embed-container. The problem is only for blocks, where are only field templates, no `block.html.twig`.

# Answer
> 1 votes
I did not understand well the difference between **block** and **block\_content**. Block content don't has its own template what I missed.

Here is an issue about this: https://www.drupal.org/project/drupal/issues/2366687

My solution was to use the block\_content\_template contrib module. So a got my twig file suggestions:

---
Tags: theming, 9
---


# Question
Title: Rewrite url facet by taxonomy term machine name
I have a multi-facet search page, with those 2 facets : **poste** and **type\_de\_contrat** (= internship, open-ended contract...)

It's working fine, but I'd like to rewrite the url, because it looks like this : `?f[0]=poste%3A131&f[1]=type_de_contrat%3A89`, i want to rewrite the taxonomy IDs by the taxonomy machine name.

I've created and activated a ProcessorHandler to achieve this.

```
/**
 *
 * @FacetsUrlProcessor, which can be configured on the Facet source.
 *
 * @FacetsProcessor(
 *   id = "mymodule_processor_handler",
 *   label = @Translation("Gestion 'Type de contrat' preprocess"),
 *   description = @Translation("Permet de preprocess la facette type de contrat."),
 *   stages = {
 *     "pre_query" = 99,
 *     "build" = 99,
 *   },
 *   locked = false
 * )
 */
class TypeContratProcessorHandler  extends ProcessorPluginBase implements BuildProcessorInterface, PreQueryProcessorInterface, ContainerFactoryPluginInterface {

  /**
   * The actual url processor used for handing urls.
   *
   * @var \Drupal\facets\UrlProcessor\UrlProcessorInterface
   */
  protected $processor;

  /** @var \Symfony\Component\HttpFoundation\RequestStack*/
  protected $request;

  /**
   * Constructs a new object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, RequestStack $request) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->request = $request;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('request_stack')
    );
  }

  /**
   * Gets the Processor.
   *
   * @return \Drupal\facets\UrlProcessor\UrlProcessorInterface
   *   The Processor.
   */
  public function getProcessor() {
    return $this->processor;
  }

  /**
   * {@inheritdoc}
   */
  public function preQuery(FacetInterface $facet) {
  }

  /**
   * {@inheritdoc}
   */
  public function build(FacetInterface $facet, array $results) {
    $current_request = $this->request->getCurrentRequest();
    if ($current_request === NULL) {
      return $results;
    }
    $taxo_name = "type_de_contrat";
    $filter_key = 'f';
    $facet_url_alias = $facet->getUrlAlias();
    /** @var \Drupal\facets\Result\Result $facetResult */
    foreach ($results as &$facetResult) {
      $url = $facetResult->getUrl();
      if ((int) $facetResult->getRawValue() == '') {
        $facetResult->setActiveState(TRUE);
        $url->setRouteParameters([$facet_url_alias => '']);
      }
      else {
        // rewrite here.
        $taxo = Term::load($facetResult->getRawValue())->get('machine_name')->value;
        $url->setRouteParameters([$facet_url_alias => $taxo]);
      }

      $query = $url->getOption('query');
      $facet_list = $query[$filter_key];
      foreach ($facet_list as $index => $item) {
        if (strpos($item, $facet_url_alias) !== FALSE) {
          unset($query[$filter_key][$index]);
        }
      }
      if (empty($query[$filter_key])) {
        unset($query[$filter_key]);
      }
      $url->setOptions(['query' => $query]);
      $facetResult->setUrl($url);
    }
    return $results;
  }

}

```

But with this, when selecting the facet type\_de\_contract, it's always the same selected taxonomy machine name (*type\_de\_contrat=internship*), and the facet isn't making any filter anymore...

# Answer
I used the facets pretty paths contrib module for things like this.

It can be configured like this:
> 0 votes

---
Tags: search, 9
---


# Question
Title: How to set up news page view so that news/topic shows news pieces with topic (which is an entity reference field)?
I have a news page set up as a page display, showing nodes of a specific Content Type. /news works as expected.

I now want to improve the view: When someone goes to /news/pancreas or /news/heart, for example, nodes are filtered for that particular topic.

I have an entity reference field (*Groups audience*) whose machine name is *og\_group\_ref*, which allows unlimited categories.

For my display mode, I am outputting that field as an ID (although I'm not sure this is correct). For results without a topic on the view page they look something like the following screenshot (with ID of category shown).

>

However if I add a category to the URL, such as /news/heart, I do not get any results.

I have a contextual filter and a relationship set up from trying to follow a guide elsewhere, but I do not think it is correct and I'm sadly pretty fuzzy on how contextual filters and relationships work. I am not really sure I'm even on the right track.

>

>

>

How can I set up categorization based on an entity reference field?

# Answer
Judging by the name of the "og group" field, the Drupal 7 site probably used Organic Groups and the Drupal 8 site probably uses Group.

These modules have completely different implementations, so it's important to know which one you're working with when you configure your View -- and not to mix the old way with the new way.

It seems likely that the "og group" field contains legacy data from Drupal 7 Organic Groups. (It's common in migrations to create fields to preserve important data from the old site for the historical record, even if it is not used anymore in the new site.)

The OG group reference for "heart" has ID 46, but this is likely just a taxonomy term reference rather than a full OG implementation. (OG for Drupal 9 is currently under heavy development; I would not recommend installing both OG and Group on the same site.)

The "Groups audience" field refers to the new Group implementation, where "Heart" has ID 13366. This is the Group which matters for your Views contextual filter. But your View also has a Relationship with `og_group_ref` so you may be mixing things here.

Your View may not need a Relationship at all, so to simplify debugging I would remove that and concentrate on your contextual filter.

You may find that it's relatively straightforward to set up a contextual filter on Groups Audience, as long as the URL contains the Group number rather than its label. (In other words, try `news/13366` instead of `news/Heart`.)

If you are certain that all Groups will always have a corresponding `og_group_ref`, you could instead opt to use a contextual filter on that taxonomy term reference, as long as the URL contains the taxonomy term ID rather than its label. (In other words, try `news/46` instead of `news/heart`.)

Once you get the contextual filter working, I recommend you post another question to see how you can make this filter work with the word `heart` in the URL segment rather than the number `13366`. It's a separate issue.
> 1 votes

---
Tags: views
---


title: Migrating dependent entities

text:
# Question
Title: Migrating dependent entities
I'm trying to custom-migrate D7 to D8 articles with references to file(images), taxonomy terms, and users(uid). Do i have to migrate the whole group all these entities belong to with

```
drush migrate_import --group=mygroup

```

to keep the references all right?

Or is it somehow possible to run one subsidiary migration and still keep the references, i mean

```
drush migrate_import mymigration

```

?

# Answer
> 2 votes
The --execute-dependencies option will cause all the migrations your "main" migration depends on to run first, so all references are resolved:

```
drush mi --execute-dependencies mymigration

```

Of course, 'mymigration' needs to reference the migrations it depends on in migration\_dependencies:

```
migration_dependencies:
  required:
    - my_file_migration
    - my_user_migration
...

```

# Answer
> 1 votes
I haven't done a D7 to D8 migration, but for a migration to D8 from an sql source, I find it's best to do a "child" migration before its "parent. So do the users, terms, and files before migrating the articles. And then if you roll back, do that in the reverse order: parents before children.

This blog post was helpful to me: http://www.mediacurrent.com/blog/migrating-content-references-drupal-8

This is the way I organize things in my migrations...

In the child migration:

```
process:
  parent_id:
    plugin: migration_lookup
    migration: parent_migration
    source: my_parent_id

```

In the parent migration:

```
process:
# for the label field and any other non-reference fields, create 'stub' values in this manner:
  label_field:
  -
    plugin: get
    source: my_label_field
  -
    plugin: default_value
    default_value: 'Stub Label'
child_items:
  plugin: migration_lookup
  migration: child_migration
  source: my_child_items

```

Note: if some of your parent entities don't have any child items, you can use the skip\_on\_empty process plugin as follows to make sure those parent entities are still migrated properly. (If child items are required for all parent entities, you can omit from the migration any parent entities with missing children by changing the 'method' from 'process' to 'row'.)

```
  child_items:
  -
    plugin: skip_on_empty
    method: process
    source: my_child_items
  -
    plugin: migration_lookup
    migration: child_migration

```

# Answer
> 0 votes
Migrations are automatically processed by their migration\_dependencies:

e.g.

```
id: upgrade_d7_field_instance_widget_settings
[...]
migration_dependencies:
  required:
    - upgrade_d7_field_instance
  optional:
    - upgrade_d7_field
    - upgrade_d7_field_instance

```

So if you're running all migrations (or all from a tag or group), their migration order is calculated based on their migration\_dependencies.

In this example, upgrade\_d7\_field\_instance\_widget\_settings will only run after upgrade\_d7\_field\_instance has been migrated! As upgrade\_d7\_field is a migration\_dependency of upgrade\_d7\_field\_instance the order will be:

1. upgrade\_d7\_field\_instance
2. upgrade\_d7\_field
3. upgrade\_d7\_field\_instance\_widget\_settings

So you should be careful when running single migrations!

If you're for example running upgrade\_d7\_user before upgrade\_d7\_field\_instance, your custom user fields values might not be migrated!

This is quite tricky!

I think this might be interesting for you with more details: https://understanddrupal.com/lessons/introduction-migration-dependencies-drupal/

---
Tags: migrations
---


# Question
Title: How do I properly cache a menu item that varies by user?
We are attempting to show a users first name on a profile menu for authenticated users. We added a lazy builder to the `hook_preprocess_page` hook in our theme given this is highly dynamic content on heavily cached pages.

```
if ($account->isAuthenticated()) {
  $vars['current_user_first_name'] = [
    '#create_placeholder' => true,
    '#lazy_builder' => [
      '\Drupal\ourtheme\OurThemeLazyBuilders::getUserFirstName',
      [$account->id()]
    ]
  ];
}

```

With this callback (inside of a class that implements `RenderCallbackInterface`)

```
public static function getUserFirstName($account_id) {
    $user = User::load($account_id);
    return [
      '#plain_text' => $user->field_first_name->value,
      '#cache' => [
        'max-age' => 0
      ],
    ];
  }

```

However, when two of us (both `administrator` accounts) log in, whoever logs in second will see the other persons first name. We have verified the caching issue by setting a breakpoint in the `hook_preprocess_page` hook and see that the breakpoint never gets hit for the second users request. We tried moving the lazybuilder into it's own block and placing that block in a region of our theme, this didn't seem to make a difference, we saw the same caching behavior.

Interestingly, this only seems to happen when the users have the `administrator` role, we have thousands of other active users who only have `authenticated users` role and we've not heard anything about this issue from them (we would have heard immediately if there was an issue for general users).

Is there a way to debug the caching system in Drupal to know what parts of a page are cached by the dynamic cache and/or page cache?

# Answer
Don't pass the user ID to the lazy builder, arguments get cached. Get the current user ID in the lazy builder:

```
public static function getUserFirstName() {
    $account_id = \Drupal::currentUser()->id();
    $user = User::load($account_id);
    return [
      '#plain_text' => $user->field_first_name->value,
      '#cache' => [
        'max-age' => 0
      ],
    ];
  }

```
> 5 votes

---
Tags: caching
---


# Question
Title: How can I render a specific node as the content for the maintenance page?
Given a nid X, how do I have Drupal render it as the content for the maintenance page?

# Answer
> 3 votes
Use the Twig tweak module and create an overwrite template for `maintenance-page.html.twig`. Then copy & paste stuff from your base theme, but replace `{{ page.content }}` from the base theme with `{{ drupal_entity('node', X) }}`

E.g. for stable 9 theme this would look like

```
<header role="banner">
  {% if logo %}
    <a href="{{ front_page }}" title="{{ 'Home'|t }}" rel="home">
      <img src="{{ logo }}" alt="{{ 'Home'|t }}"/>
    </a>
  {% endif %}

  {% if site_name or site_slogan %}
    {% if site_name %}
      <h1>
        <a href="{{ front_page }}" title="{{ 'Home'|t }}" rel="home">{{ site_name }}</a>
      </h1>
    {% endif %}

    {% if site_slogan %}
      <div>{{ site_slogan }}</div>
    {% endif %}
  {% endif %}
</header>

<main role="main">
  {% if title %}
    <h1>{{ title }}</h1>
  {% endif %}

  {{ page.highlighted }}

  {# disabled {page.content} here #}
  {{ drupal_entity('node', X) }}
</main>

{% if page.sidebar_first %}
  <aside role="complementary">
    {{ page.sidebar_first }}
  </aside>
{% endif %}

{% if page.sidebar_second %}
  <aside role="complementary">
    {{ page.sidebar_second }}
  </aside>
{% endif %}

{% if page.footer %}
  <footer role="contentinfo">
    {{ page.footer }}
  </footer>
{% endif %}

```

# Answer
> 0 votes
In order to customize the Maintenace Page in Drupal 8/9 We need to do following items but not restricted to:

1. Create a Basic Page or Article in Drupal for Maintenance page and keep its node id in handy
2. Update settings.php to include your custom theme machine name in the config value like: $settings\['maintenance\_theme'\] = 'your\_theme\_machine\_name';
3. Copy maintenance-page.html.twig from batrik theme or core/modules/system/templates/maintenance-page.html.twig and keep at your\_theme\_name/templates/system/maintenance-page.html.twig
4. Update your maintenance-page.html.twig as in below snippet to embed the content you have in place from Article/Basic page in 1st step

```
 {#
 /**
  * @file
  * Bartik's theme implementation to display a single Drupal page while offline.
  *
  * All available variables are mirrored in page.html.twig.
  *
  * @see template_preprocess_maintenance_page()
  */
  #}

  <header role="banner">
    {% if logo %}
      <a href="{{ front_page }}" title="{{ 'Home'|t }}" rel="home">
        <img src="{{ logo }}" alt="{{ 'Home'|t }}"/>
      </a>
    {% endif %}
 </header>

 <article{{ attributes }}>
   {% block article_title %}
     <div class="container">
        <div class="row">
          <div class="col-12 col-xs-12">
            <div class="s-inner-content">
              {# disabled {page.content} here #}
              {# render body field from Article or Basic page with specific node id #}
              {{ drupal_field('body', 'node', nid) }}
            </div>
          </div>
        </div>
     </div>
   {% endblock %}

</article>

```

In order to have some static page like maintenance-page--ofline.html.twig in drupal 8/9 as in Drupal 7 when Database is down we need to refer to the ongoing discussion on issues: https://www.drupal.org/project/drupal/issues/2720109

We can also refer existing discussion: Drupal 8 maintenance page theming

---
Tags: maintenance-mode
---


# Question
Title: drush puts my website in a subdirectory named 'web'
I use shared web hosting with Cpanel, LAMP and Composer.

I have installed Drupal with Drush on a registered web domain (example.com).

My website is accessible via `example.com/web/` but I would expect the website to be accessible via `example.com` only. Why is that the case and how to handle that situation?

# Answer
## How to fix this

You need to set the web root for the domain (to `web`). You need to do this on your web server, not in Drupal. If you're on a shared host, something like CPanel will have a setting for the web root.

## Why does Drush install Drupal in the web subdirectory?

Drupal has a lot of support files, **many of which should never be exposed to the public by your webserver**. So, the files that should be exposed get put in the `web` directory, while the other utility files get put in other directories.
> 2 votes

---
Tags: drush, 9, installation
---


# Question
Title: managed_file not initialised after form ajax
I'm having issues with a managed\_form field not beeing initialised after it is introduced via a ajaxcallback in a custom checkout Pane:

```
/**
 * Provides a custom message pane.
 *
 * @CommerceCheckoutPane(
 *   id = "video_greeting",
 *   label = @Translation("Gift Information"),
 *   default_step = "video_greeting",
 * )
 */
class VideoGreetingPane extends CheckoutPaneBase {

 // ...

 public function buildPaneForm(array $pane_form, FormStateInterface $form_state, array &$complete_form) {
    $form_state->set('uploadPath', 'public://orders/' . $this->order->get('order_id')->getString() . '/');

    // ...

    $pane_form['expandable'] = [
      '#prefix' => '<div id="video-greeting-expandable" class="video-greeting__upload pb-3 ' . ($sendsVideoGreeting ? 'show' : 'hidden') . '">',
      '#suffix' => '</div>',
      '#type' => 'container'
    ];

    $pane_form['expandable']['video'] = [
        '#type' => 'inline_template',
        '#template' => "{% include '@vanity/commerce/video-thumbnail.html.twig'  %}",
        '#context' => [
          'video' => $video,
          'order' => $this->order
        ],
      ];

      $class = get_class($this);

      $pane_form['expandable']['remove'] = [
        '#type' => 'button',
        '#value' => $this->t('Remove'),
        '#name' => 'removeButton',
        '#attributes' => [
          'class' => ['btn', 'btn-remove'],
          'type' => 'button'
        ],
        '#ajax' => [
          'callback' => [$class, 'ajaxRemoveVideoCallback'],
          'event' => 'click',
          'wrapper' => 'video-greeting-expandable',
          'method' => 'replace',
          'progress' => [
            'type' => 'throbber',
            'message' => ''
          ]
        ]
      ];

    // ...

 }

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

    $form['video_greeting']['expandable']['video']['#access'] = false;
    $form['video_greeting']['expandable']['remove']['#access'] = false;

    $form['video_greeting']['expandable']['file'] = [
      '#type' => 'managed_file',
      // '#parents' => array_merge($form['video_greeting']['#parents'], ['file']),
      '#required' => false,
      '#upload_location' => $form_state->get('uploadPath'),
      '#upload_validators' => [
        'file_validate_is_video' => [],
        'file_validate_extensions' => ['mp4'],
      ],
      '#description' => t('Please upload a video file.'),
      '#default_value' => null, // don't need
      '#accept' => 'video/mp4',
    ];

    return $form['video_greeting']['expandable'];
  }

  // ...

}

```

The ajax replace works fine, but the js-component of the managed file get's not initialized somehow. It stays like this after the replace:

```
<div id="video-greeting-expandable" class="video-greeting__upload pb-3 show">

  <!-- THEME DEBUG -->
  <!-- THEME HOOK: 'container' -->
  <!-- BEGIN OUTPUT from 'core/modules/system/templates/container.html.twig' -->
  <div data-drupal-selector="edit-patenschaft-video-greeting-expandable" id="edit-patenschaft-video-greeting-expandable--NjypaZO-NI0" class="js-form-wrapper form-wrapper">

    <!-- THEME DEBUG -->
    <!-- THEME HOOK: 'form_element' -->
    <!-- BEGIN OUTPUT from 'themes/custom/vanity/templates/form/form-element.html.twig' -->
    <div class="form-item mb-3 form-item- js-form-item- form-no-label">

      <!-- THEME DEBUG -->
      <!-- THEME HOOK: 'file_managed_file' -->
      <!-- BEGIN OUTPUT from 'themes/custom/vanity/templates/form/file-managed-file.html.twig' -->
      <div class="js-form-managed-file form-managed-file">
        <!-- ---- Nothing gets initialized here! --- -->
      </div>

      <!-- END OUTPUT from 'themes/custom/vanity/templates/form/file-managed-file.html.twig' -->

    </div>

    <!-- END OUTPUT from 'themes/custom/vanity/templates/form/form-element.html.twig' -->

  </div>

  <!-- END OUTPUT from 'core/modules/system/templates/container.html.twig' -->

</div>

```

Any hint would be greatly appreciated.

# Answer
You are creating form elements in the Ajax callback. These will not work, as the Drupal settings are created before the Ajax callback is called, and therefore any elements added in the ajax callback do not have their JS settings sent to the browser, and therefore the managed file ajax is not initialized.

You need to add any form elements, including your managed\_file element, in a conditional in the form definition. This conditional should check if the form has been submitted, and add the form elements accordingly, in the form definition, NOT the ajax callback.
> 3 votes

---
Tags: commerce, ajax, files, 9
---


# Question
Title: No results because of relationships, unless "Bypass content access control" is selected
I have a view that lists faculty members in a table. Everything was working fine until I decided to go into *incognito mode* to view the table. It wasn't rendering anything at all. So I went back and tried a few things:

1. Since it was a view/display issue, I thought it was caused from the permissions. So I changed all the permissions to *access: none* (and a bunch of other combinations). This didn't seem to be the issue.
2. Selecting *Bypass content access control* worked fine, but I don't want to use this because of the security implications.
3. Getting rid of the relationships works, but I need the relationships.

Note that this view works if I am logged in as administrator user; it doesn't work when I am in incognito mode (logged out/anonymous user). So I suspect it is a permission issue (given that "Bypass content access control" worked), but I am not really sure.

I have 6 different pages in this view.

# Answer
> 0 votes
https://www.drupal.org/project/commerce/issues/1276450

The above link solved it for me (#5: Disable SQL Rewriting).

# Answer
> 0 votes
In my case, on Drupal 9, it was a matter of editing the view for the search, specifically the query options.

1. In the edit interface for your view, click the Advanced link to open up the advanced options.
2. Under "Other", click the settings link next to "Query settings".
3. Check "Skip item access checks".
4. Check "Bypass access checks".
5. Click "Apply".
6. Save your view.

This assumes that you have already configured access checks for your content and tested the search to make sure that sensitive information is not included in the results.

---
Tags: views, users
---


# Question
Title: How can I disable a single option of checkboxes?
I am using domain access module in Drupal 8. I want to disable one option/site in domain access settings in node edit page . I am trying to disable through hook\_node\_form\_alter. Following is my array in node form alter

Array (

```
[widget] => Array
    (
        [#title] => Domain Access
        [#description] => stdClass Object
            (
                [__CLASS__] => Drupal\Core\Field\FieldFilteredMarkup
                [string] => Select the affiliate domain(s) for this content
            )

        [#field_parents] => Array
            (
            )

        [#required] => 1
        [#delta] => 0
        [#weight] => 0
        [#element_validate] => Array
            (
                [0] => Array
                    (
                        [0] => Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsButtonsWidget
                        [1] => validateElement
                    )

            )

        [#key_column] => target_id
        [#type] => checkboxes
        [#default_value] => Array
            (
                [0] => site1
                [1] => site3
            )

        [#options] => Array
            (
                [master] => stdClass Object
                    (
                        [__CLASS__] => Drupal\Core\Field\FieldFilteredMarkup
                        [string] => Master
                    )

                [site1] => stdClass Object
                    (
                        [__CLASS__] => Drupal\Core\Field\FieldFilteredMarkup
                        [string] => Site 1
                    )

                [site2] => stdClass Object
                    (
                        [__CLASS__] => Drupal\Core\Field\FieldFilteredMarkup
                        [string] => Site 2
                    )

                [site3] => stdClass Object
                    (
                        [__CLASS__] => Drupal\Core\Field\FieldFilteredMarkup
                        [string] => Site 3
                    )

                [site4] => stdClass Object
                    (
                        [__CLASS__] => Drupal\Core\Field\FieldFilteredMarkup
                        [string] => Site 4
                    )

            )

```

)

# Answer
> 4 votes
You can use the Form Options Attributes module and use the following code in `hook_form_alter()`.

```
$form['field_domain_access']['widget']['#options_attributes']['your_option_key']  = ['disabled' => 'disabled'];

```

# Answer
> 2 votes
A contrib module isn't required.

```
$form['field_domain_access']['your_option_key']['#disabled'] = TRUE;

```

# Answer
> 1 votes
In my case i can't disable checkbox by this way because it is a drupal element and use 'checkboxes' type. Instead of reconstruct the entire element to use 'checkbox' type i add the attribute in the hook\_preprocess because int the preprocess we have checkbox element by element like this :

```
if (
  isset($variables['element']['#type']) &&
  $variables['element']['#type'] === 'checkbox' &&
  $variables['element']['#return_value'] === RoleManagementServiceInterface::GROUP_CONTRIBUTOR_ROLE
) {
   $variables['attributes']['disabled'] = TRUE;
}

```

---
Tags: 8, forms, hooks
---


title: Show book tree from page on down

text:
# Question
Title: Show book tree from page on down
Using Views I've created a block which show the immediate children of the current parent book page. What I really want is a block that shows the total child hierarchy of the current parent book page. My intention is to place these blocks on just certain pages which have no content but are there for content grouping. I'm on Drupal 9 if it matters.

This is the screenshot of the fields in the block view.

>

This is the screenshot showing the first advanced settings of the view.

>

This is the screenshot of the block rendered on one of my book pages.

>

Each of those headings have a hierarchy beneath them. I want to see the expanded tree rather than just the immediate child pages.

Is there a way to modify the view to show all children pages?

# Answer
It's been more than a year, but I'll drop my solution:

You can tweak Drupal's book navigation block (that's displayed under nodes) using`hook_preprocess_book_navigation` to add full tree.

```
use Drupal\book\BookManager;

function MYTHEME_preprocess_book_navigation(&$variables) {

  $book_link = $variables['book_link'];
  $variables['tree'] = ''; //Remove existing tree

  $book_manager = \Drupal::service('book.manager');
  if ($book_link['nid']) {
    $book_tree = $book_manager->bookSubtreeData($book_link); //Get the full tree for the current node
    $book_tree = reset($book_tree)['below']; //Remove current node from tree.
    $variables['tree'] = $book_manager->bookTreeOutput($book_tree); // re-create the tree
  }
}

```

You can tweak the layout of the items with `book-tree.html.twig` and the main block with `book-navigation.html.twig`
> 1 votes

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