# Question
Title: Accessing Webforms Parameters in hook_form_alter
I got a webform which is embedded in a paragraph template. I do this via renderArray which works pretty well - the form is embedded. However I need to grab parameters - the only example I could find is about how to get "GET" parameters or about how to set default values via parameter. This is not what I need. I need the host paragraph as ID in my hook\_form\_alter. But I cannot find the value.

```
<div class="paragraphs-container container">
  <div class="paragraphs-row">
    <div class="paragraphs-col">
     {{ {
       '#type': 'webform',
       '#webform': 'contact',
       '#values': {
         'paragraph_context': 21
       },
       '#parameters':[{'a':'1122'}]
       } }}
    </div>
  </div>
 </div>

```

The hook\_form\_alter $form array should contain either "#values" or '#parameters' but they are not included. - at least not in an easy findable location.

* Are they in any deep sub sub sub location in the array?
* or is there a mystic way to define the parameters for the webform, so hooks can pick them up?

Oh when you ask your self why I just don't use the default value to fill the value of a field directly... The reason would be, that I actually have to create the select form field options first. That's why I need the id to the paragraph - it contains all the holy data stored in its entity.

===================================== EDIT ================ After 3 hours of searching and heavy use of Xdebug I found it.

```
$form_state->build_info["callback_object"]->originalData['value_name']

```

However it is a protected property. So I cannot access the value. There must be an easier way to get form parameters. Is there any?

# Answer
> 2 votes
I can't see a way to access the *originalData* property you mention. It's a protected property and there's no getter defined. See the callback\_object's class in the webform module at *src/WebformSubmissionForm.php*.

I'd take a slightly different approach here. Since you are building custom values based on the paragraph id, it seems appropriate for the paragraph id to be included with the submission data. To do this, add a new *hidden* element to your webform for the paragraph id, e.g. with machine name *paragraph\_context*.

Then, to provide a default value for your hidden field, update your twig like:

```
{{ {
  '#type': 'webform',
  '#webform': 'contact',
  '#default_data': {
    'paragraph_context': paragraph.id,
  },
} }}

```

(Note: I don't see any mention of the *values* or *parameters* options you're using in the How to embed a Webform documentation on d.o.)

Lastly, access your paragraph\_context value via the *#default\_value* key for your hidden element in your *hook\_form\_alter()*. For example:

```
mymodule_hook_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'my_form_id' && !empty($form['elements']['paragraph_context'])) {
    $paragraph_context = $form['elements']['paragraph_context']['#default_value'];
  }
}

```

---
Tags: webforms
---


title: Custom view sorting plugin / handler

text:
# Question
Title: Custom view sorting plugin / handler
I am trying to create a custom sorting option for view that will sort result on the basis of percentage of 2 fields.

field 1 = node\__field\_funding\_amount field 2 = node\__field\_funding\_goal

and i am trying to do something like below

```
$percentage = "round(( $this->tableAlias.$this->realField/node__field_funding_goal.field_funding_goal_value * 100 ),2)";
    $this->query->addOrderBy(NULL,
      $percentage
    );

```

Full code is here 1:- code in views.inc

```
function crowdfundingproject_views_data_alter(array &$data) {
  $data['node__field_funding_amount']['views_cfp_almost_full'] = array(
    'title' => t('CFP Almost Full'),
    'group' => t('Content'),
    'help' => t('Project almost full'),
    'field' => [
      'id' => 'almost_full',
      'click sortable' => TRUE,
    ],
    'sort' => [
      'field' => 'field_funding_amount_value',
      'id' => 'funding-percent',
    ],
  );
}

```

2:- Code in sorting class

```
use Drupal\views\Plugin\views\sort\SortPluginBase;

/**
 * Basic sort handler for Events.
 *
 * @ViewsSort("funding-percent")
 */
class FundingPercent extends SortPluginBase {

  /**
   * Called to add the sort to a query.
   */
  public function query() {
    $this->ensureMyTable();
    $percentage = "round(( $this->tableAlias.$this->realField/node__field_funding_goal.field_funding_goal_value * 100 ),2)";
    $this->query->addOrderBy(NULL,
      $percentage
    );
  }

}

```

But it's showing me column not found error

```
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'node__field_funding_goal.field_funding_goal_value' in 'field list': SELECT node_field_data.created AS node_field_data_created, node_counter.totalcount AS node_counter_totalcount, node__field_funding_end.field_funding_end_value AS node__field_funding_end_field_funding_end_value, node_field_data.nid AS nid, ABS(round(( node__field_funding_amount.field_funding_amount_value/node__field_funding_goal.field_funding_goal_value * 100 ),2)) AS absroundnode__field_funding_amountfield_funding_amount_ FROM {node_field_data} node_field_data LEFT JOIN {node_counter} node_counter ON node_field_data.nid = node_counter.nid LEFT JOIN {node__field_funding_end} node__field_funding_end ON node_field_data.nid = node__field_funding_end.entity_id AND node__field_funding_end.deleted = :views_join_condition_0 LEFT JOIN {node__field_funding_amount} node__field_funding_amount ON node_field_data.nid = node__field_funding_amount.entity_id AND node__field_funding_amount.deleted = :views_join_condition_1 WHERE (node_field_data.status = :db_condition_placeholder_2) AND (node_field_data.type IN (:db_condition_placeholder_3)) ORDER BY node_field_data_created DESC, node_counter_totalcount DESC, absroundnode__field_funding_amount.field_funding_amount_ ASC LIMIT 6 OFFSET 0; Array ( [:db_condition_placeholder_2] => 1 [:db_condition_placeholder_3] => crowdfunding_project [:views_join_condition_0] => 0 [:views_join_condition_1] => 0 )

```

# Answer
There is an error in your SQL so you're getting the column not found error. If you break up your query, you should be able to get it.

Since this question has 1k views and no answers, and I just had to do this myself, here are some helpful resources for anyone looking to build their own Views custom sort plugin in Drupal 8/9.

First, this blog post on Medium by Oleksandr Trotsenko has a detailed tutorial on writing custom sorts and filters for Views. The example is to take a `product weight` and `weight unit` fields to sort all products by weight, regardless of whether that weight is recorded in lb or kg. There are code examples for hook\_views\_data() and the views sort plugin.

There's another tutorial by Clare Ming on how to extend a datefield to add a sort that shows dates in the future first, and then dates in the past in reverse chronological order. It also has code examples.
> 1 votes

---
Tags: 8, views
---


# Question
Title: Add to cart button not displaying inside custom text in drupal 8 views
I created a product display view in drupal8 to display the product. For this, I added some fields like product price, title, and `" add to cart"` form. When I call all the fields inside custom text fields, the add to cart button is not displaying on the page. To display the `" add to cart"` button, I am using

> {{ variations\_target\_id }}

from replacement patterns.

# Answer
> 1 votes
AFAIK you can't rewrite the output of rendered entities (add to cart form) with replacement patterns for in D8 views.

I ran into this same problem and discussed it with the maintainer of the commerce\_variation\_cart\_form module. You can read about it here: https://www.drupal.org/project/commerce\_variation\_cart\_form/issues/3081903

Specifically this from comment #17 https://www.drupal.org/project/commerce\_variation\_cart\_form/issues/3081903#comment-13269416

> All the render code runs including the form generation and extra field addition, but anything in a views field rewrite is then run through Xss::filterAdmin() to remove dangerous tags, and apparently form is a dangerous tag

---
Tags: views, commerce
---


# Question
Title: why my custom jquery code stopped working on a multipage webform after upgrade to WF x6
I have a long questionnaire as multi-page webform and I do many mostly simple counting and addclass using jquery done via a custom module I made for the purpose. This was perfectly working before on Drupal 8 with WF x5 but not anymore after upgrading to Webform x6 (dev) on latest Drupal 9.02.

The below sample code only works if I move the related form to be on first page while it doesn't load on later pages!

```
(function($, load) {
    $('input.countme').change(function(){
        var a =  $("input.countme:checked").length // count all checked checkboxes with the css class "countme"
        $(".cm_score").val(a)  //update the value of the textfield that has the class ".cm_score"
    });
})(jQuery);

```

Below is myModule.libraries.yml

```
wfcount:
  version: VERSION
  css:
    theme:
      css/webform.css: { preprocess: false }
  js:
    js/wfCount.js: { preprocess: false }
  dependencies:
    - core/jquery

```

# Answer
> 1 votes
Following the tips in this post, I changed the code as follows and it worked:

```
(function ($, Drupal) {
 Drupal.behaviors.myBehavior = {
  attach: function (context, settings) {
    $('input.countme').change(function(){
        var a =  $("input.countme:checked").length // count all checked checkboxes with the css class "countme"
        $(".cm_score").val(a)  //update the value of the textfield that has the class ".cm_score"
    });
 }
};
})(jQuery, Drupal);

```

---
Tags: javascript, webforms, 9
---


# Question
Title: What is the difference between State API vs UserData API?
* In which case we will use State API ? Instead of UserData API ?
* Some Use cases where we will use State API ?
* Some use cases where we will UserData API?
* Is there any difference apart from the following?

+ Information stored is not configuration that should be exported.
* Real world examples for both. Is any popular contrib or core modules using this concepts(except user module) ?

# Answer
You find real world examples for State API in the `key_value` table under the collection `state`:

```
comment.maintain_entity_statistics
field.field.deleted
install_time
locale.translation_last_checked
search_api.index.default_index.has_reindexed
system.cron_last
system.maintenance_mode
update.last_check
webform.version

```

The first part of the name is usually the module. In these examples they are core and the popular contrib modules Search API and Webform.

In contrast UserData API is obviously specific to the user, not the entire system. You would use it for data you don't want to store in a user field. Because it is easy to add user fields in code and config this service is rarely used in Drupal 8+.
> 2 votes

---
Tags: 8
---


# Question
Title: What's the event triggered after an autocomplete has run and how to retrieve the value selected
I have a node add form with a term reference that uses autocomplete widget.

I want the "tid" of the filled term by the user using the autocomplete widget.

# Answer
> 13 votes
No event is triggered at the moment (as of 7.34), but there's a patch on this issue that should let you use something like:

```
$('#input-id').on('autocompleteSelect', function(event, node) {

});

```

or if you're using on old version of jQuery

```
$('#input-id').bind('autocompleteSelect', function(event, node) {

});

```

Where `node` is the selected item. You should be able to get the `tid` from one of the properties on that object.

# Answer
> 5 votes
Drupal 7 and 8 provide jQuery autocomplete event generation without any custom code at this time.

