# Question
Title: CSS aggregration breaks site - how to troubleshoot?
I have a number of D7 sites that "broke" recently when I applied 7.39 and a few other updates. By "broke" I mean the site's CSS styling completely disappeared. I can easily fix by disabling CSS aggregation, so I know that's the cause.

At first I thought it might be a Omega 3.x problem since all sites initially affected, but then a site based on Bootstrap had the same problem. (The CSS doesn't always break right away).

What steps can I take to troubleshoot to determine the root cause?

Edit - to add more detail based on Clive's questions below:

1. Page source does contain `<link>`'s to aggregated CSS files (5 total)
2. Aggregated CSS files do exist on server
3. Status codes are 304 (4) and 200 (1)
4. Folder permissions seem OK

# Answer
> 9 votes
Some initial things to check:

* Clear the cache (if you're running advagg, clear its cache). You can end up with stale file references sometimes.
* Find out what's happening to the missing CSS:
    + When the styles go missing, does the page source contain a `<link>` to an aggregated CSS file? If not, check for modules/themes implementing `hook_html_head_alter()`, `hook_css_alter()`, or `hook_preprocess_html()`, and see if they're doing anything strange.
    + If the source does contain the `<link>`, what status code is the browser returning for the request? 404? You might have a stale cache issue. Clear all caches including those on any reverse proxy you're running. It might easily be something else, would require more intimate debugging. 500? Check the server logs, that should give you clues as to where things are failing.
    + If it's 200, does the requested file actually contain the styles it's supposed to? If not, you might be looking at a cache issue again, or potentially an issue with build tools (Compass/Gulp/Grunt/etc).
* Switch the theme to a core one. Does it have the same problem? If so, it's probably a module or server setting at fault. If not, it's likely to be a problem with the theme.
* Make sure permissions for your files folder are at the right level - the web server must be able to write to that folder to store the aggregated files. This is less likely to be an issue if the files are being created successfully, but it's worth double-checking you don't have an intermittent file system issue (if it's over NFS for example)

Getting the answers to those questions will help to narrow down the source of the problem, but unfortunately it's difficult to give specific advice as to where you should look in the code, as there are a lot of points problems could occur, and a lot of different modules you could have installed, at varying versions.

# Answer
> 2 votes
I had this happen recently on a Backdrop site and had to really dig around to find the answer. Adding it here in case anyone else runs into this and none of the other answers here solve it.

As @Doomd writes here, using `@import` with Google fonts can cause the aggregation to break, apparently due to semicolons in the URL.

> One thing that broke the css was a google fonts import. It seems the semicolon that separates the different font weights in the google fonts url confuses the aggregator:

> `@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&display=swap");`

> So I changed it to this:

> `@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@400&display=swap");` `@import url("https://fonts.googleapis.com/css2?family=Open+Sans:wght@700&display=swap");`

# Answer
> 1 votes
I am experiencing this problem as well. I'm adding a new answer since I don't have enough reputation to comment on Clive's response.

I don't have a final fix for this, but I have found the following:

* The CSS from my theme (plus the base theme and module CSS) is being aggregated and loaded into the page as I would expect. I can inspect it in Chrome's development tools and confirm that it's there.
* However, only the CSS from the first CSS file in my theme is actually being applied. I'm using Adaptive as a base theme, so this means global.base.css.
* If I copy my CSS overrides into this file, they are applied to the site. This is a fix of sorts, since it now allows me to aggregate the CSS without any problems. It's an imperfect fix since the issue/bug remains.
* The issue relates to core CSS aggregation. Installing Advagg neither helps nor hinders.
* I ran CSS validation on my CSS overrides. I didn't see any showstoppers. However, the fact that the code works fine in the first CSS file listed in my theme's info file but not in the fifth file when aggregation is enabled, suggests it probably isn't a validation issue.

One possibility is that there is a bug in AdaptiveTheme that breaks when D7.39 and/or CTools 1.9 are installed. I haven't ruled that out yet. But I have other sites with this combination that are not affected so I'm disinclined to point the finger at AdaptiveTheme.

I'm now working through the modules installed on this site and a similar site that isn't affected to try and find a module that might be causing the problem.

# Answer
> 0 votes
Problems with aggregated CSS files are very often because of unclosed or mismatched curly brackets in one of the individual files.

When there is an unclosed curly bracket in 1 out of 15 CSS files, the error is limited to that file, and some browsers will assume the closing bracket at the end of the file. The other 14 correct CSS files will apply normally.

When those 15 CSS files are concatenated together through aggregation, that unclosed bracket now contains all of the style rules that appear after it. They will not be evaluated.

You may want to check each individual CSS file. A linter or a good IDE with error highlighting can work wonders.

# Answer
> 0 votes
After inspecting the .htaccess file, I got it working by removing this:

```
<IfModule mod_headers.c>
    # Serve gzip compressed CSS files if they exist and the client accepts gzip.
    RewriteCond %{HTTP:Accept-encoding} gzip
    RewriteCond %{REQUEST_FILENAME}\.gz -s
    RewriteRule ^(.*)\.css $1\.css\.gz [QSA]

    # Serve gzip compressed JS files if they exist and the client accepts gzip.
    RewriteCond %{HTTP:Accept-encoding} gzip
    RewriteCond %{REQUEST_FILENAME}\.gz -s
    RewriteRule ^(.*)\.js $1\.js\.gz [QSA]

    # Serve correct content types, and prevent mod_deflate double gzip.
    RewriteRule \.css\.gz$ - [T=text/css,E=no-gzip:1]
    RewriteRule \.js\.gz$ - [T=text/javascript,E=no-gzip:1]

    <FilesMatch "(\.js\.gz|\.css\.gz)$">
      # Serve correct encoding type.
      Header set Content-Encoding gzip
      # Force proxies to cache gzipped & non-gzipped css/js files separately.
      Header append Vary Accept-Encoding
    </FilesMatch>
  </IfModule>

```

I am still going to dig a bit deeper to find out why, but for the time being, this solves my problem.

I think that the aggregation module also tries to compress files. So by having this in the htaccess file, you are gzipping twice. I THINK. I could be wrong. Either way, this solves it.

# Answer
> 0 votes
I stumbled upon this with D9, trying to add a css resource to a library.

I eventually solved it adding a couple of properties to that css :

```
global-styling:
  css:
    theme:
      css/booswatch_flatly.min.css: { minified: true, preprocess: false}
      ...

```

---
Tags: theming, performance
---


# Question
Title: InvalidArgumentException: Class ... does not exist in custom configuration form
I create configuration form, so that I could dynamically set the API key for my custom weather module.

But when I write in the url address `http://drupalsite/admin/config/services/weather/settings` I get the error:

> InvalidArgumentException: Class "\Drupal\weather\Form\WeatherSettingsForm" does not exist. in Drupal\Core\DependencyInjection\ClassResolver-\>getInstanceFromDefinition() (line 24 of core/lib/Drupal/Core/DependencyInjection/ClassResolver.php).

I checked the Class Name and File name and cleared the caches but the error did not go away. How to fix it?

**weather.routing.yml**

```
weather.weather_page:
  path: '/weather/{city}'
  defaults:
    _controller: '\Drupal\weather\Controller\WeatherPage::getWeather'
  requirements:
     _permission: 'access content'
weather.settings:
  path: '/admin/config/services/weather/settings'
  defaults:
    _form: '\Drupal\weather\Form\WeatherSettingsForm'
    _title: 'Weather Settings form'
  requirements:
    _permission: 'administer site configuration'

```

**WeatherSettingsForm.php**

```
<?php

namespace Drupal\weather\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Configure example settings for this site.
 */
class WeatherSettingsForm extends ConfigFormBase {
  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'weather_admin_settings';
  }

  /**
   * {@inheritdoc}
   */
  protected function getEditableConfigNames() {
    return [
      'weather.settings',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $config = $this->config('weather.settings');

    $form['weather_api_key'] = array(
      '#type' => 'textfield',
      '#title' => $this->t('API Key'),
      '#default_value' => $config->get('weather_api_key'),
    );

    return parent::buildForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $this->configFactory->getEditable('weather.settings')
      ->set('weather_api_key', $form_state->getValue('weather_api_key'))
      ->save();

    parent::submitForm($form, $form_state);
  }
}
?>

```

# Answer
## Solution:

I just needed to restart the **docker4drupal**.

When I wrote the commands:

```
docker-compose stop
docker-compose up -d

```

The error is gone.
> 4 votes

---
Tags: forms, 9
---


# Question
Title: Dynamic Registration Form submission using vanilla Javascript ajax
I want to use the ajax capability of not refreshing the page or rerouting the user to the registration page. Login / Register dialogue modals have been created. I have the login javascript ajax working perfectly using an ajax call to the login api without any configurations or added modules. I want to integrate the registration form in the same way. I would like the registration to:

1. show in a modal - this works.
2. Submit javascript code works with preventDefault
3. response is failing.

Ajax Post is returning '\<' obviously this is returning some html. How do I know how to pass the data in the ajax call and what to expect as a response? My example below:

```
<style>
.scroll {
  //background-color: #fed9ff;
  //width: 600px;
  height: 500px;
  overflow-x: hidden;
  overflow-y: auto;
  //text-align: center;
  //padding: 20px;
}

.close {
  margin: 10px 25px 0px;
}
#log-title {
  margin-left:25px;
}
</style>

<a data-target="#register-modal" data-toggle="modal" class="" id="" href="#register-modal">Register / Create an Account </a>

<div id="overlay_container"></div>

<!--  Register to download button so stays on same page.  -->
<div id="register-modal" class="modal" tabindex="-1" role="dialog" aria-hidden="true">
  <button type="button" class="close" data-dismiss="modal" aria-label="Close">
    <span aria-hidden="true">×</span>
  </button>
  <h3 id="log-title">Please register:</h3>
  <div class="modal-dialog">
    <div class="modal-content scroll">
      <?php
        $register_form = \Drupal::service('entity.form_builder')->getForm(\Drupal\user\Entity\User::create([]), 'register', []);
        // Load the service renderer
        $render = Drupal::service('renderer');
        $rform = $render->renderPlain($register_form);
        echo $rform;
      ?>
    </div> <!-- Register modal content end-->
  </div><!-- Register modal-dialog end -->
</div><!-- Register modal end -->

<script>
  var registerForm = document.getElementById('user-register-form');
  if (registerForm ) {
    // capture registration submit, prevent from submission and use ajax to get response
    registerForm.onsubmit = async (e) => {
      e.preventDefault();
        // callRegCaptcha();
      elms =document.getElementById("user-register-form").elements;
      var url = "https://website/user/register"; //website is a true url

      fetch(url, {
        method: 'POST',
        body: elms
      })
      .then(response=>response.json())
      .then(json => {
        console.log(json);
      });
    }
  }
</script>

```

Everything is working except the response. I cant find anywhere what to expect as a response. Or if Im binding the data of elms correctly. Can anyone help me in this area?

The login required a csrfToken to be passed along with

```
 headers: {
                'Content-Type': 'application/json',
                'X-CSRF-Token': csrfToken
              },

```

and "?\_format=json" appended to the url but for the registration values I am running blindly. Does anyone have any information on what to pass? The response I get is the html page.

Lastly, the Registration has a captcha v2 which outputs the error: "The answer you entered for the CAPTCHA was not correct"

I also looked at this page: https://www.drupal.org/node/2405657

Showing the #Register

```
POST: https://example.com/user/register?_format=json
Content-type: application/json

{
  "name": { "value": "fooBar" },
  "mail": { "value": "foo@bar.com" },
  "pass": { "value": "secretSauce" }
}
200 OK

```

I dont get a json response, it returns the syntax error: unexpected token \< in JSON at position 1.

```
fetch(url, {
            method: 'POST',
            data:  JSON.stringify({
  "name": { "value": "fooBar" },
  "mail": { "value": "foo@bar.com" },
  "pass": { "value": "secretSauce" }
}),

            dataType: "json",
            contentType: "application/json; charset=utf-8",
            success: function(data) {
                console.log(data);
                successmessage = 'Data was succesfully captured';
                $("#overlay_container").text(successmessage);
            },
            error: function(data) {
                console.log(data);
                successmessage = 'Error';
                $("#overlay_container").text(successmessage);
            }
        })
        .then(response=>response.json())
        .then(json=> {
            console.log(json);
        }).catch(function(err) {
                        console.log(err);      // shows the above exception
                 });

```

None of the success: or error is responding, just the catch

Further more, when the \_format=json to the url, the following error is reported:

```
{message: 'Not acceptable format: json'}
message: "Not acceptable format: json"
[[Prototype]]: Object

```

Next, I have tried to follow this posts response by @Fons Vandamme of installing Rest UI and configuring the user registration

user registration with rest

```
message: "No user account data for registration received."
[[Prototype]]: Object

```

Next: under admin extend, changed the authentication from cookies to basic authentication by installing the HTTP basic authentication, navigating to the rest UI configuration for the User registration /user/register: POST and the new error is a 400 Bad Request.

# Answer
> 1 votes
To get this to work, These were the steps taken to get it functional. As per many comments, Follow this links instructions: https://areatype.com/blog/register-user-drupal-8-rest-api

1. Enable RESTful Web Services, HAL, REST UI, Serialization
2. Configure Rest UI click 'configure' under extend Rest UI. Enable the 'User registration' resource with the following settings:

---

```
       a. path -> /user/register: POST
       b. methods: POST
       c. formats: hal_json, json
       d. authentication: cookie  "**NOTE**: this maybe avoids credentials for new users..."

```
3. Account settings: Under Configuration -\> Account settings "Who can register accounts?" -\> visitor disable "Require email verification when a visitor creates an account"
4. RESTful Web Services -\> Extend -\>RESTful Web Services -\> permissions "Access POST on User registration resource" Grant Anonymous user checkbox.
5. Get Postman for chrome and set it up as such: POST -\> url endpoint -\> http://{website-name-pointer}/user/register?\_format=hal\_json Authorization: none Headers: Content-Type:application/json x-csrf-token:OGVi9xj9vemD3BItXOWf4-3ml2maqy-2kk0gkjIRuHk \**Get x-csrf-token token through new builder get call \** \** http://{website}/session/token \** it outputs a csrf token in return body.

should look like this:

```
header: X-CSRF-Token and Content-Type
post url: http://{website-name-pointer}/user/register?_format=hal_json
body:
{
"name":[{"value":"test3"}],
"mail":[{"value":"test+3@test.com"}],
"pass":[{"value":"test"}]
}

```

This should return a 200 ok status along WITH the newly registered users uid uuid etc content. as a response just as it would if the registration page were submitted.

**NOTE** if it is returning the html page "create/register user" in the response body, or other values, it is the settings in the rest ui configuration or the vistor configuration most likely.

If you are receiving other less identifyable status, it is all incorrect. If you are receiving the 500 error it is likely the authentication problem and switch from either cookie to basic authorization or double check the UI settings for authenticators. Number 2 and 3 seemed to be the area of trial and error.

It seems troubleshooting is more difficult than it should be, and it took 3 days of searching the internet for answers and reading a lot of the code change log.

I put this out there to help anyone with similar difficulties getting the process to work effectively.

---
Tags: ajax
---


# Question
Title: Disable an option for the select form field
How do I disable an option in the select form field?

```
$form['feed'] = array(
  '#type' => 'select',
  '#title' => t('Display of XML feed items'),
  '#options' => array(
    'title' => t('Titles only'),
    'teaser' => t('Titles plus teaser'),
    'fulltext' => t('Full text'),
  ),
  '#description' => t('Global setting for the length of XML feed items that are output by default.'),
);

```

How can I disable, for example, the "Title only" option?

# Answer
Disabling an option may be tricky to achieve (Using form\_alter to disable ONE option of a select field) so I'll recommend you to look at optgroups as an alternative. The Drupal form API documentation doesn't explain it but the API allows nested array for the options, have a look at form\_select\_options() and the `<optgroup>` part.
You can write this code:

```
$form['feed'] = array(
    '#type' => 'select',
    '#title' => t('Display of XML feed items'),
    '#options' => array(
        'Titles only' => array(,
          'teaser' => t('Titles plus teaser'),
          'fulltext' => t('Full text'),
        ),
        'Titles only 2' => array(,
          'teaser2' => t('Titles plus teaser 2'),
          'fulltext2' => t('Full text 2'),
        ),
    ),
    '#description' => t('Global setting for the length of XML feed items that are output by default.'),
);

```

Have a look at Drupal 6 forms and optgroup arrays.

**Edit**: to clarify this is an alternative and not a direct answer.
> 6 votes

# Answer
The only way to disable one of the options for a "select" form field is to override the theme\_select() function implementing hook\_theme\_registry\_alter().

`theme_select()` executes the following code:

```
function theme_select($variables) {
  $element = $variables['element'];
  element_set_attributes($element, array('id', 'name', 'size'));
  _form_set_class($element, array('form-select'));

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

```

The function that you implement should invoke your own function instead of form\_select\_options().

As `theme_select()` is called for each select field used in any Drupal form, I would rather consider implementing hook\_form\_alter() to remove the option from the form field you want.
> 6 votes

# Answer
I got mine working with the following line

```
unset($form['field_name']['und']['#options'][1]);

```

where 1 is the index of the item which you don't want to be displayed.
> 4 votes

# Answer
I don't know and haven't been able to find any way to *disable* an individual option. It does look like they are trying to get something like this into Drupal. Maybe some alternatives, could what you want be done with css?:

```
$form['feed']['#attributes'] = array('class' => array('options-styles-class'));

```

Or, if you don't want the values to be shown at all you can unset them

```
unset($form['feed']['#options']['title']);

```
> 3 votes

# Answer
**Convert the one single item you want to disable into an empty `<optgroup>`.**

**Pros:**

* This can be done in a `hook_form_alter` or directly when building your custom form, there is no need to implement a `theme_select` function in your theme.

**Cons:**

* There's no way to represent the `value='title'` attribute associated with the original `<option>` in the resulting DOM.
* YMMV if you're trying to disable an option that already pertains to an optgroup. Nested optgroups might indeed work, but this is untested and unconfirmed.

**Implementation:**

Optgroups in Drupal are denoted inside the `#options` array as any `key => value` pairs where the value is itself an array.

So from the example in the OP we would **move the value of `t('Titles only')` to become the `key` and then make the value be an empty array.**

```
$form['feed'] = array(
  '#type' => 'select',
  '#title' => t('Display of XML feed items'),
  '#options' => array(
    t('Titles only') => array(), // This one becomes disabled as an empty optgroup
    'teaser' => t('Titles plus teaser'),
    'fulltext' => t('Full text'),
  ),
  '#description' => t('Global setting for the length of XML feed items that are output by default.'),
);

```

The resulting HTML will look something like this:

```
<form>
  <div>
    <label>Display of XML feed items</label>
    <select>
      <optgroup>Titles only</optgroup>
      <option value="teaser">Titles plus teaser</option>
      <option value="fulltext">Full text</option>
    </select>
  </div>
</form>

```
> 1 votes

# Answer
For disabling the whole field, use

```
$form['field_name']['#disabled']= TRUE;

```

For disabling an option in the select field, use

```
unset($form['field_name']['und']['#options'][1]);

```

where:

*\['field\_name'\]* is the name of the your field

*\[1\]* is the index of the option in the list
> 0 votes

# Answer
For drupal 8 or 9 you could take a look to the anwser on this page https://drupal.stackexchange.com/a/207505/89554.

You have to install the module https://www.drupal.org/project/form\_options\_attributes

## Usage

To add attributes to a form element's options, add an **#options\_attributes** key to the form element definition. The **#options\_attributes** value should be an array with keys that match the keys in the **#options** value array. The values in the **#options\_attributes** array should be formatted like the main **#attributes** array

## Exemple based on the question

Set the form field like this:

```
$form['states'] = [
  '#type' => 'select',
  '#title' => t('Display of XML feed items'),
  '#options' => [
    'title' => t('Titles only'),
    'teaser' => t('Titles plus teaser'),
    'fulltext' => t('Full text'),
  ],
  '#options_attributes' => [
    'title' => ['disabled' => 'disabled'],
  ],
  '#description' => t('Global setting for the length of XML feed items that are output by default.'),
];

```

In our exemple pay attention on **#options\_attributes** array where I set the attribute **disabled**
> 0 votes

---
Tags: 7, forms
---


# Question
Title: Filter views by field value equals another field of curent node
D9.3. All fields are not referenced, they are just simple integers. All data was pulled from a huge external API and it was not possible to create all references.

Just for ease of understanding, imagine a book database website with books and characters. But each character is presented in one book only.

So, book node has `field_book_id`, which is numeric, unique, but not NID. Also it has a multiple `field_character_ids` with a list of ids of all characters in this book.

A character node has its own `field_character_id` (matching with `field_character_ids` from book node). And also `field_my_book_id`, which equals to book id field.

**The goal is to create a View, which will show the current book's characters in a list.**

I'm using `Views Contextual Filter Default Entity Field Values` module which allows to pull fields values from the current node, for example.

But in Views Filter Criteria I can't match the selected field with the value from the Contextual Filter. It has only pre-defined operators, such as *is equal to, is less than, is greater than*, etc. And I can't select something like "Match value from contextual filter". I tried to use twig and replacement patterns there without any luck.

It would be a very simple database query, but is it possible to get it working in Views?

# Answer
Ok, it was rather simple.

In contextual filter add the field you want to target.

Then: When the filter value is NOT available \> Provide default value \> Field value from current entity \> under Entity Field select field which will filter the view results.
> 0 votes

---
Tags: views, 9
---


# Question
Title: EntityQuery condition only if field exists
How to apply a condition only if a field exists?

```
$query = \Drupal::entityQuery('node')
  ->condition('type', 'videos')
  ->condition('field_tags', 39, '=')
  ->condition('status', 1)
  ->condition('field_date_start', $now->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), '<=')
  ->condition('field_date_end', $now->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), '>=')
  ->execute();

```

I want to get nodes that meet the condition about `field_date_end` but also those, that do not have a value for `field_date_end`.

Thanks in advance !

# Answer
> 2 votes
Something like this:

```
$query = \Drupal::entityQuery('node');
$group = $query
  ->orConditionGroup()
  ->condition('field_date_end', $now->format(DateTimeItemInterface::DATETIME_STORAGE_FORMAT), '<=')
  ->notExists('field_date_end');
$results = $query
  ->condition('type', 'videos')
  ->condition('field_tags', 39, '=')
  ->condition('status', 1)
  ->condition($group)
  ->execute();

```

---
Tags: 8, entities
---


# Question
Title: Conditional subelement within custom composite webform element
I have a webform that has a custom composite element; let's name it composite\_name.

Within that custom composite, I have element\_a, element\_b, and element\_c.

Is it possible to make element\_c visible only when a value is entered in either element\_a or element\_b, by editing the composite element in the Webform UI?

I tried putting this in the custom properties for element\_c, but it does not work:

```
states:
  visible:
    - ':input[name=["composite_name"]["element_a"]]':
        filled: true
    - or
    - ':input[name=["composite_name"]["element_b"]]':
        filled: true

```

I also tried a few variations on that, with no success. I don't know whether I just have some punctuation out of place or something.

It looks like I could make the condition happen using a custom module (following the webform\_example\_composite module's code), but I'm hoping to configure it in the UI.

# Answer
Conditions need to be set per row.

The webform\_example\_composite.module, included w/ Webform, shows how to do this via \Drupal\webform\_example\_composite\Element\WebformExampleComposite
> 0 votes

---
Tags: webforms
---


title: Multisite same host different basepaths

text:
# Question
Title: Multisite same host different basepaths
I have a site for the virtual host `example.com`, the base directory for the drupal application is `example.com/site1`. I'd like to setup a multisite but have the sites only differ by the base path, not the host name. So the new site will be reached through `example.com/site2`, but it will use the code base in `example.com/site1`.

I've tried creating a symbolic link https://www.drupal.org/docs/7/multisite-drupal/multisite-mapping-with-drupal#multisite-drupal-by-subdomains-and-url-path `ln -s site1 site2` but that gives a 404 when accessing `example.com/site2`

I've also tried setting up a multisite using this https://www.drupal.org/docs/multisite-drupal/set-up-a-multisite and an `AliasMatch` in the `httpd.conf` but this seems to want the sites to have different hostnames rather than different paths. I also get a 404 in this setup.

Is it possible to set up a multisite with the sites only differing by the basepath? I'm using Drupal 9.

# Answer
> 1 votes
I'm working on a site that works like that now. I didn't set it up, but it's done as follows.

Sites:

* example.com/eu
* example.com/us
* example.com/global

The webroot is at \[PROJECT\]/web.

The following symlinks were created:

* \[PROJECT\]/web/eu =\> \[PROJECT\_WEB\]
* \[PROJECT\]/web/us =\> \[PROJECT\_WEB\]
* \[PROJECT\]/web/global =\> \[PROJECT\_WEB\]

So as you can see, three symlinks were created from subfolders of the webroot, to the webroot. Then the the domain was set to point at the webroot. By doing this, when accessing for example example.com/eu, the server looks for the domain at \[project\]/web, then for the subfolder /eu, which is a symlink to the webroot, so Drupal sees it as a Drupal installation.

---
Tags: multi-sites
---


# Question
Title: How do I get the full URL of the current page?
I need to get the full URL of the currently opened page. I use the following code, but it returns `http://localhost/mysite/page_name`.

```
$path = isset($_GET['q']) ? $_GET['q'] : '<front>';
$link = url($path, array('absolute' => TRUE));

```

It's not enough for my code to complete; I want to get the values that are passed with the URL as `http://localhost/mysite/page_name/value1=value&value2=value`.

How can I do that?

# Answer
Have you tried using request\_uri()?

```
$_SERVER['HTTP_HOST'] . request_uri();

```

It should do the trick. I haven't tried it myself, and I may be off a bit, but I suggest you give a try. From JavaScript, you could use the `window.location.href` variable.
> 34 votes

# Answer
Here's how to get the absolute URL for the current page, using the Drupal API:

```
$current_url = url(current_path(), array('absolute' => TRUE));

```

If you need the extra (non-q) querystring parameters as well, you can use:

```
$current_url = url(current_path(), array(
  'absolute' => TRUE,
  'query' => drupal_get_query_parameters(),
));

```
> 32 votes

# Answer
You can use the following code.

```
global $base_root;
$current_url = $base_root . request_uri();
echo $current_url;

```
> 8 votes

# Answer
Try $base\_url variable, provides Drupal installation URL without "/" and current\_path() it returns path of current page being viewed.

```
global $base_url;
$current_path = $base_url . '/' . current_path();

```
> 3 votes

# Answer
The question is pretty old but chiming in for people that might get there for a more recent version of Drupal.

You can get the current full-path for a page with:

```
$path = \Drupal::service('path.current')->getPath();
$queryParams = \Drupal::request()->query->all();

$path . "?" . http_build_query($queryParams);

```

Really handy for dynamically changing the value of certain query parameters like a page for example.
> 3 votes

# Answer
I think the best way to do that is using url() API like this

```
url('your/drupal/path', array('absolute' => TRUE));

```
> 1 votes

---
Tags: 7, uri
---


# Question
Title: How to delete a node or a list of nodes with Drush?
I discovered the Delete all module which gives you the ability to delete all the nodes of a given content type. However, with this module you can't delete a single node or a list of nodes.

In the question "Can I delete nodes of a given content type with Drush?" I found 2 answers talking about the command `drush node_delete <nid>` but I can't find this command.

I found in a discussion about node\_delete() some code using eval to accomplish this task, but it is using eval:

```
drush php-eval "global \$user; \$user = user_load(1); node_delete(nid);"

```

In case that there doesn't exist a functionality implemented to accomplish this, what is the better way to implement this functionality: in the Drush module or create a new module?

# Answer
> 6 votes
If you use the Drush Entity module, then you may run `drush entity-delete node 123` to delete nid 123 from your site.

**EDIT:** If somebody need to use the `drush entity-delete` command, should use the dev version of the module: https://www.drupal.org/project/drush\_entity/releases/7.x-5.x-dev

# Answer
> 7 votes
Finally I create my own module named `drush_delete`

Inside the `drush_delete.drush.inc` file put this code:

```
<?php
/**
 * @file
 * The Drush Delete drush commands.
 */

/**
* Implements hook_drush_command().
*/
function drush_delete_drush_command() {
  $items['node-delete'] = array(
    'description' => dt("Delete nodes."),
    'aliases' => array('nd'),
    'arguments' => array(
      'nids' => dt('The nids of the nodes to delete'),
    ),
    'examples' => array(
      'drush node-delete 1' => dt('Delete the node with nid = 1.'),
      'drush node-delete 1 2 3' => dt('Delete the nodes with nid = 1, 2 and 3.'),

    ),
  );
  return $items;
}

/**
 * Callback for the node-delete command
 */
function drush_drush_delete_node_delete() {
  $nids = func_get_args();
  $nids = array_filter($nids, 'is_numeric');
  $nids = array_map('intval', $nids);
  $nids = array_unique($nids);
  $nids = array_values($nids);
  $cant = count($nids);

  if ($cant > 0) {
    node_delete_multiple($nids);

    drush_print(dt("Deleted nodes:"));
    drush_print(implode(' ', $nids));
  }
  else {
    drush_set_error('DRUSH_ERROR_CODE', dt("You must enter at least one nid"));
  }
}

```

Install the module, run `drush cc drush` to clear the drush cache and use the command like this:

To delete a node use:

```
drush node-delete 1
drush nd 1

```

To delete multiple nodes use:

```
drush node-delete 1 2 3
drush nd 1 2 3

```

You can found the command in this module:

https://github.com/adrian-cid/drush\_commands

# Answer
> 7 votes
IMHO the easiest way is with php-eval:

```
drush php-eval "node_delete_multiple(array(NODE_ID));"

```

...

```
drush php-eval "node_delete_multiple(array(34));"     // for node/34

drush php-eval "node_delete_multiple(array(34, 35));" // for node ids 34 and 35

```

# Answer
> 1 votes
If you want to delete all nodes use the range() function as

> `drush php-eval "node_delete_multiple(range(1,3000));"`

---
Tags: 7, nodes, drush
---


# Question
Title: How to filter idlist in command line when importing data via migration
I know I'm really missing something here. I have a custom migration source plugin that requires a query() to be returned.

If I pass an `--idlist=123` parameter with the import this query still runs on all of the nodes as there is no way to limit it dynamically. What am I missing?

The migration is supposed to query the legacy D7 db for content types (event) and then I need to update each result's fields in my prepareRow(). This works except that the query is always returning all events. I think I'm misunderstanding the need/purpose for the query() function.

# Answer
> 2 votes
This is a known issue during migration. There are open issues in Drupal.org but they are not closed yet. But for now we have a work around to solve this issue.

```
public function query() {
    // Hack for getting idlist to filter in command line
    $idlist = NULL;
    foreach ($_SERVER['argv'] as $arg) {
      if (strpos($arg, '--idlist') === 0) {
        list(, $idlist) = explode('=', $arg);
        $idlist = explode(',', $idlist);
        break;
      }
    }
$query = $this->select('node', 'n')
  ->fields('n')
  ->orderBy('nid', 'ASC');

if ($idlist) {
  $query->condition('n.nid', $idlist, 'IN');
}

return $query;
}

```

Then use it like this:

```
drush migrate:import example_node_articles --update --idlist=1234
 [notice] Processed 1 item (0 created, 1 updated, 0 failed, 0 ignored) - done with 'example_node_articles'

```

Source : https://www.drupal.org/project/migrate\_tools/issues/3107400#comment-13428024

---
Tags: migrations
---


# Question
Title: How do I remove the "Save draft" button from every page of a multi-step form?
I have a multi-step webform and I want to add a save draft button however it needs to be added only to the last preview page and not all step pages.

I have used settings within submission to activate saving draft however the button appears on each page. Any way to hide, without changing code but just through configuration/settings?

# Answer
> 1 votes
Create a new module and then you can check the `$form_state` page to conditionally enable to disable buttons.

```
function submission_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'webform_submission_xyz') {
    $form['actions']['button or field']['#access'] = $form_state->get('current_page' )== 'abcd';
}

```

---
Tags: webforms
---


# Question
Title: Best Practice: Remove UUID or default_config_hash from Custom Content Type definitions?
When I'm exporting the custom content type definitions using the UI, many of the resulting YML files hold a `uuid` and `default_config_hash`, like:

```
uuid: b69d8e54-076c-4a15-a396-19f49369fa68
...
_core:
  default_config_hash: 3aSvUp4PtrivflrkaLdNRL1USkZLsS7NdQroSiRX9mA
...

```

Now, when I'm using this as a basis for my custom module, is it recommended to remove those lines?

# Answer
> 4 votes
Yes, it is best practice to remove both.

Drupal Console provides these options:

```
drupal config:export:single \
  --name=config.settings.name \
  --remove-uuid \
  --remove-config-hash

```

Or export an entire set of YAML files of a content type directly to the modules install folder:

```
drupal config:export:content:type page \
  --module="demo" \
  --optional-config \
  --remove-uuid \
  --remove-config-hash

```

See https://drupalconsole.com/docs/en/commands/config-export-content-type

# Answer
> 7 votes
To manually remove all of the UUID and default\_config\_hash lines from your config files so that they don't conflict with those of a new site this can be done quite easily on the command line like so: (Linux)

```
find /path/to/PROFILE_NAME/config/install/ -type f -exec sed -i -e '/^uuid: /d' {} \;
find /path/to/PROFILE_NAME/config/install/ -type f -exec sed -i -e '/_core:/,+1d' {} \;

```

Here's the command for Mac OSX:

```
find /path/to/PROFILE_NAME/config/install/ -type f -exec sed -i '' '/^uuid: /d' {} \;
find /path/to/PROFILE_NAME/config/install/ -type f -exec sed -i '' '/_core:/{N;d;}' {} \;

```

See this https://www.drupal.org/docs/distributions/creating-distributions/how-to-write-a-drupal-installation-profile#config

---
Tags: 8
---


title: How do I run the drush tests in docker?

text:
# Question
Title: How do I run the drush tests in docker?
I'm trying to improve drush, and the drush contributing guidelines state:

> Drush's own tests may be run within provided Docker containers (see docker-compose.yml):
>
> Start containers: docker-compose up -d

So I forked Drush on Github, cloned the repo locally, and then, from the repo root, ran `docker-composer up -d`. This gives an error:

> ERROR: Can't find a suitable configuration file in this directory or any parent. Are you in the right directory?

So then I tried to find the right directory by searching for a `docker-compose.yml`, but I can't find it anywhere. I searched the Drush repo on GitHub as well but I couldn't find it there, either.

How do I launch `docker-compose` to run the drush tests?

# Answer
We've started using DDEV instead of direct docker-compose. Docs now updated. Thanks for the report
> 2 votes

---
Tags: drush
---


# Question
Title: How to track recently viewed nodes using JavaScript on a completely cached website?
I want to make a block of recently viewed nodes on a website which is completely cached using Boost module (it saves a static HTML page for every request on the website). I don't want to disable Boost and recache a page every time this block updated, instead, I wondering if it possible to use JavaScript here. Is there any way I can do this?

# Answer
> 0 votes
Not a module, but still better than nothing. Note that some parts of the script are theme-aware.

**This goes to the bottom of node--\[type\].tpl.php:**

```
<?php if ($page): ?>
  <script type="text/javascript">updateRecentlyVisited();</script>
<?php endif; ?>

```

**This to the new block (block's text format shouldn't change tags):**

```
<script type="text/javascript">
var thisBlock = document.getElementById('[PUT BLOCK ID HERE]');
if (currentlyStored) {
  var recentlyVisited = '<ul">';
  for (var i = 0; i < currentlyStored.length; i++) {
    recentlyVisited += '<li><a href="' + currentlyStored[i][0] + '">' + currentlyStored[i][1] + '</a></li>';
  }
  recentlyVisited += '</ul>';

  thisBlock.innerHTML = recentlyVisited;
}
else
   thisBlock.remove();
</script>

```

**And the script.js to attach in theme.info**

```
var currentlyStored = JSON.parse(localStorage.getItem('recentlyVisited'));

function updateRecentlyVisited() {
    var maxLinks = 20;
    var currentPage = new Array (document.URL, document.getElementsByClassName('node-title').item(0).textContent);

    if (currentlyStored)
        for (var i = 0; i < currentlyStored.length; i++) {
            if (currentlyStored[i][0] == currentPage[0]) {
                currentlyStored.splice([i],1);
                break;
            }
        }
    else
        currentlyStored = new Array();
    currentlyStored.unshift(currentPage);
    if (currentlyStored.length > maxLinks)
        currentlyStored.pop();

    localStorage.setItem('recentlyVisited', JSON.stringify(currentlyStored));
}

```

---
Tags: 7, javascript, blocks, caching
---


# Question
Title: Alter "Action processing results" message for a specific action
I have a view based on view bulk operations. this is a comment based view and performs the below actions:

```
1. Publish comment 2. Unpublish comment

```

When one of these actions are selected to be executed on a set of records, I get to see a success message like below:

```
Action processing results: Unpublish Comment (1).

```

I would like to alter the success message as:

```
The selected comment(s) have been unpublished successfully

```

I am using VBO 4.0.0 which has action processing message update commit in it. No clue about how this can be implemented for a specific actions. any help?

UPDATE:

Below is my trial so far:

```
function mymod_batch_alter(&$batch) {
  foreach ($batch['sets'] as $key => $set) {
      $batch['sets'][$key]['finished'] = 'mymod_views_bulk_operations_execute_finished';
    }
  }

/**
 * Implements hook_views_bulk_operations_execute_finish().
 */
function mymod_views_bulk_operations_execute_finished($success, array $results, array $operations) {
    if ($success) {
      $operations = $results['operations'];
      if($operations == "Approve Comment"){
        $message = \Drupal::messenger()->addMessage('Success! Approved');
      }
      elseif($operations == "Disapprove Comment"){
        $message = \Drupal::messenger()->addMessage('Success! Disapproved');
      }
    }
    else {
      $message = \Drupal::messenger()->addWarning('Failure message...');
    }
    return NULL;
  }

```

This code is working well, but just one issue. everytime, even for the "disapprove comment" action, I get to see "Success! Approved" message. Control is going into wrong if-condition. Can someone point the mistake out?

# Answer
Alright, the below code works:

```
function mymod_batch_alter(&$batch) {
  foreach ($batch['sets'] as $key => $set) {
      $batch['sets'][$key]['finished'] = 'mymod_views_bulk_operations_execute_finished';
    }
  }

/**
 * Implements hook_views_bulk_operations_execute_finish().
 */
function mymod_views_bulk_operations_execute_finished($success, array $results, array $operations) {
    if ($success) {
      $operations = $results['operations'];
      if($operations[0] == "Approve Comment"){
        $message = \Drupal::messenger()->addMessage('Success! Approved');
      }
      elseif($operations[0] == "Disapprove Comment"){
        $message = \Drupal::messenger()->addMessage('Success! Disapproved');
      }
    }
    else {
      $message = \Drupal::messenger()->addWarning('Failure message...');
    }
    return NULL;
  }

```
> 0 votes

---
Tags: views, hooks
---


# Question
Title: Warning: Invalid argument supplied for foreach() ViewsData.php
On my drupal 9 website I get a warning when running the Cache Clear Command. I get these two messages. I have no clue where to start with finding the problem. Hope someone understands these messages and can point me in te right direction.

```
Warning: Invalid argument supplied for foreach() in Drupal\views\ViewsData->getData() (line 239 of core/modules/views/src/ViewsData.php).
Drupal\views\ViewsData->getData() (Line: 154)
Drupal\views\ViewsData->get('block_content') (Line: 91)
Drupal\views\Plugin\Derivative\ViewsEntityRow->getDerivativeDefinitions(Array) (Line: 101)
Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator->getDerivatives(Array) (Line: 87)
Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator->getDefinitions() (Line: 285)
Drupal\Core\Plugin\DefaultPluginManager->findDefinitions() (Line: 175)
Drupal\Core\Plugin\DefaultPluginManager->getDefinitions() (Line: 22)
Drupal\Core\Plugin\DefaultPluginManager->getDefinition('data_field') (Line: 16)
Drupal\Core\Plugin\Factory\ContainerFactory->createInstance('data_field', Array) (Line: 83)
Drupal\Component\Plugin\PluginManagerBase->createInstance('data_field') (Line: 817)
Drupal\views\Plugin\views\display\DisplayPluginBase->getPlugin('row') (Line: 122)
Drupal\views\Plugin\views\style\StylePluginBase->init(Object, Object, Array) (Line: 820)
Drupal\views\Plugin\views\display\DisplayPluginBase->getPlugin('style') (Line: 346)
Drupal\rest\Plugin\views\display\RestExport->collectRoutes(Object) (Line: 120)
Drupal\views\EventSubscriber\RouteSubscriber->routes()
call_user_func(Array) (Line: 146)
Drupal\Core\Routing\RouteBuilder->rebuild() (Line: 83)
Drupal\Core\ProxyClass\Routing\RouteBuilder->rebuild() (Line: 382)
Drupal\Core\Extension\ModuleInstaller->install(Array, 1) (Line: 83)
Drupal\Core\ProxyClass\Extension\ModuleInstaller->install(Array) (Line: 476)
Drupal\system\Form\ModulesListForm->submitForm(Array, Object)
call_user_func_array(Array, Array) (Line: 114)
Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 52)
Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 592)
Drupal\Core\Form\FormBuilder->processForm('system_modules', Array, Object) (Line: 320)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 564)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 158)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 80)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

Warning: Invalid argument supplied for foreach() in Drupal\Component\Utility\NestedArray::mergeDeepArray() (line 327 of core/lib/Drupal/Component/Utility/NestedArray.php).
Drupal\Component\Utility\NestedArray::mergeDeepArray(Array) (Line: 295)
Drupal\Component\Utility\NestedArray::mergeDeep(Array, NULL) (Line: 244)
Drupal\views\ViewsData->getData() (Line: 154)
Drupal\views\ViewsData->get('block_content') (Line: 91)
Drupal\views\Plugin\Derivative\ViewsEntityRow->getDerivativeDefinitions(Array) (Line: 101)
Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator->getDerivatives(Array) (Line: 87)
Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator->getDefinitions() (Line: 285)
Drupal\Core\Plugin\DefaultPluginManager->findDefinitions() (Line: 175)
Drupal\Core\Plugin\DefaultPluginManager->getDefinitions() (Line: 22)
Drupal\Core\Plugin\DefaultPluginManager->getDefinition('data_field') (Line: 16)
Drupal\Core\Plugin\Factory\ContainerFactory->createInstance('data_field', Array) (Line: 83)
Drupal\Component\Plugin\PluginManagerBase->createInstance('data_field') (Line: 817)
Drupal\views\Plugin\views\display\DisplayPluginBase->getPlugin('row') (Line: 122)
Drupal\views\Plugin\views\style\StylePluginBase->init(Object, Object, Array) (Line: 820)
Drupal\views\Plugin\views\display\DisplayPluginBase->getPlugin('style') (Line: 346)
Drupal\rest\Plugin\views\display\RestExport->collectRoutes(Object) (Line: 120)
Drupal\views\EventSubscriber\RouteSubscriber->routes()
call_user_func(Array) (Line: 146)
Drupal\Core\Routing\RouteBuilder->rebuild() (Line: 83)
Drupal\Core\ProxyClass\Routing\RouteBuilder->rebuild() (Line: 382)
Drupal\Core\Extension\ModuleInstaller->install(Array, 1) (Line: 83)
Drupal\Core\ProxyClass\Extension\ModuleInstaller->install(Array) (Line: 476)
Drupal\system\Form\ModulesListForm->submitForm(Array, Object)
call_user_func_array(Array, Array) (Line: 114)
Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 52)
Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 592)
Drupal\Core\Form\FormBuilder->processForm('system_modules', Array, Object) (Line: 320)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 564)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 158)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 80)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

```

# Answer
Thanks to 4k4s comment:

> "The cache clear invalidates all views data so that every hook\_views\_data is invoked. One of them, probably in a custom module, is not returning a proper views data array."

I searched my project for `_views_data` and found out I still had the Draggableviews module installed. I remember having problems with this module before and therefore don't use it anymore, it was quite easy to uninstall and remove from my project. Doing this was the solution for my problem.
> 0 votes

---
Tags: 9
---


# Question
Title: Set Default Value of User Entity Reference to logged in user
I have a Drupal 8 installation that has a user reference field and I would like the currently logged in user to be the default value for the field. I believe in Drupal 7 I would've used the \[current-user:name\] Token for this. That functionality didn't seem to show up when I installed Token for D8.

# Answer
You'll probably want to make a utility module and use `hook_form_alter()` (with a switch statement on the `$form_id` you're targeting if you're targeting multiple forms) or `hook_form_FORM_ID_alter()`. Then the following should do the job:

```
use Drupal\user\Entity\User;
use Drupal\Core\Form\FormStateInterface;

function mymodule_hook_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == "TARGET_FORM_ID") {
    $current_user = \Drupal::currentUser();
    $form['field_user']['widget'][0]['target_id']['#default_value'] = User::load($current_user->id());;
  }
}

```
> 1 votes

---
Tags: entities, users, tokens
---


# Question
Title: AccessDeniedHttpException on a route with _access: TRUE
In my custom module I have a few "publication" routes that do not need any kind of authentication. Months ago I learnt that I could achieve this with the following requirements in routing.yml:

```
my_module.myroute:
  [...]
  requirements:
    _access: 'TRUE'

```

This works on my existing routes.

Now I'm trying to add a new one that parses the `Authorization` HTTP header *only for identification purposes*: the purpose is to show a custom view on *public* data, without any authentication or authorization need. So, I tried to reach my custom route adding an `Authorization` header (via a browser extension), and I get the following error:

```
Path: /CLS/it/pub/quadroxml. Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException:
The used authentication method is not allowed on this route.
in Drupal\Core\EventSubscriber\AuthenticationSubscriber->onExceptionAccessDenied()
(line 134 of [...]/core/lib/Drupal/Core/EventSubscriber/AuthenticationSubscriber.php).

```

So, sending an `Authorization` header apparently triggers some authentication method even on routes with `_access: 'TRUE'`.

Can I disable *completely* all authentication and authorization on some routes? Alternatively, can I enable the "used authentication method" on my route, and then accept any password? (I am only interested in the user id!)

# Answer
Inspired by @4k4 answer, I implemented a custom authentication provider, as detailed here: the sample implementation used on that page only checks for the presence of an header, I just had to replace `X-Auth-Token` with `Authorization` to get the code to do what I need.

With a minor, but important correction: if I left `priority: 10` in the tags of the authentication service, I *still* keep on getting the same error when I send an `Authorization` header in the request. I struggled with this problem for a few hours, googling and searching; in the end my eye fell on the `priority: -10` value of a path processor service I implemented months ago, where I had left the helpful comment "Low priority acts last", so I changed the value of the priority to 1000, and suddenly I managed to get my route to work!

I don't understand exactly why this happens, since I had only my custom authentication provider in the `_auth` vector under `options`, so I don't see how another provider can get a higher priority. I think this may be a bug, I'll try to find the time to reproduce it on a clean installation and file it.

Anyone needing help on this issue should also have a look at this question: it didn't help me much because the problem with priority is not mentioned, but since the problem is exactly the same, maybe other hints may be collected.
> 0 votes

# Answer
I'm not sure about how to accept any password. But there is a difference between the default user authentication and `basic_auth` you are probably using for this route. The first one is defined as global:

*core/modules/user/user.services.yml*

```
user.authentication.cookie:
    class: Drupal\user\Authentication\Provider\Cookie
    arguments: ['@session_configuration', '@database', '@messenger']
    tags:
      - { name: authentication_provider, provider_id: 'cookie', priority: 0, global: TRUE }

```

while the second one is not:

*core/modules/basic\_auth/basic\_auth.services.yml*

```
services:
  basic_auth.authentication.basic_auth:
    class: Drupal\basic_auth\Authentication\Provider\BasicAuth
    arguments: ['@config.factory', '@user.auth', '@flood', '@entity_type.manager']
    tags:
      - { name: authentication_provider, provider_id: 'basic_auth', priority: 100 }

```

In this case the route needs to specify the `_auth` option. See

https://www.drupal.org/docs/drupal-apis/routing-system/structure-of-routes
> 3 votes

# Answer
You can do pretty much anything you want when it comes to access control, by either defining a custom access check via a controller class (1) that you set directly on the specific route, or by creating your own access check service (2).

**1. Access check via controller class**
Docs: Custom route access checking

`example.routing.yml`

```
example:
  [...]
  requirements:
    _custom_access: '\Drupal\example\Controller\ExampleController::access'

```

`ExampleController.php`

```
class ExampleController {

  public function access(AccountInterface $account) {
    // Return \Drupal\Core\Access\AccessResultInterface here
  }

}

```

**2. Access check service**
Docs: Advanced route access checking

Basically, you do the same thing that provides the `_access` parameter that you already use (which is implemented by DefaultAccessChecker. So you create a tagged service and set that service to be a requirement on your route. The example from the docs is very complete, so I don't copy that here.
> 0 votes

---
Tags: 8, routes, authentication-authorization
---


# Question
Title: Programmatically loading and saving nodes is not updating my field but editing and saving manually does. Why the difference?
I have migrated D7 date fields to D9 Smart Date (with recurring). During the migration, I've parsed the legacy repeat rules and populated them into the new D9 Smart Date field.

However, the repeating dates do not show up in Views unless I first manually edit and save the node (without making any changes).

The problem is that I have hundreds of nodes that need to be resaved and none of the progratic methods work. Only manually editing and saving is forcing the repeat rule to do what needs to be done to show up.

I've tried using Views Bulks Action's Save Node function. I've tried using the Save All module. I've tried creating a PHP script to load and save the node.

None of these work. My script is below. Any ideas why only manually saving works?

# Answer
> 1 votes
> Any ideas why only manually saving works?

As Jaypan mentioned in the comments, this is because Drupal won't save the node if nothing has changed.

When you submit the form for an entity which has a created/changed date (i.e. implements `EntityChangedInterface`), it does this:

```
if ($entity instanceof EntityChangedInterface) {
  $entity->setChangedTime($this->time->getRequestTime());
}

```

Which changes a field value, forcing the entity to save.

You could use the same method to force a save in your code.

---
Tags: nodes, migrations
---


# Question
Title: How do I pass a node field value as view argument to another entity reference field?
The issue seems simple, but I can't get any documentation for it.

I have a content type with two drop-down fields: *field\_company* which lists taxonomy terms and *field\_protocol* which is referencing a view of entity reference type.

I want to pass the *field\_company* value to *field\_protocol* as view argument, so that when the company is selected, the protocol list is automatically filtered via AJAX. I did add an AJAX callback to refresh the node form with field\_company field. I don't knoww how to pass the field value and if this value will filter the view by contextual filter.

>

# Answer
> 1 votes
The way I thought to update the dropdown of the node field will not work. This should be done in this way:

https://codimth.com/blog/web/drupal/dependent-select-dropdowns-using-ajax-node-addedit-form-drupal-8-9

```
<?php

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;

/**
 * Implements hook_form_alter().
 */
function MODULENAME_form_alter(&$form, FormStateInterface $form_state, $form_id)
{
  if ($form_id == 'node_article_form' || $form_id == 'node_article_edit_form') {

    //add wrapper to select 2
    $form['field_select2']['#prefix'] = '<div id="select2-wrapper">';
    $form['field_select2']['#suffix'] = '</div>';

    // add ajax to select 1
    $form['field_select1']['widget']['#ajax'] = [
      'callback' => 'callback_field_select1_trigger',
      'wrapper' => 'select2-wrapper',
      'event' => 'change',
      'progress' => [
        'type' => 'throbber',
        'message' => t('Fetching content...'),
      ],
    ];

    //get select 2 options in edit form
    $field_select1_value = $form_state->getValue('field_select1');
    if ($form_id == 'node_article_edit_form' && !$field_select1_value) {
      $field_select1_edit_value = isset($form['field_select1']['widget']['#default_value'][0]) ? $form['field_select1']['widget']['#default_value'][0] : null;
      $form['field_select2']['widget']['#options'] = getSelect2Options($field_select1_edit_value);
    }

  }
}

/**
 * @param array $form
 * @param $form_state
 * @return mixed
 */
function callback_field_select1_trigger(array $form, $form_state)
{
  $field_select1_value = $form_state->getValue('field_select1');
  if (!empty($field_select1_value)) {
    $select1_value = $field_select1_value[0]['target_id'];
    $form['field_select2']['widget']['#options'] = getSelect2Options($select1_value);
  } else {
    $form['field_select2']['widget']['#options'] = getAllSelect2Options();
  }
  return $form['field_select2'];
}

/**
 * @param $select1_value
 * @return array
 */
function getSelect2Options($select1_value)
{
  $query = \Drupal::entityQuery('taxonomy_term');
  $query->condition('vid', "select2_term");
  $query->condition('field_select1.0.target_id', $select1_value);
  $tids = $query->execute();
  $terms = \Drupal\taxonomy\Entity\Term::loadMultiple($tids);
  $options = [];
  $options['_none'] = t('- Any -');
  foreach ($terms as $key => $term) {
    $options[$key] = $term->name->value;
  }
  return $options;
}

/**
 * @return array
 */
function getAllSelect2Options()
{
  $query = \Drupal::entityQuery('taxonomy_term');
  $query->condition('vid', "select2_term");
  $tids = $query->execute();
  $terms = \Drupal\taxonomy\Entity\Term::loadMultiple($tids);
  $options = [];
  $options['_none'] = t('- Any -');
  foreach ($terms as $key => $term) {
    $options[$key] = $term->name->value;
  }
  return $options;
}

```

```
// example how to get options if select 1 is multiple field
$selectedItems = [];
$default_values = $form['field_select1']['widget']['#default_value'];
if ($default_values != NULL) {
  foreach ($default_values as $key => $value) {
    if ($value != 0) {
      $selectedItems[$value] = $value;
    }
  }
}
if (count($tab) > 0) {
  $form['field_select2']['widget']['#options'] = getSelect2Options($selectedItems);
} else {
  $form['field_select2']['widget']['#options'] = getAllSelect2Options();
}

```

---
Tags: views, nodes, 9
---


# Question
Title: How can I set a variable for all theme templates?
I want to set few global variables which I need to be available in all my theme's Twig templates in Drupal 8.

Drupal 7 documentation mentions preprocess function:

> themeName\_preprocess This one is named after the theme itself. Applies to all hooks.

So I added the function below to my `themename.theme` file, but the variables aren't set.

```
function themename_preprocess(&$variables) {
  $theme_path = $variables['base_path'] . $variables['directory'];
  $variables['theme_path'] = $theme_path;
  $variables['images_path'] = $theme_path . "/images/";
  $variables['templates_path'] = $theme_path . "/templates/";
}

```

When instead of defining `themename_preprocess` I define `themename_preprocess_page` (below) the variables are properly defined and available in `page.html.twig` template. I also tried defining `template_preprocess()`, but got error `PHP Fatal error: Cannot redeclare template_preprocess() (previously declared in /home/robert/programming/dns-drupal/core/includes/theme.inc:1202)`.

```
function themename_preprocess_page(&$variables) {
  $theme_path = $variables['base_path'] . $variables['directory'];
  $variables['theme_path'] = $theme_path;
  $variables['images_path'] = $theme_path . "/images/";
  $variables['templates_path'] = $theme_path . "/templates/";
}

```

But I want the variables to be available in **all** templates instead of only `page.html.twig`. How can I do that?

# Answer
> 0 votes
use hook\_preprocess in a custom module, then it will available in all the themes.

for example here I set a `activeLang` and it will be available in all themes and pages

```
/**
 * @param $variables pass active lang everywhere
 */
function YOURMODULE NAME_preprocess(&$variables) {
  $interfaceLang = \Drupal::languageManager()
    ->getCurrentLanguage()
    ->getId();
  $contentLang = \Drupal::languageManager()
    ->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)
    ->getId();
  $variables["activeLang"] = $contentLang ?? $interfaceLang;
}

```

---
Tags: theming, 8
---


title: Set cookie inside webform handler

text:
# Question
Title: Set cookie inside webform handler
Following up with my previous question, I need to set and retrieve a cookie in two difference places:

* set - inside `postSave()` in a Webform handler
* get - inside an event subscriber.

In looking around, it seems that there are a few different options for tools, such as `\Symfony\Component\HttpFoundation\Response` and `\Symfony\Component\HttpFoundation\Cookie`, or `GuzzleHttp\Cookie\SetCookie` and `GuzzleHttp\Cookie\CookieJar`.

For setting the cookie, if I try this in my webform handler:

```
$values = $webform_submission->getData();

$response = new Response();
$cookie = new Cookie('Dixon customer info form', $values['destination_url'], 0, '/' , NULL, FALSE);
$response->headers->setCookie($cookie);
$response->send();

```

I get redirected to a blank page. If I try this:

```
$values = $webform_submission->getData();

$cookie_jar = new CookieJar();
  // Get the current host.
  $host = \Drupal::request()->getSchemeAndHttpHost();

  // Set a cookie for the specific form.
  $cookie = new SetCookie([
    'Name' => 'formEnterCookie',
    'Value' => $values['destination_url'],
    'Domain' => $host,
    'Secure' => FALSE,
  ]);
  $cookie_jar->setCookie($cookie);

```

no cookie gets set. Using either option, how do I set my cookie within my webform handler?

# Answer
> 0 votes
Just in case someone still needs this: There's a module https://github.com/vaza18/webform\_cookie, which work fine for me. It's setting a cookie the old way - using PHP https://www.php.net/manual/en/function.setcookie.php function.

---
Tags: 8, webforms, cookies
---


title: EventSubscriber not trigger

text:
# Question
Title: EventSubscriber not trigger
I have a `EventSubscriber` which I want to trigger before the entity is saved (to alter the title). But I can't figure why it doesn't work. I got back the projet, do the migration from D8 to D9. Is it possible that is came from the D9 migration ?

I could simply add the `hook_entity_presave` in a module, but I guess it's cleaner to add that in an `EventSubscriber`

```
  my_module.entity_event_subscriber:
    class: Drupal\my_module\EventSubscriber\EntityEventSubscriber
    arguments: ['@entity_type.manager','@entity_field.manager']
    tags:
      - { name: event_subscriber }

```

Here my event

```
<?php

namespace Drupal\my_module\EventSubscriber;

use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\hook_event_dispatcher\Event\Entity\EntityPresaveEvent;
use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class EntityEventSubscriber implements EventSubscriberInterface {

  private $em;
  private $entityFieldManager;

  public function __construct(EntityTypeManagerInterface $em, EntityFieldManagerInterface $entityFieldManager) {
    $this->em = $em;
    $this->entityFieldManager = $entityFieldManager;
  }
  public static function getSubscribedEvents() {
    return [
      HookEventDispatcherInterface::ENTITY_PRE_SAVE => 'entitySave',
    ];
  }

  /**
   *
   */
  public function entitySave(EntityPresaveEvent $event) {
    /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
    $entity = $event->getEntity();
    $entity_type_id = $entity->getEntityTypeId();
    $bundle = $entity->bundle();
    if (in_array($entity_type_id, ['node', 'node_custom'])) {
        /// logic
    }
  }
}

```

# Answer
> 1 votes
Hook Event Dispatcher in version `8.x-2.x` have had their `EntityPresaveEvent` namespace switched from `hook_event_dispatcher` to `core_event_dispatcher` in Move Entity events to core\_event\_dispatcher.

Please change these references accordingly:

**Before:**

```
use Drupal\hook_event_dispatcher\Event\Entity\EntityPresaveEvent;

```

**After:**

```
use Drupal\core_event_dispatcher\Event\Entity\EntityPresaveEvent;

```

Also ensure you install the new `core_event_dispatcher` dependency.

See also ExampleEntityEventSubscribers.php for example usages.

---
Tags: 9, event-subscribers
---


# Question
Title: Unable to programmatically render webform with CAPTCHA
Our website has a custom route, with a controller rendering a custom Webform. This is required, as the form has some hidden fields to be pre-populated.

Now I would like to add the CAPTCHA module to the webform. When enabling the CAPTCHA for Drupal's default contact form and viewing it in incognito mode, it works nicely. The CAPTCHA shows up.

But when adding the CAPTCHA element to the custom form, it is not displayed at all.

I've tried several ways to embed the form, but none is working:

* Embed as a Webform entity (using `getSubmissionForm(..)`)
* Embed as a Webform entity (using `getViewBuilder('webform')`)
* Embed as a render array with the new element type webform

Would be glad to get any info on what's wrong here?

# Answer
It turned out there is a custom `twig` template in the theme, specifically overwriting this form only. In this template only some specific form elements are rendered:

`/web/themes/custom/some_theme/templates/webfom/webform--course-registration.html.twig`

This wasn't visible at first, because other templates related to this custom form implementation are located in the custom form module.
> 0 votes

---
Tags: 8, webforms, captcha
---


# Question
Title: Creating file from s3fs (S3 bucket) breaks migration
I have s3fs module installed and configured, so when I upload some file it goes to S3 bucket. Then I'm making processing plugin which should copy file from another S3 bucket to Drupal's bucket and register that file. Copying bucket to bucket works well, so after that part is done I have file in Drupal's bucket at `private/images/image.jpg`. Inside `private/images` folder I also have other images uploaded from the back-end so that part should be ok.

Then my transform() function of my class that extends `Drupal\migrate\Plugin\migrate\process\FileCopy` should create a file and return it's id. I'm doing it like:

```
 $file = File::create([
        'uri' => $final_destination,
        'uid' => $uid,
        'status' => FILE_STATUS_PERMANENT,
      ]);

      $file->save();
      return $file->id();

```

`$final_destination` has the value: `private://images/image.jpg`, file is created, id is returned.

Now the problems:

* migration fails and when I list messages I get: `"[file]: uri.0.value=This value should be of the correct primitive type. "`
* File does exist in the back-end and it's path looks ok, but when I try to open it I get the message that file doesn't exist. When comparing with some file uploaded from the back-end path looks ok and also location in the bucket is correct.
* What I notice is missing is record in `s3fs_file` table for migrated file, while manually uploaded ones have the record there.
* Tried manually adding the record there and after that when trying to open file instead of file is missing I get message that I don't have permission to see the file (logged in as master admin).

What I'm doing wrong? Should I create file somehow differently so it's also processed by s3fs module?

**Update:** I added following rows after $file-\>save();

```
  $uri = $file->getFileUri();
  $stream = new S3fsStream();
  $stream->writeUriToCache($uri);

  if ($stream->waitUntilFileExists($uri)) {
    return $file->id();
  }
  throw new MigrateSkipProcessException("File could not be retrieved from S3://$uri.");

```

And now Instead of "file doesn't exist" I'm getting "access denied" when trying to open file, i.e. in drupal's log I see message:

```
Path: /system/files/images/image.jpg. Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException: in Drupal\system\FileDownloadController->download() (line 80 of /var/www/web/core/modules/system/src/FileDownloadController.php).

```

And there request is identical (except the file name and date stumps), but header is different, for working file uploaded in back-end:

```
Array
(
    [Content-Type] => image/png
    [Content-Length] => 744920
    [Cache-Control] => private
)

```

And for problematic one:

```
Array
(
    [0] => -1
)

```

# Answer
Problem was what plugin returns. It should return file uri object, and not file id:

```
return $file->getFileUri();

```

Also, if files are private and not referenced accessing them is not allowed.
> 0 votes

---
Tags: 8, files, migrations
---


# Question
Title: Is there a way to limit the time zones available to the user to select from?
We have a Drupal 9 site that has a Smart Date field with Time Zones. However, the time zone selection list is huge. We want to limit it to the four main US times zones. Is this possible?

# Answer
> 2 votes
I have never personally used that module, but according to their release notes, since version 3.0.0-rc1 this seems to be possible via the widget configuration:

> Another step towards a stable release for the 3.0.x branch. This release brings improved Gin and Claro compatibility, cleanup up a variety of UI/UX issues, and fixes for notices being logged in a variety of circumstances. Also included here is a substantial amount of coding standards cleanup, in some cases for code going back to the 2.x branch. **A new feature in the timezone widget is the ability to choose a subset of timezones to make available, so sites with a specific range of timezones to support can simplify the editor experience.** There is now also improved views handling for recurring events, including the ability to expose a filter to view events recurring at a specific frequency (daily, weekly, monthly, etc.).

I also see relevant code for that in the current release branch src/Plugin/Field/FieldWidget/SmartDateTimezoneWidget.php

---
Tags: datetime
---


title: What could be causing this error?

text:
# Question
Title: What could be causing this error?
I am facing an error in Drupal 9 Stripe module. After installing the module and setting the private and public keys, I visited the /admin/commerce/orders/84/payments/add page, and selected my newly created 'test stripe payment' as payment gateway. Then, I selected one of the payment methods that I've added from /user/18/payment-methods (*Add new payment method*). This redirected me to the *Add payment* page where there is an *Amount* field and two radio buttons (*Authorize only* and *Authorize and capture*) and an *Add payment* button. When I click on this button, the site crashes with the following error.

> Error : Call to a member function getRemoteId() on null dans Drupal\commerce\_stripe\Plugin\Commerce\PaymentGateway\Stripe-\>createPaymentIntent() (/home/mywebsite/www/web/modules/contrib/commerce\_stripe/src/Plugin/Commerce/PaymentGateway/Stripe.php line 430)

The line causing the error belongs to this function. Does it mean `$payment_method` is null? Do you have any idea on what might be causing this error?

```
/**
  * {@inheritdoc}
  */
public function createPaymentIntent(OrderInterface $order, $capture = TRUE) {
  /** @var \Drupal\commerce_payment\Entity\PaymentMethodInterface $payment_method */
  $payment_method = $order->get('payment_method')->entity;

  // Line 430
  $payment_method_remote_id = $payment_method->getRemoteId();
  $customer_remote_id = $this->getRemoteCustomerId($order->getCustomer());

  $amount = $this->toMinorUnits($order->getTotalPrice());
  $order_id = $order->id();
  $capture_method = $capture ? 'automatic' : 'manual';
  $intent_array = [
    'amount' => $amount,
    'currency' => strtolower($order->getTotalPrice()->getCurrencyCode()),
    'payment_method_types' => ['card'],
    'metadata' => [
      'order_id' => $order_id,
      'store_id' => $order->getStoreId(),
    ],
    'payment_method' => $payment_method_remote_id,
    'capture_method' => $capture_method,
  ];
  if (!empty($customer_remote_id)) {
    $intent_array['customer'] = $customer_remote_id;
  }
  try {
    $intent = \Stripe\PaymentIntent::create($intent_array);
    $order->setData('stripe_intent', $intent->id)->save();
  }
  catch (\Stripe\Exception\ApiErrorException $e) {
    ErrorHelper::handleException($e);
  }
  return $intent;
}

```

# Answer
Commerce Stripe is a bit of a mess at the moment. There are lots of issues that need to be fixed as you can see in the project issue queue.

You are probably experiencing the bug described on Stripe\PaymentIntent instance has invalid ID, but there is a longer discussion about how to handle this at \[meta\] SCA, the Stripe Review pane and recurring payments.

Basically, the issue is that Commerce Stripe does not generate a payment ID unless you go through the review pane first. That means that if you configure a standard Commerce checkout flow and go through that flow (login -\> cart -\> checkout, etc.), then the module will probably work. If not, you will spend hours searching the issue queue to try to debug the module.

Source: Have spent several frustrated hours over the past couple years with Commerce Stripe.

If it helps, I'm currently using the following patches just to get the module to work on my site:

```
    "drupal/commerce_stripe": {
        "do not load stripe library on every page": "https://www.drupal.org/files/issues/2020-02-03/3083393-21.patch",
        "skip review step by autosubmit": "https://www.drupal.org/files/issues/2020-09-16/commerce_stripe-3171411-2.patch",
        "fix 1112 errors https://www.drupal.org/project/commerce_stripe/issues/3177168": "https://www.drupal.org/files/issues/2020-10-16/3177168-2_commerce_stripe-fix_address_errors.patch",
        "fix TrustedCallbackInterface warning https://www.drupal.org/project/commerce_stripe/issues/3168822": "https://www.drupal.org/files/issues/2020-10-09/PaymentMethodAddForm%20needs%20to%20implement%20TrustedCallbackInterface%20for%20Drupal%209-3168822-14.patch"
    },

```
> 1 votes

# Answer
I had the same issue and struggle to know what actions go on what steps. These posts helped but had a lot of trial and error left to do. I thought I would post my flow for reference for others. Please note that a couple actions are custom modules that I built: (Terms and COnditions, and Need Help)
> 0 votes

---
Tags: payment-gateways
---


title: Aggregating by date field

text:
# Question
Title: Aggregating by date field
I've been trying to aggregate (SUM) by a date field with a custom format (YYYY, MM) but its not working as expected. I tried Views Date Format SQL and Merge rows modules but didn't work for me. Also, some other suggested solution is to group by field (Table settings) which also does not fit my needs.

```
2014-08-05     12
2014-08-05     15
2014-08-15     20
2014-09-09     10

```

Im trying to do it as follows:

```
2014,Aug      47
2014,Sep      10

```

Note: My collected dates attributes are year, month , day (i.e. 2014-08-05 00:00:00)

# Answer
I recommend trying the Views Aggregator Plus module. It supports many useful aggregation functions. As an exmaple creating the following output:

```
Industry    Companies             Turnover
Food (2)    Heiny, McRonalds      $566,000,000
Clothing (1)Cenneton              $99,000,000
IT (2)      AcquiB, PreviousBest  $30,000,000
Totals              5             $695,000,000

```

From this source table:

```
Industry    Company Name    Turnover
IT          AquiB           $25,000,000
Clothing    Cenneton        $99,000,000
Food        Heiny           $66,000,000
IT          PreviousBest    $5,000,000
Food        McRonalds       $500,000,000

```

> With the grouping taking place on, say Industry, and aggregation functions TALLY, ENUMERATE and SUM applied on Industry, Company Name and Turnover respectively, the final result with a descending sort on the last column will display like below. Note that the module identified three groups. It also added a totals row, Views Calc style.
> 0 votes

# Answer
To do that you need to tell the database to chop a part of the field. So if your field column in the database is `field_date`, then you should have in the views query something like:

`GROUP BY FROM_UNIXTIME(field_date, '%Y-%m')`

As there's no aggregation plugin (as far as I know), most probably you will need to alter the views query to add that part to the query (there's a hook for that). Also, make sure that `field_date` is not listed again there, as in that case, the `field_date` will kick out the other one.

The above example uses a `datatime` field type (by the database). If you storing the date as a string, you can cut the string end with another SQL function.
> 0 votes

---
Tags: views, datetime
---


# Question
Title: After rendering entity form how can be modified?
I rendering a custom entity form display with the following code:

`$form = $this->entityFormBuilder->getForm($entity, 'array_delimiter');`

This is perfect, as it shows what I set on the form display. However when I try to add a new submit callback function (i.e. `$form['actions']['submit']['#submit'][] = 'custom_callback';`) then this is not being called.
When I try to hide some form items, I lose their data. (i.e. `$form['status']['#access'] = FALSE;`).

But when I do all of this in a `hook_form_FORM_ID_alter` it does work as expected. The callback is being called while hidden form element values are not lost.

Is there a way to do this without an extra `hook_form_FORM_ID_alter`?

# Answer
> 1 votes
Forms are rendered in three stages:

1. The structure of the form is built in FormInterface::buildForm. The result can be altered in a hook\_form\_alter().
2. The form elements are processed. Only form elements which are processed can be submitted.
3. The final render array of the form is rendered.

Despite the name the form builder not only builds the form elements, but also processes them, so that they are ready to be rendered. More complex form elements require this step because the final render structure is built in #process callbacks. But even simple form elements rendering fine without processing can't be submitted.

---
Tags: 8, forms
---


# Question
Title: How to restrict taxonomy term reference with certain terms?
In a node edit/add form, I need to show a field with dropdown/select list options (Cardinality unlimited). I do not want all the taxonomy terms of that vocabulary to appear. I want to show certain terms. The vocabulary has 2 level hierarchy. First dropdown in the form element shows only parent terms. On selecting parent term from the dropdown, certain child elements should show in the second dropdown.

# Answer
You seem to be asking 2 questions here:

* Restricting Terms: You can edit the entity reference field's **Reference method** to use a new custom view that filters only the criteria you're looking for.
* Parent/Child Widget: The Hierarchical Select did have this widget functionality in D7, in D8 there are a few modules out there, like Simple hierarchical select & Client-side hierarchical select, that have similar dual-selection functionality.
> 1 votes

# Answer
Check for the D8 module Tac Lite
> -1 votes

---
Tags: 8, taxonomy-terms
---


# Question
Title: Composer installation missing files from Core
I just attempted to update Drupal 9.2.10 to 9.3.0 using composer and received the following error during the database update.

`views module`
`Update sort_identifier`
`Failed: Drupal\Component\Plugin\Exception\PluginNotFoundException: The "tag" plugin does not exist. Valid plugin IDs for Drupal\views\Plugin\ViewsPluginManager are: in Drupal\Core\Plugin\DefaultPluginManager->doGetDefinition() (line 53 of /path/to/home/dir/core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php).`

I've used composer to install everything for quite some time now, and up until now everything has run just fine.

Upon further inspection into this error, I noticed that the installation doesn't even have the `DiscoveryTrait.php` file that is included in the Core 9.3.0 zip.

Furthermore, the installation is a rather complex multi-site install.

What, if any, ramifications would I encounter by copying some of the files from the zip to my local and pushing the changes via git?

Would I need to keep installing this file manually since it doesn't seem to be included in the composer package?

Lastly, why wouldn't this file had been installed after having run the `composer update "drupal/*" -w` command?

I guess I'm mostly concerned about what other files may be missing from the core at this point too...

# Answer
> 1 votes
The issue lied in my root .gitignore file where I had `cache/` marked as a directory to ignore. I guess when I first set up that ignore file I didn't realize that that line would also exclude `/path/to/public/core/modules/views/src/Plugin/views/cache` and all of its contents, which is where `Tag.php` resides and is the actual plugin that it was looking for.

So for anyone that is seeing this, if you have a cache folder that you want to ignore from your root directory, make sure you add `!*/core/**/cache/` to include any core cache files.

---
Tags: views, 9
---


# Question
Title: How do I output HTML from a text_long field in Twig?
What is the alternative to the `|raw` filter if I want to output html from a entity field in twig in Drupal 8?

According to this ticket, `|raw` should be avoided, but I can't figure out how to use what they recommend in that ticket (Safestring/SafeMarkup) in twig.

I have a custom content entity that has a field definition as follows:

```
$fields['internal_description'] = BaseFieldDefinition::create('text_long')
  ->setLabel(t('Internal description'))
  ->setSettings(array(
    'max_length' => 1500,
  ))

```

The field stores HTML from a CKEditor instance. Now I would like to output this as HTML in a twig template. Currently if I just call

```
{{  event.getExternalDescription }}

```

I get the escaped HTML as expected, however that is not what I want. If I do

```
{{  event.getExternalDescription | raw }}

```

I get what I want, which is unescaped, rendered HTML. However since it's not checked in any way in this case, I would like to know how to make this output safe and still allow my users to use CKEditor for entering content?

# Answer
Normally you would configure the display of the field in UI.

You can do this in code by using the render element `processed_text`.

**PHP**

```
  $build = [
    '#type' => 'processed_text',
    '#text' => '<p>Hello world</p>',
    '#format' => 'full_html',
  ];

```

**TWIG**

In twig you would use instead of the extremely unsafe `{{ event.getExternalDescription | raw }}` this code:

```
  {% set build = {
    '#type':   'processed_text',
    '#text':    event.getExternalDescription,
    '#format': 'full_html',
  } %}

  {{ build }}

```

The safety of the text format depends on the configuration of the text filters and the content of the field. Apply the same security considerations as you would for text formats in ckeditor.
> 13 votes

# Answer
This type of usage worked for me, in making a long text wysiwyg field render that was within a paragraph entity on a node:

```
{{ item.entity.field_innerfieldname.value|t() }}

```

Specifically within nodes where field\_paragraph\_items is the set of paragraph elements:

```
{% for item in content['#node'].field_paragraph_items %}

```

It took a while to figure this out. the twig processor |t() is not widely advertised.

See also:
> 2 votes

# Answer
After @HongPong answer (sorry, I can't comment, yet) I found the following DID work for me:

```
{{ node.body.value|t }}

```

Note there're no brakets after '|t' !

Before I was using simply `{{ node.body.value }}` and got the HTML tags parsed onto the webpage (e.g. '`<p>`') while in the webpage code got *escaped* AKA *HTML encoded* (e.g. '`<p>`').
> -1 votes

---
Tags: theming, 8, entities
---


# Question
Title: How to limit access to the Views pages of the user account?
I created Views page with tabs in the users account.

The problem: If I am user `3` and I go to the page of user `56`, I have access to the page.

I have searched in the Contextual filters on the Views page and there is no setting to limit this.

How do I limit access to the Views pages of the user account ? The current user must have access to all the pages of his own account, but not to those of other users.

**EDIT**

Here is a very simple Views page for the user account. How do I display a 403 page if I go to another user page ?

EXAMPLE :

I am the user ID:88 I have access to the page /user/88/demo

I must not have access to /user/69/demo

```
uuid: faef0cd7-9481-4a11-920e-77b683989956
langcode: fr
status: true
dependencies:
  config:
    - core.entity_view_mode.node.teaser
  module:
    - node
    - user
id: demo
label: Demo
module: views
description: ''
tag: ''
base_table: node_field_data
base_field: nid
display:
  default:
    id: default
    display_title: Default
    display_plugin: default
    position: 0
    display_options:
      title: Demo
      fields:
        title:
          id: title
          table: node_field_data
          field: title
          relationship: none
          group_type: group
          admin_label: ''
          entity_type: node
          entity_field: title
          plugin_id: field
          label: ''
          exclude: false
          alter:
            alter_text: false
            make_link: false
            absolute: false
            word_boundary: false
            ellipsis: false
            strip_tags: false
            trim: false
            html: false
          element_type: ''
          element_class: ''
          element_label_type: ''
          element_label_class: ''
          element_label_colon: true
          element_wrapper_type: ''
          element_wrapper_class: ''
          element_default_classes: true
          empty: ''
          hide_empty: false
          empty_zero: false
          hide_alter_empty: true
          click_sort_column: value
          type: string
          settings:
            link_to_entity: true
          group_column: value
          group_columns: {  }
          group_rows: true
          delta_limit: 0
          delta_offset: 0
          delta_reversed: false
          delta_first_last: false
          multi_type: separator
          separator: ', '
          field_api_classes: false
      pager:
        type: mini
        options:
          offset: 0
          items_per_page: 10
          total_pages: null
          id: 0
          tags:
            next: ››
            previous: ‹‹
          expose:
            items_per_page: false
            items_per_page_label: 'Items per page'
            items_per_page_options: '5, 10, 25, 50'
            items_per_page_options_all: false
            items_per_page_options_all_label: '- All -'
            offset: false
            offset_label: Offset
      exposed_form:
        type: basic
        options:
          submit_button: Apply
          reset_button: false
          reset_button_label: Reset
          exposed_sorts_label: 'Sort by'
          expose_sort_order: true
          sort_asc_label: Asc
          sort_desc_label: Desc
      access:
        type: perm
        options:
          perm: 'access content'
      cache:
        type: tag
        options: {  }
      empty: {  }
      sorts:
        created:
          id: created
          table: node_field_data
          field: created
          relationship: none
          group_type: group
          admin_label: ''
          entity_type: node
          entity_field: created
          plugin_id: date
          order: DESC
          expose:
            label: ''
            field_identifier: ''
          exposed: false
          granularity: second
      arguments:
        uid:
          id: uid
          table: node_field_data
          field: uid
          relationship: none
          group_type: group
          admin_label: ''
          entity_type: node
          entity_field: uid
          plugin_id: numeric
          default_action: default
          exception:
            value: all
            title_enable: false
            title: All
          title_enable: false
          title: ''
          default_argument_type: user
          default_argument_options:
            user: false
          default_argument_skip_url: false
          summary_options:
            base_path: ''
            count: true
            override: false
            items_per_page: 25
          summary:
            sort_order: asc
            number_of_records: 0
            format: default_summary
          specify_validation: false
          validate:
            type: none
            fail: 'not found'
          validate_options: {  }
          break_phrase: false
          not: false
        uid_1:
          id: uid_1
          table: node_field_data
          field: uid
          relationship: none
          group_type: group
          admin_label: ''
          entity_type: node
          entity_field: uid
          plugin_id: numeric
          default_action: ignore
          exception:
            value: all
            title_enable: false
            title: All
          title_enable: false
          title: ''
          default_argument_type: fixed
          default_argument_options:
            argument: ''
          default_argument_skip_url: false
          summary_options:
            base_path: ''
            count: true
            override: false
            items_per_page: 25
          summary:
            sort_order: asc
            number_of_records: 0
            format: default_summary
          specify_validation: true
          validate:
            type: 'entity:user'
            fail: 'access denied'
          validate_options:
            access: true
            operation: update
            multiple: 0
            restrict_roles: false
            roles: {  }
          break_phrase: false
          not: false
      filters:
        status:
          id: status
          table: node_field_data
          field: status
          entity_type: node
          entity_field: status
          plugin_id: boolean
          value: '1'
          group: 1
          expose:
            operator: ''
            operator_limit_selection: false
            operator_list: {  }
      style:
        type: default
      row:
        type: 'entity:node'
        options:
          view_mode: teaser
      query:
        type: views_query
        options:
          query_comment: ''
          disable_sql_rewrite: false
          distinct: false
          replica: false
          query_tags: {  }
      relationships: {  }
      header: {  }
      footer: {  }
      display_extenders: {  }
    cache_metadata:
      max-age: -1
      contexts:
        - 'languages:language_content'
        - 'languages:language_interface'
        - url
        - url.query_args
        - 'user.node_grants:view'
        - user.permissions
      tags: {  }
  page_1:
    id: page_1
    display_title: Page
    display_plugin: page
    position: 1
    display_options:
      display_extenders:
        simple_sitemap_display_extender: {  }
        metatag_display_extender: {  }
      path: user/%user/demo
      menu:
        type: tab
        title: Demo
        description: ''
        weight: 0
        expanded: false
        menu_name: main
        parent: ''
        context: '0'
    cache_metadata:
      max-age: -1
      contexts:
        - 'languages:language_content'
        - 'languages:language_interface'
        - url
        - url.query_args
        - 'user.node_grants:view'
        - user.permissions
      tags: {  }

```

# Answer
You can do the following:

1. In the Contextual filters for the view
2. Check *specify validation criteria*
3. Check *Validate the user has access to the User*
4. Under *Access operation to check* choose *edit*.

This will limit access to the user themselves, and mods/admins who are able to edit their account.

## Other considerations

You can relax those permissions by choosing *view* for the access operation, however if authenticated or anonymous users have permission to view other users profiles on the site, they will also have access to this view/page. This would appear to be the situation in the original question, so *view* would not work for the OP. But for other sites where users are not able to access other user's profiles, this could be an option.

Further permissions could be configured by creating a new custom permission (in a module), for example `view my custom page`, and add that as permission on the access settings for the view. This would add for an additional level of access configuration.
> 0 votes

---
Tags: views, 9
---


# Question
Title: How do I use `NestedArray::getValue()` to get a value from an array?
I see the `NestedArray::getValue()` but the documentation isn't clear. How do I use this to get a value out of a nested array, such as form state or raw form input?

# Answer
If you have an array like this:

```
$my_array = [
  'key1' => [
    'key1.1' => 'a',
    'key1.2' => 'b',
    'key1.3' => 'c',
  ],
  'key2' => [
    'key2.1' => 'x',
    'key2.2' => 'y',
    'key2.3' => 'z',
  ],
];

```

And you want to get to `$my_array['key2']['key2.2']` dynamically (e.g., using an array of `#parents` from a form element), you can use `NestedArray::getValue($my_array, ['key2', 'key2.2'])`.

As a bonus, this method returns a *reference* to the value so you can also change what you get back and the change will be reflected in the array.
> 3 votes

---
Tags: 9
---