In Drupal 7, the `autocompleteSelect` event was added in Drupal issue #365241. (Clive mentioned this was in progress when he posted his response.)

Drupal 8 uses the jQuery UI autocomplete widget. The `autocompleteclose` event is the jQuery UI event most similar to the D7 `autocompleteSelect` event. In D8 the jQuery UI `autocompleteselect` event will also be also triggered but an Ajax callback on it will not receive updated form state values. `autocompleteclose` callbacks are provided with updated form state values, which is usually what you want.

As the other answers have indicated, you may make use of the event data in the client browser using a jQuery on event handler, or Drupal.behaviors (Drupal 7, Drupal 8). In Drupal 7 you would use the `autocompleteSelect` event, and on Drupal 8 `autocompleteclose`.

If you need the value in your PHP code, an Ajax callback may be used. Here are some directions for how to do this in Drupal 7 or in Drupal 8.

# Answer
> 1 votes
I needed to use a behavior to get it to work (thanks to the issue mentioned by Clive, and this comment: https://www.drupal.org/node/365241#comment-9575707):

```
Drupal.behaviors.autocompleteSupervisor = {
    attach: function (context) {
      $('#edit-field-foo-und-0-target-id', context).bind('autocompleteSelect', function(event, node) {

        // Do custom stuff here...
        var entity_id = $(this).val().replace($(node).text().trim(), '').replace(/\(|\)| /g, '');

      });
    }
  };

```

# Answer
> 0 votes
In Drupal 8 this has moved. You can override the functionality with the following code.

```
/**
 * Handles an autocompleteselect event.
 *
 * Override the autocomplete method to add a custom event.
 *
 * @param {jQuery.Event} event
 *   The event triggered.
 * @param {object} ui
 *   The jQuery UI settings object.
 *
 * @return {bool}
 *   Returns false to indicate the event status.
 */
Drupal.autocomplete.options.select = function selectHandler(event, ui) {
  var terms = Drupal.autocomplete.splitValues(event.target.value);
  // Remove the current input.
  terms.pop();
  // Add the selected item.
  if (ui.item.value.search(',') > 0) {
    terms.push('"' + ui.item.value + '"');
  }
  else {
    terms.push(ui.item.value);
  }
  event.target.value = terms.join(', ');
  // Fire custom event that other controllers can listen to.
  jQuery(event.target).trigger('autocomplete-select');
  // Return false to tell jQuery UI that we've filled in the value already.
  return false;
}

```

Overrides the code in `core/misc/autocomplete.js`.

Then in your code you can listen to

```
var field = jQuery('<field-selector>');

var lastField = ''
field.on('autocomplete-select', function() {
    console.log("autocompleteSelect");
    // Check that field actually changed.
    if ($(this).val() != lastValue) {
      lastValue = $(this).val();
      console.log('The text box really changed this time');
    }
  })

```

# Answer
> 0 votes
Drupal 8 uses the jQuery UI autocomplete widget which means you can use one of those events: https://api.jqueryui.com/autocomplete/

```
$(context).find('#my-autocomplete-input-element').on('autocompleteselect', function (event, data) {
  // Do something with "data" ...
});

```

---
Tags: javascript, ajax
---


# Question
Title: How do you add a input and a select field with webforms?
I would like to add a select element that has an input field attached, so the user can input a value from the list without having to scroll through hundreds of options. Is this possible to do with the module webforms? I have researched it and the only thing I can find is the chosen module but I have no idea how the two integrate, and alot of people say it is incompatible in some browsers. Thank you for your help.

# Answer
Welcome to the Drupal Answers Mel.

You can use the Select or Other module. When you enable it, you get another element called Select other. Please take a look at the below screenshots:

Hope that helps.
> 0 votes

---
Tags: forms
---


# Question
Title: How to make a facet search on a taxonomy term contained in a paragraph contained in a content type?
On Drupal 8, I try to make a facet on a taxonomy term contained in a paragraph entity contained in a content type. Is it possible?

My stack : Druapl 8.9.0 + Search API 8.x-1.17 + Facets 8.x-1.5

In Search API, I have indexed the taxonomy from the paragraph. In database I have a new table with 2 columns entity and taxonomy. It seems OK to link node with paragraph with taxonomy id.

I have created the facet without problem but it does not display on my search page.

Is someone has realized this before? Or maybe a advise to resolve this problem.

# Answer
A solution is to associate the taxonomy directly with the content type (field\_ingredient\_search\_index in the example below) and make a hook to update it automatically.

```
$nodeTerms = []; // 1,2,3 = terms IDs
$erase = [];
$node->set('field_ingredient_search_index', $erase);

foreach ($node->get('field_liste_ingredients')->referencedEntities() as $enty){

  if($enty->getParagraphType()->id == 'ingredient' && isset($enty->get('field_ingredient')->target_id)) {
      $nodeTerms[] = $enty->get('field_ingredient')->target_id;
  }

}

$node->set('field_ingredient_search_index', $nodeTerms);

```
> 0 votes

---
Tags: taxonomy-terms, search, paragraphs
---


# Question
Title: user:role:add for email addresses in Drush 9/10?
In Drush 8, you can add a role to an email address like this:

```
drush user-add-role "power user" --mail=penguin@example.com

```

In Drush 9, the --mail option no longer exists for `user:role:add`.

So, if I only have an email address, how can I add a role to the user account?

# Answer
> 5 votes
Maybe there are better ways, but the following should work:

```
drush user-add-role "power user" $(drush user-information --mail=penguin@example.com --field=name)

```

You get the user name from the e-mail address using the user-information command.

---
Tags: drush
---


# Question
Title: How to programmatically associate a taxonomy term to a field
I'm trying to import user profiles data from a JSON file. Several fields are *entity reference* to *vocabularies*.
I'm able to create a new taxonomy term entity in the universities vocabulary bundle using the following code:

```
$term = Term::create([
  'name' => "University of Bologna",
  'vid' => 'universities',
])->save();

```

Now I have to link this newly created term to a field contained in *Profile Type*. I'm testing the following code.

```
    $values = array(
        'type' => 'profile_type',
        'uid' => 3043,
    );
    $profileStorage = \Drupal::entityTypeManager()->getStorage('profile');
    $profileEntity = $profileStorage->create($values);
    $profileEntity->field_entry_university->appendItem($term);
    $profileEntity->save();

```

However, this approach doesn't work. How can I fix it?

# Answer
EntityInterface::save() returns the status of the save operation, not the entity:

```
$term = Term::create([
  'name' => "University of Bologna",
  'vid' => 'universities',
])->save();

```

`$term` is always .

So first assign the newly created entity to `$term` and then save it:

```
$term = Term::create([
  'name' => "University of Bologna",
  'vid' => 'universities',
]);
$term->save();

```

Adding the entity should be no problem then:

```
$profileEntity->field_entry_university->appendItem($term);

```

It doesn't matter whether you add the target entity or the target ID.
> 1 votes

# Answer
`appendItem` takes an array.

Try `$profileEntity->field_entry_university->appendItem(['target_id' => $term->id());`
> 1 votes

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


# Question
Title: How can I suppress the "connection to @remote closed" message?
I'm running Drush 10 and have set up site aliases for my local and the remote Drupal site. When I run the following command for my local alias:

```
drush @local dd

```

This returns:

> var/www/html/abc

But when I run the same command for my remote alias:

```
drush @remote dd

```

This returns:

> var/www/html/abc
>
> Connection to "remote" closed

Why is the output different? Is there any chance to avoid the "connection closed" message?

# Answer
> 2 votes
`--ssh-options="-o LogLevel=QUIET"` suppresses the SSH message but still produces a blank line. Although I couldn't put this into the command line I was able to add this to the self.site.yml file.

```
ssh:
  options: -i /cert.pem -o LogLevel=QUIET

```

---
Tags: drush
---


title: Views relationships

text:
# Question
Title: Views relationships
I have a content type called **part** with a multivalue reference field to a custom entity called **fitment**.

on the part there is a field called **SKU** and on the custom entity type **fitment** there is a field called **fitment ID**

I want to create a table that shows the **SKU** for the part and then a list of fitment id's separated by pipe. This will then be used in data export.

SKU | Fitment ID

0001 |123123|12312|12321

I have tried using rendered entity to display the fitment reference field with a view mode that only shows fitment id but it leaves lots of white space around the fitment id because I have to strip html and whitespace using the views processor.

I'm sure I should be able to do this by adding a relationship in views and then using aggregation but I can't get the fitment id's to group on to the same row. I just get the following.

SKU | Fitment ID

0001 | 123123

0001 | 12312

0001 | 12321

# Answer
> 0 votes
I think you might want to look into Views Aggregator Plus. Views' default aggregation system uses 'group' for every field (you need to change at least one field into count, sum, etc to see effect), but that will not be the effect you are looking for.

Views aggregator plus will be able to also combine field values when grouping on another field.

Example from the project page with multiple companies in one industry:

---
Tags: 8, views
---


title: Import images after git clone

text:
# Question
Title: Import images after git clone
So I did a git clone to get my Drupal 8 site working locally on another PC. This project already has a lot of nodes (articles) with images attached to them. The site works perfect, but of course I did not push the images to git. So ATM I'm a bit confused as to where I should add these images. Is there a proper way to import these with a module or setting? I'm still learning so could be a simple thing I missed. Thanks in advance

# Answer
> 1 votes
The stage\_file\_proxy module is what you're looking for.

You can configure this module to download images on the fly, i.e. as they're needed, or have your local environment serve them straight from your remote environment.

From the project page on d.o, the simplest install:

```
composer require drupal/stage_file_proxy
drush en stage_file_proxy
drush config-set stage_file_proxy.settings origin "https://www.example.com"

```

The module's *INSTALL.md* file goes into more detail about all of the module's options.

---
Tags: 8, version-control
---


# Question
Title: How to create a views filter for users who have never accessed a site?
I have a view where I am trying to show all users who have a last access value of `never`, meaning they have never logged in.

The filter however expects a Date value which is no help to me because I just need to filter by users who have never accessed.

Does anyone know a way around this?

# Answer
> 6 votes
You can achieve this using following simple steps:

1. Add filter criteria **User: Last access** or **User: Last login** is equal to **1970-01-01**

2. You could see the **users.access = 0** in query

> Note: Drupal uses Unix time. The unix time stamp is a way to track time as a running total of seconds. This count starts at the Unix Epoch on January 1st, 1970 at UTC. Therefore, the unix time stamp is merely the number of seconds between a particular date and the Unix Epoch.

# Answer
> 0 votes
Use hook\_views\_query\_alter

> Alter the query before executing the query.

Add a filter to your view on `User: Last access` and set `Is equal to` with `Value: today`

Next create a module and add following:

```
function MODULE_views_query_alter(&$view, &$query) {
  if ($view->name == 'useraccess') { // add your view name instead
    foreach ($query->where as &$condition_group) {
      foreach ($condition_group['conditions'] as &$condition) {
        if (strpos($condition['field'], 'users.access') === 0) {
          $condition = array(
              'field' => 'users.access',
              'value' => array(null),
              'operator' => '=',
          );
        }
      }
    }
  }
}

```

# Answer
> 0 votes
If you use GMT+x you can use "**Regular expression**" instead of "is equal to" and use **^0$** as expression.

The SQL result will be:

```
...
WHERE (( (users.uid NOT IN  ('0')) AND (users.access RLIKE '^0$') ))
...

```

# Answer
> 0 votes
In the value field just enter "never", exactly as it shows on /admin/people

---
Tags: 7, users, views
---


# Question
Title: Private file system, The upload directory private://webform/XXXX/_sid_ for the file field could not be created or is not accessible
I am trying to set up the private file system for drupal 8. I have created a private folder /home/user/public\_html/private\_files with permissions set to 777

in settings.php i uncommented the $settings\['file\_private\_path'\]= '/home/\[USERNAME\]/public\_html/private\_files';

the .htaccess file was created.

the status report page gives: File system Writable (private download method)

When i try to upload a file with either the webform file field or a drupal file field i get the error message: File could not be uploaded.

In the error log i get: The upload directory private://webform/XXXX/*sid* for the file field could not be created or is not accessible. A newly uploaded file could not be saved in this directory as a consequence, and the upload was canceled.

Can anyone help me with this

# Answer
> 3 votes
I had this problem too.

Problem for me was solved by changing Private files setting (in settings.php) to NOT be absolute. Instead make it RELATIVE to Drupal installation. In my case this worked:

$settings\['file\_private\_path'\] = '../private';

Drupal documentation in settings.php says that you should use an absolute path, which seems to be misleading.

# Answer
> 2 votes
Your path must exist outside of your webroot directory and be an absolute path, for example: `/var/www/private` )

Also check PHP configuration

* file\_uploads = On must be set to "On"
* upload\_max\_filesize = 24M can't be larger than post\_max\_size
* max\_input\_time = 300 small values may cause timeouts for large file uploads
* memory\_limit = 64M small values may cause out of memory errors for large file uploads
* max\_execution\_time = 180 small values may cause timeouts for large file uploads
* post\_max\_size = 24M limits the size of input submitted to the website (including attached files)

Information is taken from here.

# Answer
> 0 votes
I ran into the same problem. I set up the private upload directory like this:

```
$settings['file_private_path'] = $app_root . '/../private';

```

That way the private folder was above the web root. Although Drupal could access it Webform couldn't. I tried different path levels and ended up with the directory

```
$settings['file_private_path'] = 'sites/default/private';

```

which is working - although this is not the safest set up.

# Answer
> 0 votes
Same here. Assumed that the documentation was correct, but the only thing that worked in my case was to set it as a relative path (../../drupal\_private\_path).

---
Tags: files
---


# Question
Title: How can I add a Dismiss Button to a Webform Modal Conformation?
I added an extra close button to my webform confirmation modal in a Bootstrap 4 theme:

```
<button class="btn btn-primary" data-dismiss="modal" id="button-close-modal" type="button">OK</button>

```

Then I added a script to act on that button, but it doesn't seem to do anything:

```
(function($) {
  Drupal.behaviors.hideModal = {
    attach: function(context, settings) {
        $('#button-close-modal', context).on('click', function(e){
            $('.webform-confirmation-modal', context).modal('hide');
        });
    }
  };
})(jQuery);

```

Nothing in the console to give me a clue as to what may be happening. I tried `.modal('toggle')` and that didn't work either (although at least I could visually see a change).

I also tried `$('.ui-dialog-titlebar-close', context).click();`, but that didn't work either.

Note: I have the "Webform Bootstrap" module enabled.

# Answer
> 0 votes
Here is how I got it working:

```
(function($) {
  Drupal.behaviors.hideModal = {
    attach: function(context, settings) {
        $('body', context).on('click', '#button-close-modal', function(e){
            $('.webform-confirmation-modal--content', context).dialog('close');
        });
    }
  };
})(jQuery);

```

---
Tags: 8, webforms, bootstrap-theme
---


# Question
Title: Is the X-csrf-token only available for authenticated users?
I am working on a rest api end point. I am noticing that some end points work without X-csrf-token header. Digging into the core revealed the following

```
  // This check only applies if
    // 1. the user was successfully authenticated and
    // 2. the request comes with a session cookie.
    if ($account->isAuthenticated()
      && $this->sessionConfiguration->hasSession($request)
    ) {
      if (!$request->headers->has('X-CSRF-Token')) {
        return AccessResult::forbidden()->setReason('X-CSRF-Token request header is missing')->setCacheMaxAge(0);
      }

```

This means that the X-csrf-token header is only checked for authenticated users. Are anonymous users not required to have this header? This really seems counter-intuitive to me as I feel that authenticated users already have a session cookie and its the anonymous users that need some kind of validation.

How do we add token validation for anonmyous users?

# Answer
> 4 votes
Drupal still doesn't use CSRF tokens for anonymous users. The CSRF token is also checked only when a session is available for the currently logged-in user, and only when the request method declared from the route is not one of the following: *GET*, *HEAD*, *OPTIONS*, *TRACE*.

There are some issues opened for Drupal core, which (at the moment I write this answer) still have to be fixed for Drupal 9.1.x, such as Allow form tokens to be used on anonymous forms in some cases (on January 24, 2024, its status is *Needs work*), CSRF check always fails for users without a session (*Needs work*), and X-CSRF-Token request header is missing when using Bearer authentication (*Needs work*).

The only way to add CSRF tokens for anonymous users is creating a new service that duplicates almost all the code in `CsrfRequestHeaderAccessCheck`, possibly using a route requirement that is different from *\_csrf\_request\_header\_token* used from Drupal core, and add that route requirement to the routes of your module that needs to be accessible also from anonymous users. Such service should also create a session, if it has not been already created.

Keep in mind that CSRF tokens are requested for those routes that alter data (for example, a route that deletes data from the database). If the route is simply showing data, the CSRF token is not required.

---
Tags: 8, csrf
---


# Question
Title: Map array of node IDs to bundle types without loading all the nodes
For complicated reasons I need to map an array of node IDs to a list of node bundles. That is, for a given list of node IDs, I need to get all the different bundles (node types) of the nodes the IDs belong to. The simple approach would be to load all the nodes, map that to their bundles and using array\_unique to get the final list. Unfortunately, this is not a good solution because there may be hundreds of IDs in the array and loading all those nodes will result in a bad performance hit and/or go over the memory limit.

What is the best way to map an array of node IDs to (unique) node bundle types? Is there something built-in or does this require a custom database query? If so, I would be grateful for a dynamic query I could use for this (we're using MySQL). Thanks!

# Answer
> 1 votes
Rather than trying to load all nodes, you can query the DB directly for the `nid`/`type` (Bundle) pairs you need. Query the `node_field_data` table and use the `IN` operator to retrieve all the relevant nids you need.

```
$nids = [1, 2, 3];
//@TODO: add select query on node_field_data
$query->condition('nid', $nids, 'IN');
//@TODO: execute query and array map results

```

See the drupal.org docs on using `IN` operator in dynamic queries.

# Answer
> 1 votes
For reference, here's the query I used to get this result:

```
$nodeIds = [1, 2, 3]; // array of node ids
$query = \Drupal::database()->select('node_field_data', 'n');
$query->condition('nid', $nodeIds, 'IN')
    ->fields('n', ['type'])
    ->distinct()
    ->groupBy('type');
$nodeTypes = $query->execute()->fetchCol('type');

```

---
Tags: 8, nodes
---


# Question
Title: Unknown drupal_view() function although Twig Tweak is installed
Acquia BLT won't let me commit some Twig.

```
> tests:twig:lint:all
Validating twig syntax for all custom modules and themes...
Iterating over fileset files.twig...
  ERROR  in ~/repos/agency/client-site/docroot/themes/custom/client_theme/templates/taxonomy/taxonomy-term--faq.html.twig (line 35)
      33       {{ title_suffix }}
      34       <div class="accordion" data-accordion>
  >>  35         {{ drupal_view('faqs_per_term', 'block_1', term.id) }}
  >> Unknown "drupal_view" function.
      36       </div>
      37     </div>
 [WARNING] 28 Twig files have valid syntax and 1 contain errors.

```

I have installed and enabled Twig Tweak module, and rebuilt cache.

Do you know of any reason why BLT might not know the module is installed?

Possibly relevant: I'm running Drupal and BLT under Lando. The error is triggered after `git push` but I get the same result if I call `lando blt tests:twig:lint:all` directly.

# Answer
If a module defines new twig filters or functions, they need to be manually excluded from the blt linter. Per a comment in the BLT issue queue, you can make these exclusions in *blt.yml* like:

```
validate:
  twig:
    functions:
      - drupal_block
      - drupal_field
      - drupal_view
      - drupal_region
      - drupal_entity
      - drupal_field
      - drupal_menu
      - drupal_form
      - drupal_image
      - drupal_token
      - drupal_config
      - drupal_title
      - drupal_url
      - drupal_link
      - drupal_messages
      - drupal_breadcrumb

```

This is also documented in the Overriding variables at runtime section of the blt docs (it's near the bottom of the section, under the *tests:* list item).
> 2 votes

---
Tags: 8, theming, acquia-cloud
---


title: Can you query webform settings?

text:
# Question
Title: Can you query webform settings?
I have the task to query data from my phpMyAdmin database and also to query the emails from each webform 'to\_email' field. Is there a way to query that data using MySql? I was able to do it using php, but I can't seem to find a way to access the webform email settings by using only MySql.

Edit: I just found out that all the website data is stocated in the database. For example, you can find the data in your 'to\_email' field inside your node.type. row, in a blob.

# Answer
> 0 votes
Yes, it is possible. you can try the following query to find all entries in 'cache\_config' that contain 'to\_email':

```
SELECT cid, data
FROM cache_config
WHERE data LIKE '%to_mail%'

```

This will get you all the blobs that contain the given field. Even more than that, you can look for what follows 'to\_mail' to get the actual mail by using the LOCATE and SUBSTRING functions.

---
Tags: webforms
---


# Question
Title: How to create block to list all children of an entity?
I want to list all the nodes that have the currently viewed node as their parent.

To make this more tangible and less abstract, let's do an example:

---

I have a content type `Locations` which has an *Entity Reference* field called `parent_location` with an unlimited number of values.

For example:

```
- USA (3)                             [country level]
  - New York (4)                        [state level]
    - New York City (6)                   [city level]
      - Central Park (8)                    [landmark level]
      - Empire State Building (9)           [landmark level]
      - Times Square (10)                   [landmark level]
  - Illinois (5)                        [state level]
    - Chicago (7)                         [city level]
      - Sears Tower (11)                    [landmark level]
      - That bean looking thing (12)        [landmark level]

```

So when I view the content for **USA (3)**, I wanna list all the children, meaning **New York (4)** and **Illinois (5)**.

When I view **New York City (6)** I want to list **Central Park (8)**, **Empire State Building (9)**, and **Times Square (10)**.

I want these to show up when I view `/node/6` and be clickable, so that I can browse this nested child/parent structure.

It's already possible by default to traverse UP on the tree. Meaning I can easily get from **Times Square (10)** all the way up to **USA (3)**.

---

However, I can't figure out how to list all children of the appropriate level!

I did create a block view called `List Child Locations`. And I've placed this view on the block `Content`. It shows up correctly, but it does not list the appropriate children.

---

When it comes to editing my view, I have no clue what I'm doing or how...

I see there's two options:

`admin/structure/views/view/list_child_locations/edit/block_1`

and

`admin/structure/views/view/list_child_locations/edit/entity_reference_1`

I think I have to do something with contextual filters, while I'm in the Entity Reference Display. But I can't find anything that looks like what I need...

Out of all those many options, which one do I chose to make sure it does something like

`SELECT * from Locations WHERE parent_location = %current_location%` ?

What's the right settings for my entity display to only list the children?

# Answer
> 0 votes
Finally, I figured it out!

First, I learned more about contextual filters and relationships, and what they each mean and do (relationships basically relates to the FROM query, contextual filters to the WHERE query)

https://www.youtube.com/watch?v=mRWtpcUm9pI

Another user had a similar question and solved it like so:

https://www.drupal.org/project/views/issues/1724396

So all I had to do was:

`/admin/structure/views/add`

* show content of type "Locations"
* Create a block

Then under "advanced" add a contextual filter, check "parent\_location (field\_parent\_location)", press the button to "Add and configure".

Then under "When no filter is available" say "provide a default value" and select "content ID from URL"

Hit apply, save the view.

Under `/admin/structure/block` place the block to the content region and make it visible for Locations.

This was super simple! :-)

---
Tags: views, entities, 9
---


title: Path alias and taxonomy term view

text:
# Question
Title: Path alias and taxonomy term view
I have PathAuto providing /term/\[term:name\] for terms of a specific vocabulary.

If I hover over the link for any of the terms, the path given is the alias.

When a term page is requested, e.g. /taxonomy/term/2, why isn't the page URL replaced with the alias?

# Answer
Normally the internal links /taxonomy/term/% are not used anymore, because all links Drupal puts on the page are aliased. If you want to prevent having multiple paths for the same page you can install https://www.drupal.org/project/redirect.

From the project page:

> * D8: Maintaining a canonical path and redirecting alternative URL's like non-aliased path, path without language prefixes and so on
> (Previously provided by Global redirect)
> 1 votes

---
Tags: path-aliases
---


title: Alter Webform email body

text:
# Question
Title: Alter Webform email body
I'm unable to find an example of altering the body of the Webform email confirmation according to the value submitted. I've got in my form a select field, I would like to change the body of the email according to the selected value (not only include the value in the body but change completely the message).

I have thought about something like this but not sure if it works (unable to test at the moment, sorry):

```
 if (isset($message['params']['email']['eid']) && $message['params']['email']['eid'] != 1) {
      if ($message['params']['submission']->data[1][0] == 'company') {
        $message['body'][0] = 'Thank you .. bla bla.
        Bla bla bla.
        ';
      }
    }

```

Or is it possible to do in form\_alter hook or maybe some module ?

# Answer
You can use hook\_mail\_alter to alter the body of the mail:
Something like

```
/**
 * Implements hook_mail_alter().
 */
function YOURMODULENAME_mail_alter(&$message) {
  // Check here for your mail key
  if ($message['id'] == 'modulename_messagekey') {
    $message['body'][] = 'Thank you .. bla bla.
        Bla bla bla.
        ';;
  }
}

```

Check here https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook\_mail\_alter/7.x for more exemples in comments.
> 1 votes

---
Tags: 7, webforms, emails
---


title: What is correct api key name in headers

text:
# Question
Title: What is correct api key name in headers
I'm using this module https://www.drupal.org/project/services\_api\_key\_auth, it states that you can either put the **api\_key** in query string or inside header. In query it works like this `domain.com/api/pages?api_key=SOMEKEY234729372375`. Passing this key and value in header doesn't work. I've browsed the module's code and found:

```
 $header_api_key = $request->headers->get('apikey');
    if (!empty($header_api_key)) {
      return $header_api_key;
    }

```

So I've tried to name my header **apikey**. Still no response.

Please help :)

# Answer
The code that looks for the API key is in `ApiKeyAuth::getKey()`.

```
  public function getKey(Request $request) {
    $form_api_key = $request->get('api_key');
    if (!empty($form_api_key)) {
      return $form_api_key;
    }

    $query_api_key = $request->query->get('api_key');
    if (!empty($form_api_key)) {
      return $query_api_key;
    }

    $header_api_key = $request->headers->get('apikey');
    if (!empty($header_api_key)) {
      return $header_api_key;
    }
    return FALSE;
  }

```

Effectively, the values that authentication provider looks for are:

* *api\_key* in `$_POST` data
* *api\_key* in the query string (which isn't used, due to a bug in the code)
* *apikey* in the headers

Using the correct key name isn't sufficient. The value passed in that key must be associated to a user, or `ApiKeyAuth::authenticate()` will return an empty array. (It should return `NULL` if the authentication fails, but this should not probably cause any issue.)

```
  public function authenticate(Request $request) {
    // Load config entity.
    $api_key_entities = \Drupal::entityTypeManager()
      ->getStorage('api_key')
      ->loadMultiple();
    foreach ($api_key_entities as $key_item) {

      if ($this->getKey($request) == $key_item->key) {
        $accounts = $this->entityTypeManager->getStorage('user')->loadByProperties(array('uuid' => $key_item->user_uuid));
        $account = reset($accounts);

        if (isset($account)) {
          return $account;
        }
        break;
      }
    }

    return [];
  }

```

Keep in mind that, in the case there are more authentication providers that apply to the same route, Drupal will use just one, after sorting them according to priority using `krsort()`. (See `AuthenticationCollector::getSortedProviders()`.)
In this case, it can happen the used authentication provider isn't the expected one, which is then unable to authenticate the user.
> 1 votes

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


# Question
Title: How do we programmatically place a section and then a block in that region on module install?
We are looking for the best way to export a defined/built layout with inline blocks and then use that to programmatically set both them during a module install.

eg.

* module install
    + create node in content type
    + apply section
    + create and apply block to section in node

Currently we are having to print the array, strip UUIDs.. then attach them to the layout field value of the node we create. Which can lead to issues if not cleaned up correctly.

# Answer
> 2 votes
Put this code in an .install file:

```
// Create a Home web page with alias 'home'.
  $node = Node::create([
    'type' => '<node_type>',
    'langcode' => 'en',
    'uid' => 1,
    'title' => 'Home',
    'status' => 1,
    'path' => [
      'alias' => '/home',
      'pathauto' => PathautoState::SKIP,
    ],
  ]);

  // Variable to hold the sections for this node.
  // Defaulting to have a blank section first.
  $sections[] = new Section('layout_onecol');

  // Create a new section.
  $section = new Section('layout_onecol');

  // Config for the multi-type list block.
  $pluginConfiguration = [
    'id' => '<block_id>',
    'provider' => 'entity_block',
    'label_display' => FALSE,
    'view_mode' => 'default',
  ];

  // Create a new section component using the node and plugin config.
  $component = new SectionComponent($node->uuid(), 'content', $pluginConfiguration);

  // Add the component to the section.
  $section->appendComponent($component);

  // Add the section to the sections array.
  $sections[] = $section;

  // Set the sections.
  $node->layout_builder__layout->setValue($sections);

  // Save the node.
  $node->save();

```

---
Tags: 8
---


# Question
Title: phpcs rule or sniff for detecting usage of the "ksm()" or "kint()" function?
Would it be possible for my local PHPCS standard to warn me when I use certain PHP functions like `kint()` or `ksm()`? It's not part of the Drupal Standard but I'm running a modified version with some improvements like this.

# Answer
Yes, it is possible by Checking Drupal coding standards. You can configure PHP code sniffer to check for Drupal coding standards by following the instructions from https://www.drupal.org/docs/contributed-modules/code-review-module/installing-coder-sniffer and https://www.drupal.org/node/1587138

**Edit**: It turns out you can not identify all the debugging functions with standard Drupal Coding standard functions.In my testing drupalcs was able to identify only `dpm()`and `dsm()` functions but not `ksm()` or `kint()` .

There is an alternative way to identify debugging functions. You can add pre-commit hook to identify the debugging functions.

You can add the below script to git hooks.

```
#!/bin/sh

#
# Git pre-commit hook that prevents code that is not Drupal coding standard compliant of being committed.
#
# Fork of https://git.io/fNXBi by Dave Hall http://davehall.com.au
#

# Fetch the list of files that have changed.
FILES="$(git diff --staged --name-only HEAD --diff-filter=ACMRUXB)"

echo "Running PHP lint check" >&2
LINT_FAIL=0
for filename in $FILES; do
  if ! php -l $filename; then
    LINT_FAIL=1
  fi
done;

# There is no point in running PHP Code Sniffer on broken files.
if [ $LINT_FAIL -gt 0 ]; then
  echo "Commit aborted. Fix your code. Then 'git add' and 'git commit' again."
  exit 1
fi

echo "Running PHP Code Sniffer Checks" >&2
echo $FILES | xargs phpcs --standard=Drupal --extensions=php,module,inc,install,test,profile,theme,css,info,txt --ignore=node_modules,bower_components,vendor,*.md
if [ $? -eq 0 ]; then
 # Exit executing the git commit.
 exit 0
else
  # Ask what to do, not executing the commit. Source: https://unix.stackexchange.com/a/121255/139407
  read -p "Fix the marked Sniff violations automatically [Y/n]?" line </dev/tty
  case "$line" in
    y|Y) echo $FILES | xargs phpcbf --standard=Drupal --extensions=php,module,inc,install,test,profile,theme,css,info,txt --ignore=node_modules,bower_components,vendor,*.md
      ;;
    *) echo "No automatic corrections made."
      ;;
  esac

  echo "Commit aborted. Make remaining manual code fixes if necessary. Then 'git add' and 'git commit' again."
  exit 1
fi

```

Source : Drupal git pre-commit hook
> 0 votes

# Answer
Found the list of "discouraged functions" here:

`vendor/drupal/coder/coder_sniffer/Drupal/Sniffs/Functions/DiscouragedFunctionsSniff.php`

So this class can simply be extended or modified directly, and PHPCS will warn about any other function you add to this list:

```
<?
class DiscouragedFunctionsSniff extends ForbiddenFunctionsSniff
{

    /**
     * A list of forbidden functions with their alternatives.
     *
     * The value is NULL if no alternative exists, i.e., the function should
     * just not be used.
     *
     * @var array<string, null>
     */
    public $forbiddenFunctions = [
                                     // Devel module debugging functions.
        'dargs'               => null,
        'dcp'                 => null,
        'dd'                  => null,
        'dfb'                 => null,
        'dfbt'                => null,
        'dpm'                 => null,
        'dpq'                 => null,
        'dpr'                 => null,
        'dprint_r'            => null,
        'drupal_debug'        => null,
        'dsm'                 => null,
        'dvm'                 => null,
        'dvr'                 => null,
        'kdevel_print_object' => null,
        'kpr'                 => null,
        'kprint_r'            => null,
        'sdpm'                => null,
                                  // Functions which are not available on all
                                  // PHP builds.
        'fnmatch'             => null,
                                  // Functions which are a security risk.
        'eval'                => null,
    ];
}

```
> 0 votes

---
Tags: 8
---


title: Salesforce Connection

text:
# Question
Title: Salesforce Connection
I am currently getting an error when trying to connect Drupal 8 with Salesforce. This will be the first time I am hooking into Salesforce from Drupal and I am not entirely sure what I am doing wrong. I am using the Salesforce Suite Module.

I get the following errors while creating a new authentication provider? (Not on a local environment so Salesforce can see the URL.)

> Notice: Undefined property: Drupal\salesforce\_jwt\Plugin\SalesforceAuthProvider\SalesforceJWTPlugin::$credentials in Drupal\salesforce\SalesforceAuthProviderPluginBase-\>getCredentials() (line 194 of modules/contrib/salesforce/src/SalesforceAuthProviderPluginBase.php).

> Warning: openssl\_sign(): supplied key param cannot be coerced into a private key in Firebase\JWT\JWT::sign() (line 209 of /home/client-name/vendor/firebase/php-jwt/src/JWT.php).

> OpenSSL unable to sign data

Does anyone know where I could start looking or can provide insight into what these errors mean? I have been stuck on this a few days and I can't seem to find anything helpful yet in my research.

The undefined property makes me think that I may be missing a dependency; however, this is a complete guess.

Thank you in advance.

# Answer
> 0 votes
I have fixed my issue and am putting the answer here.

There were two issues that I needed to address:

1. The database was using RDS on AWS and I needed to enable the "log\_bin\_trust\_function\_creators" parameter group
2. Add TRIGGER privilege for database web user

I hope this helps someone else out there with a similar issue.

---
Tags: 8, crm
---


# Question
Title: Generic field.html.twig template for a custom Entity
I have a custom Entity called custom\_entity, along with a custom module which provides twig templates for my bundles and their fields.

How can I define a generic/base field template for all fields created under custom\_entity?

For a specific field I could create the template:

```
field--custom-entity--field-my-field.html.twig

```

But I'm looking to do something more general, like:

```
field--custom-entity.twig

```

Where all my fields created on a custom\_entity use this base template.

I don't want to modify field.html.twig in the theme. I want this template to only apply to my entity and its bundles.

# Answer
> 1 votes
Add your own theme suggestion:

*mymodule.module*

```
/**
 * Implements hook_theme_suggestions_field_alter().
 */
function mymodule_theme_suggestions_field_alter(array &$suggestions, array $variables) {
  $element = $variables['element'];
  // place the least specific suggestion at the beginning of the array
  array_unshift($suggestions, 'field__' . $element['#entity_type']);

}

```

---
Tags: theming, entities
---


# Question
Title: What payment gateway should be used for invoice payment?
My Drupal commerce site supports multiple payment gateways. One of the payment types should be paying by invoice. That means if you select invoice payment type during checkout process you don't have to enter any "real" payment info (credit card data or something), but at end site should send you invoice (pdf document) with instructions how to pay your order.

I've installed Invoice module: https://www.drupal.org/project/commerce\_invoice

And if I understood well I should use actions and rules to send email after checkout is complete. Is that true?

But what puzzles me most is that this module doesn't provide invoice payment gateway. So I don't know how to achieve that when user is selecting payment method "Pay by invoice" method appears? Should I use some dummy (test) payment gateway or? What payment gateway should be used for invoice payment?

**An update:**

What Rules event should I use to detect that checkout process is finished, so I can send invoice.

Also, what action should I select to send email that contains invoice (with link to PDF document or PDF document attached)?

# Answer
Yes - just create a new (custom, standard) payment method named Invoice, and user's then can select that.

On the payment method edit form you can add more details, and even could limit the availability of the method.

Rules are not actively supported as in D7: https://www.drupal.org/node/1535554 But I do not see a need using rules with your use-case.

You need to configure your invoice type to send emails, there should be a checkbox: *Email the customer a confirmation when an invoice is generated* \- see https://www.drupal.org/project/commerce\_invoice/issues/3089861

The invoice is attached by default and you can remove the attachment with hook\_mail\_alter, it's using the id *invoice\_confirmation*. See https://git.drupalcode.org/project/commerce\_invoice/-/blob/8.x-2.x/src/Mail/InvoiceConfirmationMail.php (**UPDATE:** The invoice types seem to create invoices for all payment methods and is not (yet) configurable to limit them)

See also the **commerce-invoice-confirmation.html.twig** to change the email.

Not attaching the PDF makes the emails smaller, and maybe passes more SPAM filters .. But users need to take action and press a link .. I would discuss that with the customer or maybe try both and gain experience with them. (Like what method is really paid more, and which one is faster)

**UPDATE:** If you only want to send the invoice for one payment method you need to alter the commerce receipt email (id: *order\_receipt*) and attach the invoice there. You'll find the order entity in the body's theme render array (first entry using #theme commerce\_order\_receipt)
> 2 votes

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


# Question
Title: Getting latest entity data from the database
The problem: I open a `drush php:cli` shell and run the following:

```
>>> \Drupal::entityTypeManager()->getStorage('paragraph')->load(477)->get('field_end_time')->getValue()[0]['value'];
=> "05:01"

```

I then change the value in the database to `05:02` via the admin panel (content section).

But if I run the same command again in the shell, I still get `05:01`.

If I close the shell and open a new one I get `05:02`. How do I demand the latest data without terminating the process and starting over? This seems like it must be a basic thing but I've searched far and wide and tried clearing caches and etc. but no dice.

This is affecting me because I have a PHP process that is started by cron that handles a Websocket connections and the same thing is happening there—it's getting stale data from the database.

Thanks for the help.

# Answer
You can clear the cached entity in memory to get the latest field values:

```
\Drupal::entityTypeManager()->getStorage('paragraph')->resetCache([477]);

```

See Referenced entities show old value when changing properties
> 4 votes

---
Tags: entities
---


title: Popups & colorbox issues in Chrome

text:
# Question
Title: Popups & colorbox issues in Chrome
Hoping for some guidance here. Sometime in the past few weeks, my inline modal popups stopped working in Chrome. I had Colorbox set up at the time, both hand coded inline links and views colorbox triggers. With views, the links now force a page refresh to the home page with the colorbox query appended:

* i.e. ?width=500&height=500&inline=true#content

With hard links, the page refreshed on the existing page, with the same query string added.

After some investigation, I discovered that ONE page on the site still works, but it's part of a series of panel variants on a page. I've been through the variants with a fine toothed comb, but they're configured identically, so there's no clear reason why this one page should work when the others don't. I've also tested Chrome on two other (both older) laptops, with the same results.

I installed the Popup module to see if I could by-pass the issue, but the results are exactly the same. The popups work on the one rogue page but not on any of the others. So the problem isn't colorbox, but something else. Again, this is ONLY in Chrome. Firefox and IE both work fine.

I've tried creating solo links on basic pages, I've systematically turned off all the other components on all of the test pages ... nothing. I tried removing all of my custom jquery and disabled my custom modules. No dice.

Can anyone suggest another approach, or other possible conflict areas I can test?

Edit to add:

Looks like the working page is processing the link class as "colorbox-inline init-colorbox-inline-processed cboxElement", while the non-functioning pages are only rendering "colorbox-inline". It's the same block on all pages, so I'm not sure why it wouldn't be processed evenly.

The base colorbox inline code I'm using is adapted from the following:

```
<p><a class="colorbox-inline" href="?width=500&height=500&inline=true#id-of-content">Link to click</a></p>

<div style="display: none;">
<div id="id-of-content">What ever content you want to display in a Colorbox.</div>
</div>

```

# Answer
> 0 votes
Turned out to be a conflict with the Superfish menu module. Leaving this here because several other people have reported similar issues and this might help.

---
Tags: modal-dialogs
---


# Question
Title: How to change the url the core search form submits to?
The action value for the core search form is /search/node.

How could I get it to go instead to a different url for a custom View?

# Answer
> 1 votes
if you don't want to do it with code you can use Custom Searchit gives you the possibility to configure it from configuration page:
For node search you can change it from ***admin/config/search/pages/manage/node\_search***

# Answer
> 2 votes
You can use hook\_form\_alter or hook\_form\_FORM\_ID\_alter to alter a form.

Core's search block form has a form id of *search\_block\_form*, so you could implement with *hook\_form\_FORM\_ID\_alter()* like:

```
use Drupal\Core\Form\FormStateInterface;

function mymodule_form_search_block_form_alter(&$form, FormStateInterface $form_state) {
  $form['#action'] = '/my-custom-path';
}

```

---
Tags: search
---


# Question
Title: Cannot get currentUser after custom Drupal boot
I have a `/foo.php` on the Drupal 8 root which programmatically boots Drupal:

```
chdir('web');
$autoloader = require_once 'autoload.php';
$request = Request::createFromGlobals();
print_r($request->cookies);             // ... ( ... ( [SSESSabfa7...] => _Eu_28jS3Vr8Y... ))
$this->kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod');
$this->kernel->boot();
var_dump(\Drupal::currentUser()->id()); // int(0)

$this->kernel->preHandle($request);
var_dump(\Drupal::currentUser()->id()); // int(0)

```

The problem is that it doesn't seem to be able to access the current user (see the `var_dump`s). By visiting a regular Drupal URL though (e.g at `/` or `/about`) I confirm that the session cookie is correct with a logged in user.

What do I need to do so my custom PHP script boots Drupal in a way that it can return the currently logged in user?

# Answer
> 3 votes
You have to authenticate the user. This is what a normal Drupal request would do as one of the first things after the kernel is booted:

*Drupal\Core\EventSubscriber\AuthenticationSubscriber*

```
public function onKernelRequestAuthenticate(RequestEvent $event) {
  if ($event->isMainRequest()) {
    $request = $event->getRequest();
    if ($this->authenticationProvider->applies($request)) {
      $account = $this->authenticationProvider->authenticate($request);
      if ($account) {
        $this->accountProxy->setAccount($account);
        return;
      }
    }
  }
}

```

Adapting this to the procedural code:

*web/foo.php*

```
<?php

use Drupal\Core\DrupalKernel;
use Symfony\Component\HttpFoundation\Request;

$autoloader = require_once 'autoload.php';
$request = Request::createFromGlobals();
print_r($request->cookies);             // ... ( ... ( [SSESSabfa7...] => _Eu_28jS3Vr8Y... ))
$kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod');
$kernel->boot();
$kernel->preHandle($request);

$container = $kernel->getContainer();
// Ensure our request includes the session.
$request->setSession($container->get('session'));
// Authenticate the user, see AuthenticationSubscriber::onKernelRequestAuthenticate().
$account = $container->get('authentication')->authenticate($request);
if ($account) {
  $container->get('current_user')->setAccount($account);
}

var_dump(\Drupal::currentUser()->id());

```

---
Tags: 8, bootstrapping
---


# Question
Title: Can I move the description of a form field between the label and the field?
I have a form with input fields such as this one:

```
'sex' => array(
    '#type' => 'radios',
    '#title' => t('Sex'),
    '#options' => array('m' => t('M'), 'f' => t('F')),
    '#description' => t("We use this to write Mr. or Mrs. in the letters we send you.")
)

```

By default, this prints the label first ('Sex'), then the radio buttons, and then the description. I would like to print out the label followed immediately by the description and have the radio buttons appear last. How can I achieve this? I know how to load a stylesheet, but in this case it would be nice for the html to appear in the correct order: `<label /><div class="description" /><input />` rather than `<label /><input /><div class="description" />`

**Edit**: The solution proposed by Anil Sagar works, but introduces a bug. Indeed, what I use his solution, it prevents me from giving a description to a checkbox field. In other words, if I write

```
$form['myCheckbox'] = array(
  '#type' => 'checkbox',
  '#title' => t('My checkbox'),
  '#description' => t("My description")
);

```

that description never makes it to the HTML. Does anyone know how to fix this?

# Answer
You need to override theme\_form\_element in your theme template.php to change the order of the form field description. See below code which will change order for all fields.

If you would like to change for only one field, then add a if condition by inspecting $element array only for your field !

```
function yourtheme_form_element($variables) {
  $element = &$variables['element'];
  // This is also used in the installer, pre-database setup.
  $t = get_t();

  // This function is invoked as theme wrapper, but the rendered form element
  // may not necessarily have been processed by form_builder().
  $element += array(
    '#title_display' => 'before',
  );

  // Add element #id for #type 'item'.
  if (isset($element['#markup']) && !empty($element['#id'])) {
    $attributes['id'] = $element['#id'];
  }
  // Add element's #type and #name as class to aid with JS/CSS selectors.
  $attributes['class'] = array('form-item');
  if (!empty($element['#type'])) {
    $attributes['class'][] = 'form-type-' . strtr($element['#type'], '_', '-');
  }
  if (!empty($element['#name'])) {
    $attributes['class'][] = 'form-item-' . strtr($element['#name'], array(' ' => '-', '_' => '-', '[' => '-', ']' => ''));
  }
  // Add a class for disabled elements to facilitate cross-browser styling.
  if (!empty($element['#attributes']['disabled'])) {
    $attributes['class'][] = 'form-disabled';
  }
  $output = '<div' . drupal_attributes($attributes) . '>' . "\n";

  // If #title is not set, we don't display any label or required marker.
  if (!isset($element['#title'])) {
    $element['#title_display'] = 'none';
  }
  $prefix = isset($element['#field_prefix']) ? '<span class="field-prefix">' . $element['#field_prefix'] . '</span> ' : '';
  $suffix = isset($element['#field_suffix']) ? ' <span class="field-suffix">' . $element['#field_suffix'] . '</span>' : '';
   $element_description = "";
  if (!empty($element['#description'])) {
    $element_description = '<div class="description">' . $element['#description'] . "</div>\n";
  }
  switch ($element['#title_display']) {
    case 'before':
    case 'invisible':
      $output .= ' ' . theme('form_element_label', $variables);
      $output .= $element_description;
      $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n";
      break;

    case 'after':
      $output .= ' ' . $prefix . $element['#children'] . $suffix;
      $output .= ' ' . theme('form_element_label', $variables) . "\n";

      break;

    case 'none':
    case 'attribute':
      // Output no label and no required marker, only the children.
      $output .= $element_description;
      $output .= ' ' . $prefix . $element['#children'] . $suffix . "\n";
      break;
  }
  $output .= "</div>\n";

  return $output;
}

```

**Other way & simple way to solve this problem is use jQuery to change the position. This will help you !**
> 1 votes

# Answer
You can solve this with the label\_help module, which is made specifically for this purpose.

In the field settings, it will introduce one more field called "Label help message", which is "Help text to insert below the label and above the input form element." This way, you can choose for each field if you want a description above the field, below it, or both.
> 0 votes

# Answer
Better Field Descriptions is another useful module-- although it doesn't help with user registration forms. https://www.drupal.org/project/better\_field\_descriptions
> 0 votes

# Answer
I found this very helpful blog post to fix this problem : http://www.whenwhowhere.com/tech-blog/move-description-field-below-label-drupal-7-form

Basically, in hook\_form\_alter, you put the title and the description in the #prefix of the element, then unset the title and the description so they don't appear twice ... I tried it and it works perfectly.
> -1 votes

---
Tags: forms
---


# Question
Title: Taxonomy Alphabetical Sorting - Nested or Multi-Level Terms
I have a problem with the taxonomy list. Currently my website's taxonomy is unsorted, and I want to do an alphabetical sort. It is also a multi-level nested list (3 levels). I heard that using 'Reset to alphabetical' button would sort the list as a whole, and not sorting it within the sub-levels. Is there a way to address that? Currently I'm doing a drag-and-drop sort manually, but there are tons of terms and I'd appreciate any help with that! Thanks!

# Answer
> 0 votes
You may reset the list to alphabetical without losing your hierarchy. While the terms will be sorted alphabetically, those terms that have a parent item will keep that parent item, and so naturally will continue to be displayed under that parent in the hierarchy.

The reset button is found at the bottom of the list terms page in Drupal 7

# Answer
> 0 votes
Reset to Alphabetical button is worked not only on parent terms but also on child terms as well. So, if you have a term hierarchy as:

```
Term 1
 - My term 3
 - My term 2
 - My term 1
    - My term 32
    - My term 22
Term

```

After Reset to Alphabetical:

```
Term
Term 1
 - My term 1
    - My term 22
    - My term 32
 - My term 2
 - My term 3

```

Do take a backup of your DB before clicking that button.

---
Tags: taxonomy-terms
---


# Question
Title: Theme a subscriber field in Simplenews issues
I need to address my subscribers in a more personal way. Thus I added fields for Mr./Mrs., firstname, lastname to the subscription block, and data gets collected nicely.
However, I can't see how to theme these fields in simplenews-newsletter-body.html.twig.

In the header of this template there's an example printing the subscriber's (built-in) mail.

```
 {{ simplenews_subscriber.getMail  }}

```

Trying the same as `{{ simplenews_subscriber.field_lastname }}` doesn't do anything. I tried a lot of variations to this approach, but to no avail.

What's the secret of getting custom subscriber fields to print with Twig?

# Answer
{{ simplenews\_subscriber.field\_lastname.value }}

In the header of this template:

> Note that depending on the used caching strategy, the generated body might be used for multiple subscribers. If you created personalized newsletters and can't use tokens for that, make sure to disable caching or write a custom caching strategy implemention.

To solve it I added in the sites/default/services.yml

```
services:
  simplenews.mail_cache: ~

  simplenews.mail_cache:
    class: Drupal\simplenews\Mail\MailCacheNone

```
> 0 votes

---
Tags: theming
---


# Question
Title: Private file path getting set as public local files
I have a new Drupal 8 site up and running, and in the File System settings I have the *Default download method* set to *Public local files served by the web server*.

My public folder is set to site/default/files. When I set my private folder to site/default/private, I get the following error.

> Writable (public download method)
> The directory sites/default/private is not writable

The public folder is not set to sites/default/private, but sites/default/files, so why does this point to private instead?
My files and private are both writable by Drupal. The permissions for bot the directories are set to 775, so they are writable.
If I remove the private folder setting, the error goes away, but I obviously need the private directory to be set.

What could possibly cause Drupal to be confused on what is the private and public directories?

# Answer
> 0 votes
It's not mixing up public/private directories; the File system report row on the Status report page is conveying multiple bits of information:

* Your default download method ("Writable...")
* Any other issues found with your file system config. In this case, permissions on the private directory.

Regarding the permission issue, you'll need to check what user/group the Drupal/Apache/PHP is running as to confirm 775 lines up with the private dir group.

---
Tags: 8
---


# Question
Title: Why will drupal not recognize my configuration?
I am trying to import configuration from one site to another. I have copied the directory full of config files from an older site to my new site. When I try to run Drush cim, the files all show up as they will be created. However, after answering yes to the prompt I get

```
This import is empty and if applied would delete all of your configuration, so has been rejected. in Drupal\Core\Config\ConfigImporter->validate() (line 756 of
/home/vagrant/code/indigo-signs-pantheon/web/core/lib/Drupal/Core/Config/ConfigImporter.php).
The import failed due for the following reasons:                                                                                [error]
This import is empty and if applied would delete all of your configuration, so has been rejected

```

I found this question and tried changing the UUID like suggested, but it didnt change anything I still get the same error.

Any suggestions

# Answer
> 1 votes
> This import is empty

This error might occurs when the config directory is not configured in the settings.php.

Check for the config directory settings in new site. It will mostly have a different directory configured.

Change to the same folder path as in the old site.

---
Tags: 8, drush, configuration
---


title: Boost + Domain Access + flushing cache

text:
# Question
Title: Boost + Domain Access + flushing cache
I have the Boost and Domain Access modules working correctly. But I've found that if the cache is flushed for one domain it doesn't clear for the others. So if content is added to one, it won't show for others until cron has been run.

Any way to fix this at all?

# Answer
Saw your post on d.o.: https://www.drupal.org/project/domain/issues/1673650

The suggested fix looks good and should still run:

```
function MODULENAME_domain_cron($domain) {
  global $base_root;
  if (isset($domain['path'])) {
    $base_root = $domain['path'];
  }
  boost_cron();
}

```

The error you have there seems strange. The argument should be passed to the hook\_domain\_cron method ?!?

**UPDATE:** You still can try to make the argument optional:

```
function MODULENAME_domain_cron($domain=[])

```

But I would debug that to find out the real reason .. How does your code look for mymodule\_hook\_domain\_cron?
> 1 votes

# Answer
I would use use Elysia Cron module.

> Elysia Cron extends Drupal standard cron, allowing a fine grain control over each task and several ways to add custom cron jobs to your site.

That way I could leave regular CRON jobs just like they are (or tune them, but this is out of the scope of this question).

I would then set up Boost cron job to run every 5 minutes. There are 2 advantages to that:

1. You avoid heavy IO hit on your HDD, spreading it all over the day
2. Your original problem is pretty much solved - 5 minutes cache lag is something you probably can work with all right.
> -1 votes

---
Tags: 7, caching
---


# Question
Title: How can I collect a shipping address on the checkout flow?
I am using the Commerce PayPal module. PayPal is collecting the billing address, but I need to collect the shipping address on checkout.

How can I collect the address? Do I add an address field to the Order Entity or the Profile Entity?

# Answer
> 3 votes
Use the commerce\_shipping module ;)

Just create one "free" shipping method .. or one or more regarding your needs.

Also make sure to use the shipping checkout flow for your order type!

> It's fully integrated with commerce\_paypal and you even can configure how paypal shall treat the two addresses in regards of collection and updating data entered @paypal side back to your Drupal instance.

---
Tags: 8, commerce
---


# Question
Title: Add #ajax callback to an entity_autocomplete field
I have an entity\_autocomplete field in a form.

```
$element['content'] = array(
  '#type' => 'entity_autocomplete',
  '#target_type' => 'node',
  '#title' => t('Content'),
  '#title_display' => 'hidden',
  '#default_value' => $content_default,
  '#selection_handler' => 'default',
  '#selection_settings' => array(
    'target_bundles' => $selected_bundles,
  ),
  '#prefix' => '<div class="container-inline">'
);

```

I would like to add an #ajax callback to run after someone has selected a piece of content from the autocomplete drop-down, but I can't seem to find out how to attach it.

I have tried as follows which works for select boxes.

```
   $element['content']['#ajax'] = array(
      'callback' => 'Drupal\MODULE\Plugin\Field\FieldWidget\WIDGET::METHOD',
      'wrapper' => $id,
      'method' => 'replace',
      'progress' => array(
        'type' => 'throbber',
        'message' => "shuffling",
      ),
    );

```

However, it does not fire. Is it possible to do what i need?

It actually fires if you tab out of the field, but I need it to fire after a selection is made.

# Answer
> 1 votes
Drupal 8 (and Drupal 7) provides jQuery autocomplete event generation without any custom code.

Drupal 8 uses the jQuery UI autocomplete widget. The `autocompleteclose` event is the jQuery UI event most similar to the D7 `autocompleteSelect` event. In D8 the jQuery UI `autocompleteselect` event will also be also triggered but an Ajax callback on it will not receive updated form state values. `autocompleteclose` callbacks are provided with updated form state values, which is usually what you want.

(In Drupal 7, the `autocompleteSelect` event was added in Drupal issue #365241.)

In your case, you would assign this as follows:

```
$element['content']['#ajax']['event'] = 'autocompleteclose';

```

# Answer
> 2 votes
You can adjust the behavior with

```
'#ajax' => array(
  'event' => 'change',

```

This can be any javascript event. The default for a select is on 'change', for a normal field this is on 'blur'. But you can try any other event.

Reference: https://developer.mozilla.org/en-US/docs/Web/Events

# Answer
> 0 votes
As 4k4 mentioned the event can be changed via the #ajax property however there is no event in Drupal that signifies that an autocomplete has just had a selection so the event needs to be added. Taken from What's the event triggered after an autocomplete has run and how to retrieve the value selected

Add the event trigger

```
jQuery(event.target).trigger('autocomplete-select');

```

as follows

```
Drupal.autocomplete.options.select =  function selectHandler(event, ui) {
    var terms = Drupal.autocomplete.splitValues(event.target.value);
    // Remove the current input.
    terms.pop();
    // Add the selected item.
    if (ui.item.value.search(',') > 0) {
        terms.push('"' + ui.item.value + '"');
    }
    else {
        terms.push(ui.item.value);
    }
    event.target.value = terms.join(', ');
    jQuery(event.target).trigger('autocomplete-select');
    // Return false to tell jQuery UI that we've filled in the value already.
    return false;
}

```

Then the #ajax property can be set to listen to this event.

```
'#ajax' => array(
  'event' => 'autocomplete-select',

```

# Answer
> 0 votes
I have a date field on an Event entity. I have a second entity (Request) form with an autocomplete entity reference field to those Events. When i select an event from the autocomplete; I want the Event's date to be used as the default value in the date field on the Request form.

at the top of my custom module:

```
use Drupal\node\Entity\Node;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\InvokeCommand;

```

in my form\_alter I have this:

```
$form['field_my_autocomplete_entityref']['widget'][0]['target_id']['#ajax'] = [
   'callback' => '_mymodule_autofill_date',
   'event' => 'autocompleteclose',
 ];

```

I then add the callback function in my custom module:

```
function _mymodule_autofill_date($form, $form_state) {
  $eid = $form_state->getValue('field_my_autocomplete_entityref')[0]['target_id'];
  $event = Node::load($eid);

  // set Request date fields as same value set in Event
  $start = $event->field_event_date->value;
  $end = $event->field_event_date->end_value;

  $response = new AjaxResponse();
  $response->addCommand(new InvokeCommand('#edit-field-event-date-0-value-date', 'val', [$start]));
  $response->addCommand(new InvokeCommand('#edit-field-event-date-0-end-value-date', 'val', [$end]));

  return $response;
}

```

---
Tags: forms, 8, ajax
---


# Question
Title: How can I get a list of all connected/logged in users?
I would like to make a list of all logged in users accessible through the backend. The routes are created. It is only the request to retrieve the users that I would need. Is this data in the 'sessions' table? Thank you in advance for your help

# Answer
You can try

```
// 3600s is one hour.
$uids = Drupal::database()->query('SELECT uid FROM sessions WHERE uid != 0 AND `timestamp` >=:time',[':time'=>(Drupal::time()->getCurrentTime()-3600)])->fetchCol();

```
> 2 votes

---
Tags: 8, users
---


# Question
Title: How do I detect whether any contact forms have been created?
**Context:** On my Drupal 8 site I'm trying to add in a new section containing a view that lists out all forms. The user can then click on one of the form and it launches a download of all the messages sent through that form. However that section should only be visible if the user has created at least 1 form.

**What I've tried:** So far what I've discovered is that the contact forms are stored in the config table in the database, so I could theoretically run a query like "SELECT 1 FROM config WHERE name LIKE '%contact.form%'" or whatever the equivalent in D8 is. However, it seems like there has to be a quicker way to return either the presence of contact forms or the contact forms themselves programmatically.

**Final question:** How can I return either the contact forms themselves or at least a boolean representing the presence of contact forms programmatically?

# Answer
> 1 votes
You can use the D8 config factory interface to retrieve multiple contact form config keys and their corresponding config entities:

```
$contact_form_keys = \Drupal::configFactory()->listAll('contact.form');
$contact_form_configs = \Drupal::configFactory()->:loadMultiple($contact_form_keys);

```

---
Tags: 8
---


title: Webform email with list of senders

text:
# Question
Title: Webform email with list of senders
I am build a webform to send emails. I have some user local accounts. I would like to login with personal user account and send an email, choosing from a list of possible senders. It is possible in that webform to choose from which email I want to send?

For e.g. I have 2 emails

* email for advertise
* email for internal communication

I would like to go to webform, choose from which this 2 emails I want to sent, is this possible?

# Answer
> 1 votes
Go to your Webform and in **Build tab** add field of type **Select** *(Select / Entity Select)* and define all options (email addresses from which it is possible to send emails) in your field's detail form.

Then go to Webform settings and under tab **Email handlers** add **new Email**. Fill basic fields *(subject, body)* and as your **sender** *(address from which email should be send)* select name of the **Select** field you've created earlier. As receiver *(address which should receive email)* set whatever email you need.

---
Tags: webforms, emails
---


# Question
Title: User edit form on custom page is resetting roles when user belongs to the "Administrator role"
I'm trying to display the user edit form on a custom page with limited fields. Submitting my form works well, but if I have the *Administrator* role, roles are reset. I don't understand why this is happening.

This is the routing file custom\_user\_profile.routing.yml.

```
my_module.default_controller_view:
  path: '/my_module'
  defaults:
    _controller: '\Drupal\my_module\Controller\DefaultController::view'
    _title: 'Account'
  requirements:
    _user_is_logged_in: 'TRUE'
  options:
    no_cache: 'TRUE'

```

In the controller DefaultController.php I have

```

namespace Drupal\my_module\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\user\Entity\User;

class DefaultController extends ControllerBase
{

    public function view()
    {
        $user = User::load(\Drupal::currentUser()->id());

        $html = '';
        $html .= '<p>Current email is ' . $user->mail->value . '</p>';

        $data['html'] = [
            '#type' => 'markup',
            '#markup' => $html,
        ];

        $user = User::load(\Drupal::currentUser()->id());
        $formObject = \Drupal::entityTypeManager()
            ->getFormObject('user', 'default')
            ->setEntity($user);

        $form = \Drupal::formBuilder()->getForm($formObject);

        $data['form'] = [
            'form' => $form,
        ];

        return $data;

    }

}

```

In the my\_module.module I have following code.

```
use Drupal\Core\Form\FormStateInterface;

function my_module_theme($existing, $type, $theme, $path)
{
    $templates = array(
        'my_module_about_form' => [
            'render element' => 'form',
        ],
    );

    return $templates;
}

function my_module_form_alter(&$form, FormStateInterface $form_state, $form_id)
{
    if ($form_id == 'user_form') {
        $form['#theme'] = ['my_module_about_form'];
    }
}

```

In the template file my-module-about-form.html.twig I have the following lines.

```
{{ form.timezone }}

{{ form.form_build_id }}
{{ form.form_token }}
{{ form.form_id }}
{{ form.actions.submit }}

```

# Answer
The form values still persist in the form state, and as they're not printed, the will be submitted as empty and saved accordingly.

Do not hide form element by not outputting them in twig, render the full form there and use `[#access] = FALSE;` on the form elements you don't want to show. Do so in the controller, to only have that on your custom page. If you do that in hook\_form\_alter it will apply to the form always (so here also for the profile page aka /user/X/edit).

> You're mixing two concepts: Showing a form (where you have full control and can add stuff before and after with entries in the render array and use a form-mode for the form, so you can configure the fields via UI and not code) and altering a form (where you do not control where it is shown, and want to change it everywhere). I guess you want to show a form, so I would remove the theme stuff and concentrate only on the output form your controller.

Or even use a different approach .. and create a new form from scratch, populating with the user's value, and save them back to the user entity on submit (If you only need one "field" and even the password fields can be replicated in the custom form). And replace the controller with a form callback in routing.yml.
> 0 votes

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


# Question
Title: How can I avoid to return HTML markup for access denied?
I've developed a custom controller that serves as a simple endpoint, POST method.

This controller has custom access control.

Custom access is done by looking for a header in the HTTP request, by making the controller object a service as well.

Everything works great. Except that when I return AccessResult::forbidden() .. I get the HTML of the access denied page .. and I don't really want that .. I'd like to return just a short bit of JSON.

What can I do to return something that is JSON, and not the Access Denied page HTML, for this particular route, when the access() method returns AccessResult::forbidden() ?

I've read that appending ?\_format=json to the url works, and in my case it does. Is there anyway to achieve the same result without adding this url parameter?

# Answer
If you look into ParagraphAccessControlHandler you will find something similar. Implement something similar in your Access callback.

```
protected function checkCreateAccess(AccountInterface $account, array $context, $entity_bundle = NULL) {

// Allow paragraph entities to be created in the context of entity forms.
  if (\Drupal::requestStack()
    ->getCurrentRequest()
    ->getRequestFormat() === 'html') {
    return AccessResult::allowed()
      ->addCacheContexts([
      'request_format',
    ]);
  }
  return AccessResult::neutral()
    ->addCacheContexts([
    'request_format',
  ]);
}

```
> -1 votes

---
Tags: 8, routes, page-controller
---


# Question
Title: Copying prod multi-site installation to dev multi-site installation
I am attempting to upgrade my Drupal 8.9.2 multi-site installation to D9. I was hoping to work this all out on a development installation, that is located in a subdirectory of my home directory on my NameCheap Shared Hosting plan.

When I first installed this installation, I did so using the tarball method from years ago. I then followed the instructions given here (https://www.drupal.org/docs/installing-drupal/add-composer-to-an-existing-site). I was able to get the current running prod version converted to use composer with out an issue.

Before I go and start messing with the files, and attempting to upgrade to D9 through composer on a prod installation, I wanted to copy these files over to another installation where I can use it as a sandbox. To do this I:

* copied the files on my server to a new directory
* made clone databases for the new installation
* truncated all the cache tables in the cloned DB
* changed all the database settings in the settings files to point to the cloned databases

I've done this before without any issues, and now I seem to be getting a WSOD error on all the sites running from the new installation. The error I'm getting is

> PHP Fatal error: Uncaught Error: Class 'Drupal\Core\Cache\DatabaseBackend' not found in ~/{new installation dir}/public\_html/index.php:16.

If anyone has any thoughts what's going on I am all ears.

Thank you in advance

# Answer
> I was able to get the current running prod version converted to use composer with out an issue.

If you have converted your site to use composer , you dont need to copy the whole code base into the new server. Just copy the config,custom modules, composer.json, composer lock files and other reqired files except the core, vendor and contributed modules into new server along with sites directory folder and run `composer install` in the root directory of the server.This can be done by initiating a git repo in the current code and using the default `.gitignore` file which is available in code.And cloning the same repo in new server.

As you have already copied all the files into new server.

Just run `rm -Rf vendor` , `rm -Rf web/core` and `rm -Rf web/modules/contrib` and run `composer install` from the root directory in the new server.

After doing this you will probably get your site running in Dev environment as well.
> 1 votes

---
Tags: 8, multi-sites
---


# Question
Title: Migrate Multiple URLs from a Spreadsheet into ONE Link Field
I'm trying to migrate from Google Sheets into Drupal 8.9+. I have successfully configured most of the migration, but am having trouble migrating two source link fields (Event URL & Ticketing URL) into ONE multi-value links field (field\_links) in my target node. I'm trying to shape all the source data in my Google Sheet so I don't have to use custom process plugins.

Here's a link to an example of the Google Spreadsheet I'm using as the source.

I found this Github Gist that led me to believe I could shape the two url fields I have in Google sheets into an array, and have that array be processed by the iterator (now, sub\_process) plugin. So I now have a source column called "LinksArray" that merges the data from my "Event URL" and "Ticking URL" columns to create an array that looks exactly like this:

```
[
  ['title' => 'Event URL', 'uri' => 'https://coolvenue.com/etc'],
  ['title' => 'Ticketing URL', 'uri' => 'https://tickets.com/etc'],
];

```

And the relevant migration file looks like this:

```
...

    - name: src_links_array
      label: "LinksArray"
      selector: linksarray
...

  field_links:
    - plugin: skip_on_empty
      method: process
      source: src_links_array
      message: 'field_links is empty. Skipping.'
    - plugin: sub_process
      process:
        title: title
        uri: uri

```

When I run the migration, It appears to be successful, with no errors, but the content created is missing the links altogether (no titles, no uri's, nothing), so is obviously not working. I tried reformatting the array with and without outer brackets, with and without trailing commas, etc. Nothing works. Is my manually created array being written incorrectly? Do I need to create the array inside the migration instead? If so, I'd greatly appreciate help with that. Thank you!

# Answer
I eventually found THIS post on Drupal Stackexchange, and the answer proved to be extremely successful. I changed one of the columns in my source spreadsheet to follow the following format:

```
// Link Title|URL;Link Title|URL etc
// for example:
Event URL|https://coolvenue.com/etc;Ticketing URL|https://tickets.com/etc

```

*You can see an example of the source data sheet here.*

And then in my **migration file**, I used this:

```
...
    - name: src_links_delimited
      label: "LinksDelimited"
      selector: linksdelimited
...
  urls_temp:
    - plugin: skip_on_empty
      source: src_links_delimited
      method: process
      message: "No links. Skipping."
    - plugin: explode
      delimiter: ";"
    - plugin: explode
      delimiter: "|"
    - plugin: default_value
      default_value: ""
  field_links:
    - plugin: skip_on_empty
      method: process
      source: "@urls_temp"
      message: "No links. Skipping."
    - plugin: sub_process
      process:
        title: "0"
        uri: "1"

```
> 2 votes

# Answer
The two main ways to approach this with php are via hook or plugin.

The first is with a hook, specifically, hook\_migrate\_MIGRATION\_ID\_prepare\_row().

> Allows adding data to a row for a migration with the specified ID.

For example, you could combine your two link columns to a new column formatted as an array.

```
function my_module_migrate_MY_MIGRATION_ID_prepare_row(Row $row, MigrateSourceInterface $source, MigrationInterface $migration) {
  // Assuming your url fields are keyed event_url and ticketing_url in your migration.yml.
  $links_array = [];
  if ($row->hasSourceProperty('event_url')) {
    $event_url = $row->getSourceProperty('event_url');
    if (!empty($event_url)) {
      $links_array[] = [
        'title' => 'Event URL',
        'uri' => $event_url,
      ];
    }
  }
  if ($row->hasSourceProperty('ticketing_url')) {
    $ticketing_url = $row->getSourceProperty('ticketing_url');
    if (!empty($ticketing_url)) {
      $links_array[] = [
        'title' => 'Ticketing URL',
        'uri' => $ticketing_url,
      ];
    }
  }

  $row->setSourceProperty('event_and_ticketing_url', $links_array);
}

```

You can use your programmatically added source value in your process section like:

```
process:
  ...
  field_links: event_and_ticketing_url
  ...

```

---

I prefer to use plugins over hooks whenever possible for a few reasons, but one is because plugins are more visible to anybody looking at the implementation later. By looking at the migration.yml, a future developer will know that a custom plugin does something to this thing and the plugin can be found in the src/Plugin directory.

An example doing the same thing, but with a plugin might look like:

**my\_module/src/Plugins/migrate/process/EventAndTicketingLinks.php:**

```
/**
 * Process plugin to combine event and ticketing url sources to one links array.
 *
 * Example Usage:
 *
 * field_my_links_field:
 *   plugin: my_module_event_and_ticketing_links
 *   link_fields:
 *     event: event_url
 *     ticketing: ticketing_url
 *
 * @MigrateProcessPlugin(
 *   id = "my_module_event_and_ticketing_links",
 * )
 */
class EventAndTicketingLinks extends ProcessPluginBase {

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    $config = $this->configuration;
    $links = [];

    if (!empty($config['link_fields']['event'])) {
      $event_url = $row->getSourceProperty($config['link_fields']['event']);
      if (!empty($event_url)) {
        $links[] = [
          'title' => 'Event Url',
          'uri' => $event_url,
        ];
      }
    }
    if (!empty($config['link_fields']['ticketing'])) {
      $ticketing_url = $row->getSourceProperty($config['link_fields']['ticketing']);
      if (!empty($ticketing_url)) {
        $links[] = [
          'title' => 'Ticketing Url',
          'uri' => $ticketing_url,
        ];
      }
    }

    return $links;
  }

}

```

---

Additionally, since you ended up combining the urls into one source column anyway, you could use the hook or a plugin to work with that data too.
> 2 votes

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