# Question
Title: How to display all media that references this taxonomy term and its immediate children?
I have a hierarchical taxonomy vocabulary, "Living Things". A simplified excerpt looks like this:

```
Plants
--Roses
----Red Rose
----Pink Rose
--Orchids
----White Orchid
----Yellow Orchid

```

I have a library of media (images and videos) that have a field, "Primary Taxon", which references the appropriate term in that "Living Things" vocabulary. e.g. An image of various roses has its "Primary Taxon" field set to "Roses", and a video of a white orchid has its "Primary Taxon" field set to "White Orchid".

On my taxonomy term pages, how can I display all media that references that species, and that species' immediate children? i.e. The "Roses" page should show media that displays roses in general, as well as red roses and pink roses. The "Plants" page should show media that displays plants in general, as well as roses in general, and orchids in general, but not the individual species.

Ideally, it should also be possible to sort the view with either "this taxon first", or "children first", but I'm interested in any solution without this functionality too.

So far, I have made a view that shows all media on the taxonomy pages. However I can't find an appropriate contextual filter to limit the displayed media. Even a single contextual filter using "Media: Primary Taxon (field\_primary\_taxon)" stops any media from displaying.

# Answer
> 2 votes
I finally worked this out, using Views (which is a way of querying the database and presenting lists of data). My design places the View as a block on my taxonomy term pages, so I refer to a block display in this method rather than a page display:

**BASIC VIEW TO SHOW ALL MEDIA**

* Structure \> Views \> Add view
    + Enter View name and Description
    + Show *Media* of type *All* sorted by *Unsorted*
    + Select "Create a block"
    + *Unformatted list* of *Fields*
    + Adjust "Items per block" as appropriate (e.g. 25)
    + Save and edit
* Scroll down and check all your Media names are listed in the Preview section, to ensure the basic View is working correctly.
* FIELDS \> Add \> Rendered entity (Category: Media).
    + Here you could alternatively add fields such as Image, Video URL and File rather than the general Rendered entity.
    + Choose the appropriate View mode \> Apply. In my case I had set up a "Preview" display mode in /admin/structure/media/manage/MyMediaType/display, with a thumbnail image format and most fields disabled.
* Scroll down to check your media is listed below the names.
* Click "Media: Name" \> Remove, if you don't want it. It's often unnecessary for media.
* Save

**CONTEXTUAL FILTER TO SHOW ONLY THIS TERM'S MEDIA**

Here we need to make sure that in this block we will only display media that refers to the term whose page the block will be seen on. In this case, that reference is made in a field on my media labelled "Primary Taxon".

* ADVANCED \> CONTEXTUAL FILTERS \> Add
* Select "Primary Taxon (field\_primary\_taxon)" (Category: Media)(or whatever your field is called) \> Add and configure contextual filters
* WHEN THE FILTER VALUE IS NOT AVAILABLE \> Provide default value \> Type: Taxonomy term ID from URL \> Select (only) "Load default filter from term page" \> Apply \> Save. We have to supply the value this way because, unlike a page, a block does not have a URL to find the value in.
* For testing, find the taxonomy term ID number ("TID") for some of the terms in your vocabulary. You can find these in the URL of the taxonomy term's page. For example my Roses page has URL `.../taxonomy/term/86` so the TID is 86. If you have a module such as Pathauto providing URL aliases, then you can find the TIDs by visiting `.../admin/structure/taxonomy/manage/MyVocabulary/overview`, hovering over "Edit" and looking at the URL at the bottom left of your browser.
* In the Preview section, test the View is filtering correctly by entering your different TIDs in the "Preview with contextual filters" box and click "Update preview". For example if I enter 86, I see only media for which I had entered "Roses" in the "Primary Taxon" field.

**RELATIONSHIP & CONTEXTUAL FILTER TO SHOW CHILD MEDIA**

To list media that refers to **children** of the term whose page that the block will be seen on, we need to find media whose **parent** refers to that term. This "reverse thinking" helps with understanding contextual filters; think of the relationship from the thing you're listing, not from the thing you're displaying the list on. My media has no "Parent Taxon" field; that would have been redundant because terms' parents are inherently defined in the hierarchical vocabulary they belong to. This means we can't just add "Parent Taxon" as another simple contextual filter. So we need to extend the range of database tables that Views can query by adding a relationship:

* ADVANCED \> RELATIONSHIP \> Add \> Select *"Taxonomy term referenced from field\_primary\_taxon"* (Category: Media) \> Add and configure relationships \> Do not select "Require this relationship" \> Apply. This looks at the taxonomy term specified in the media's "Primary Taxon" field and "pulls in" that term's taxonomy information so that Views can query it with our next contextual filter:
* ADVANCED \> CONTEXTUAL FILTERS \> Add. You will see that the list of available filters to choose from is now longer than when we chose the first contextual filter, because of the new relationship.
* Select "Parent term" (Category: Taxonomy term) \> Add and configure contextual filters
* Same as before... WHEN THE FILTER VALUE IS NOT AVAILABLE \> Provide default value \> Type: Taxonomy term ID from URL \> Select (only) "Load default filter from term page" \> Apply.
* OTHER \> Query settings \> Select "Contextual filters OR" \> Apply \> Save. This means results will be listed that pass either the 1st contextual filter OR this 2nd one. Without this, it will filter for media matching both one AND the other, and no results will be displayed.
* Note that after this 2nd contextual filter has been added, the view can no longer be previewed below (I don't know why). So we need to place the block on a page...

**PLACE THE BLOCK ON THE PAGE**

* Go to Structure \> Block layout \> Find appropriate theme(s) (in horizontal sub-menu at the top) and region \> Place block \> Find your new block \> Place block \> De-select "Display title" if you want...
    + We only want our block to show on taxonomy term pages, however in the "Visibility" section there is unfortunately no "Taxonomy term page" listed under "Content type" (I don't know why). So click "Pages" and type `/taxonomy/term/*` in the box \> Save block \> Save blocks (at the bottom). This restriction will be applied before URL aliasing, so don't worry if you have a Pathauto alias set for your taxonomy pages.
    + Visit an appropriate taxonomy term page to check the View works. You may need to refresh the page and/or clear all caches (at `.../admin/config/development/performance`), especially if you haven't disabled caching.

**DISPLAY THIS TERM'S MEDIA BEFORE CHILDREN'S MEDIA**

The default order of display of the media is by the "Authored on" time. To display this term's media before child term's media:

* Install the Views Argument Order Sort module (there's currently only a development version).
* SORT CRITERIA \> Add \> Select "Multi-item Argument Order" \> Add and configure sort criteria \> Apply \> Save. This put this taxon's media before child taxa's media, whether I selected "Sort ascending" or "Sort descending".
* Despite exposing this sort criterion to users to try and allow them to change the sort order, I was unable to get that working. If you know how, please comment.

**FURTHER GROUP MEDIA BY TAXON**

You can group the media by the term they refer to, with headings:

* FIELDS \> Add \> Primary Taxon \> Add and configure fields \> Select "Exclude from display" (not necessary but you can still group by this field even if it is hidden like this) \> De-select "Link label to the referenced entity" (also not essential) \> Apply
* FORMAT \> Format \> Settings \> Grouping field Nr.1 \> Media: Primary Taxon \> Apply \> Save \> Test the view.

**VALIDATION BUG?**

In theory, validating the output of the 2 contextual filters as follows is a good idea:

* Click the contextual filter \> WHEN THE FILTER VALUE IS AVAILABLE OR A DEFAULT IS PROVIDED \> Select "Specify validation criteria" \> Validator: "Media" \> Select only the Media types you wish to show (or none for all of them) \> Select "Validate user has access to the Media" \> Apply \> Save. However, this validation prevents the view from displaying anything. Please comment if you know why, or if you think this is a bug.

**IMPROVEMENT SUGGESTIONS**

* HEADER \> Add \> Result summary. This will give you a summary of results at the top of the block, as is standard on a page display.
* Select ADVANCED \> Other \> "Use AJAX" to reduce page refreshes.
* In some cases a Table view is useful, rather than unformatted list etc., because you can sort the media by field columns if you add extra fields.
* You can add a "Media type" regular filter (not contextual) and expose it to visitors to allow them to show only certain type(s) of media (e.g. Images or videos or both). The Better Exposed Filters module allows the choices to be shown as checkboxes rather than as a drop-down menu, although I have a bug with it (link to follow) at the moment (version 8.x-3.0-alpha3 in Views 8.4.4).
* The Views Infinite Scroll module can make for a nice improvement over standard paging if you have a lot of media.

Here is what my View looks like (with the optional Infinite Scroll and AJAX selected):

I have little Drupal experience, so feel free to suggest refinements to this method.

# Answer
> 0 votes
Just noting this page on drupal.org that mentions this issue, along with two links. One to a core patch and one to a contributed module.

https://www.drupal.org/forum/support/post-installation/2018-02-21/how-to-display-all-media-that-references-a-taxonomy-term

---
Tags: views, 8, taxonomy-terms, media
---


# Question
Title: Within a node template how can I tell what regions are in use/ occupied?
I am trying to create a preprocess function in my .theme file in order to make a variable available to node templates.

I want the variable to contain just the names of all regions that are currently in use (i.e. rendering content).

The idea being, if I have a region called left\_hand\_nav which is rendered on some (not all) pages, and I have a node called generic\_page, from my generic\_page node template I'd like to be able to do:

```
{% if left_hand_nav %}
 do something
{% else %}
 do something else
{% endif %}

```

I am not interested in controlling the rendering of any regions blocks from the node template. Instead for any given page wherein the node is rendered I just want to know if a particular region on said page is in use.

I realize this can very easily be done from a page template but instead of having a kazillion billion conditionals in my page template I'd prefer a few conditionals in several node templates.

If someone could point me in the right direction I'd appreciate it very much.

# Answer
In special case of navigating to a node page (like when viewing an article) you can see that when implementing hook\_preprocess\_page , the $variables does contain a 'node' value, if you add any property to your $variables\['node'\] , you will be able to use it in node.html.twig file

Update

As in hook\_preprocess\_page you can access all regions using $variables\['REGION\_NAME'\] , so that you can check them if they are empty or having content , if they weren't empty you can save their name in an array and then apply that array to $variables\['node'\]
> 1 votes

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


# Question
Title: What is Pages (from D7 and D8) replaced with in D9?
I'm working on a D9 project that we just migrated from D7, but there doesn't exist a `admin > structure > pages` link. What was this replaced with? Same with Panels, I still see Panels as a Content Type, but what about a structure?

All I could find online was "How to create a Basic Page". I want more than a basic page, I want to structure pages together.

# Answer
> 1 votes
The *admin/structure/pages* route is handled by the *Page Manager* module, which is included in the Drupal 7 version of the Chaos Tool Suite (ctools) project.

>

For Drupal 8 and Drupal 9, it's a separate project: the Page Manager project. The route is handled by the *Page Manager UI* module that is part of that project. Installing only the *Page Manager* module doesn't make that route available.

>

---
Tags: migrations, 9
---


# Question
Title: Is there a way to disable the <nolink> option for menu links?
For our unified Drupal platform, we require all of our sites main menu items to be a page and any sub-pages to show a path following the parent menu item. So if "About Us" (with a path of /about-us) is a top level menu item, it must be a page. And the page "History" under that will have a path of /about-us/history. "About Us" cannot be a `<nolink>` with History as a child. How can I prevent users from using the `<nolink>` option for menu links? The core link module includes in the description to the user of how to include the `<nolink>` option. That shows that if it supports internal and external links. Well, I don't want to exclude one of those for menu links in general. I'm thinking I'm going to have to do a form alter, plus some type of validation, but I'm not sure what.

It was added from this issue but they did not do a toggle the way the D7 link contrib module did. And it's a toggle I need - to turn it off in this case.

# Answer
I'd say that I would solve this requirement by doing three things:

1. CSS: easy one, just hide the tooltip about
2. JavaScript: add a client-side validation that checks the value of the link field and if the '' regexp is found, prevent from saving and show a message.
3. hook\_form\_alter and check for instance via route parameters if it has menu\_link\_content and then add your server-side validation.

Also, point 1 could be done as well in the form\_alter by replacing the description there instead of via CSS.
> 1 votes

---
Tags: navigation
---


# Question
Title: How to address the field value in a node from a webform
I'm using Drupal 8 together with the Webform module.
Is there a way to transfer the value of a field in a specific content type to a webform?

This is the situation:
There's a content type called *'Vacature'* where you create the specific content (vacancies). When adding a new vacancy I provide a field called *'vacaturecode'* and a dropdown where you select the application webform that will be used to apply for the vacancy.

The application webform collects all the data of the applicant including two uploads (CV and motivation letter).
For these two upload fields I use the property *'File name pattern'* to rename the original uploaded document to `00_lastname_CV_vacaturecode.pdf` upon submission.

Therefore I use a string of tokens in the *'File name pattern'* property: `[webform_submission:serial]_[webform_submission:values:lastname]_CV_[webform_submission:node:field_vacaturecode:value]`

This works, only I don't get to add the value of the field *'vacaturecode'* that is submitted when creating the content. Instead the syntax is added as value.
I already tried various combinations of the syntax (e.g. `[webform_submission:source-entity:entity:field_vacaturecode:value]`) but I don't get it right.

Is there a way to address this value from within the webform?

Thanks for you help!

# Answer
this sounds like a case for `hook_webform_submission_presave`. You can also see the available hooks here: http://api.drupalhelp.net/api/webform/webform\_hooks.php/group/webform\_hooks/6.3

You'll need to add the hook implementation to your theme or module file.
> 0 votes

---
Tags: webforms
---


# Question
Title: Accessing node value in paragraph twig template
I'm writing a twig template for a paragraph. I'd like to access a text field value from the page/node where this type of paragraph will be added.

Specifically, I'd like to access the value of a text field titled 'field\_runner\_id'. I access this value in my page/node twig template like this:

```
content.field_runner_id|field_value

```

I've tried a handful of techniques (listed below) to access that field value within my paragraph template but am having no success.

How can I refer to a parent page's field value within a paragraph template?

I've found a few posts and articles that address this issue, and am able to get details about the parent node, such as the title and nid but not fields that it contains.

Eg this post: https://mark.ie/blog/printing-values-of-a-parent-node-from-a-drupal-paragraphs-field ...helped me to get the parent page and nid via adding this within my paragraph template:

```
{% set parent = paragraph._referringItem.parent.parent.entity %}
{{ parent.title.value }}
{{ parent.nid.value }}

```

I've also tried these, among others, with no success:

```
{{ parent.content.field_runner_id.value }}
{{ parent.content.field_runner_id[0] }}
{{ parent.content.field_runner_id|field_value }}

```

# Answer
> 4 votes
I think it is easier then you think:

```

{% set parentNode = paragraph.parentEntity %}
<!-- parentNode is already the node object, so now you can access any field directly without going through the content object --->

{{ parentNode.field_runner_id.value }}

```

What will make your live also more easy in general, is to install the devel and devel\_kint\_extras module for development.

Then you can explore the complicated drupal object structure like this and find the right field value:

```
{{kint(parentNode)}}

```

# Answer
> 4 votes
Preface: Do not use that method from that blog, there is a better method.

1. `something._referringItem` is not cache safe, so better not use this inside Twig templates.
2. `something._referringItem` doesn't perform any access checks
3. `paragraph._referringItem.parent.parent.entity` is possibly the longest and most confusing alternative to write `paragraph.parentEntity`

---

So, now the real answer :-)

`paragraph.parentEntity` is returning the raw parent entity object (very similar to the `paragraph` variable) but it does not include a render array like `content`. So you neither need `.content` nore you need `|field_value`.

Instead head directly for the field value `parent.field_on_hostnode.0.value`

---

**More info about variables in entity templates:**

`content` = complete render array of an entity

`content.field_something` = render array of a single field

`content.field_something|field_value` = get raw field value back from a render array (requires "Twig field value" module)

`entity` = raw entity object (replace entity with `node` in node template, `paragraph` in paragraph template, etc).

`entity.field_something.value` = not recommended, will behave differently depending on field type and field cardinality

`entity.field_something.getValue()` = get an array of raw field values, works for all field types and all field cardinalities

`entity.field_something.0.value` = get the first raw data field value (for plaintext fields, numbers, emails, telephone field; will not work with links, images, entity references...)

`entity.field_something.0.name_of_database_column` = get the first raw data subvalue `name_of_database_column` of field\_something (this could be `format` in a formatted text field, `end_value` in a daterange field, `target_id` in a entity reference field,...)

**Entity reference field only:**

*Note that the following methods are not cache-safe, not language-aware and do not perform access checks.*

`entity.field_reference.0.target_id` = get the numeric ID of the first referenced child entity

`entity.field_reference.0.entity` = the first referenced child entity object (no render array!)

`entity.field_reference.0.entity.getTranslation('de')` = get the german translation of the first child object

**Paragraphs only:**

`paragraph.parentEntity` = the direct parent entity object (no render array!)

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


# Question
Title: Send Commit message on Acquia Hook by Slack
Based on Automating with Cloud Hooks I've implemented Slack notification based on Simple Slack Notification Bash Script

```
site="$1"
target_env="$2"
source_branch="$3"
deployed_tag="$4"
repo_url="$5"
repo_type="$6"

FILE=$HOME/slack_settings

if [ -f $FILE ]; then
  # Load the Slack webhook URL (which is not stored in this repo).
  . $HOME/slack_settings

  # Post deployment notice to Slack

  if [ "$source_branch" != "$deployed_tag" ]; then
    curl -X POST --data-urlencode "payload={\"username\": \"Acquia Cloud\", \"text\": \"An updated deployment has been made to *$site.$target_env* using branch *$source_branch* as *$deployed_tag*.\", \"icon_emoji\": \":acquiacloud:\"}" $SLACK_WEBHOOK_URL
  else
    curl -X POST --data-urlencode "payload={\"username\": \"Acquia Cloud\", \"text\": \"An updated deployment has been made to *$site.$target_env* using tag *$deployed_tag*.\", \"icon_emoji\": \":acquiacloud:\"}" $SLACK_WEBHOOK_URL
  fi
else
  echo "File $FILE does not exist."
fi

```

It works correctly, it sends the message,

> An updated deployment has been made to *mysitexxxx.dev* using tag *dev*.

**But What I need is the commit's message,How can I get commit message on Acquia post-code-update?**

# Answer
> 1 votes
The commit message isn't passed in to the script, so you have to get it from somewhere else. I'm not sure if there is a git repository available to the cloud hook scripts on Acquia's cloud servers in general (it seems like there must be, but...I can't find an answer about where it is in their docs). You do have the repository url and the branch/tag, so you could try a shallow clone of the tag to get the data:

`git clone --depth 1 --branch $deployed_tag $repo_url clonedirectory
cd clonedirectory
commit_message=`git show -s --format=%B`
...
echo $commit_message`

You can use the `$commit_message` variable in the slack commands.

Of course...you have to figure out how to authenticate to the git repo and I'm not sure what's a great solution there.

Really I hope someone will reply with the location of a git clone that's available on cloud servers.

# Answer
> 0 votes
Old question but still relevant. Here is a way to implement greggles solution with better performance. It will use the same shallow clone rather than creating one each push / deploy.

ssh into your Acquia server.

Make a git directory under the home directory

cd into it and do the shallow clone into it, e.g.

`git clone --depth 1 --no-single-branch $repo_url $site`

Use your Acquia git URL for the $repo\_url and the site name for the directory (e.g the application short name).

This will be the git clone used for your commit info in the hook.

In the hook script, you can now do something like:

```
cwd=`pwd`
cd $HOME/git/$site
git checkout $source_branch
git pull
commit=`git log -1 --pretty=format:"%h %an%x09%ad%x09%s" --date=format:"%m/%d/%Y %H:%M"`
cd $cwd

```

Add the commit variable to your slack message text.

Notes:

To add a newline in the message use: `\\n` in the string.

Also, the shallow repo may not have all the log info in it, but since we only want the last one that is OK.

If you are worried about disk usage, you should remove and reclone the git repo to cut back its size. Each pull will increase disk usage.

---
Tags: acquia-cloud
---


title: Custom submit handler never gets called

text:
# Question
Title: Custom submit handler never gets called
I want to check a data when an user submits a form. I set a custom submit handler in form alter, but my custom handler function never gets called. I don't understand why.

This is my code :

```
/**
 * Implements hook_form_alter().
 */
function custommodule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
{
    if($form_id == "node_test_form") {
        kint("toto"); //toto is displayed when I load the form page
        $form_state->setSubmitHandlers(array("_custommodule_test"));
    }
}

function _custommodule_test(&$form, \Drupal\Core\Form\FormStateInterface $form_state){
    kint("mwahahaa?"); // never displayed
    die(); // doesn't work, the submit form page loaded successfully
}

```

I cleared cache, but the issue is still there.

## Edit ##

I tested add a validate handler, the problem persists.. The code :

```
/**
 * Implements hook_form_alter().
 */
function custommodule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
{
    if($form_id == "node_test_form") {
        kint("toto"); //toto is displayed when I load the form page
        $form_state->setSubmitHandlers(array("custommodule_myform_mysubmit"));
        $form_state->setValidateHandlers(array("custommodule_myform_myvalidate"));
        $form_state->getSubmitHandlers(); // display array("custommodule_myform_mysubmit")
        $form_state->getValidateHandlers(); // display array("custommodule_myform_myvalidate")
    }
}

function custommodule_myform_mysubmit(&$form, \Drupal\Core\Form\FormStateInterface $form_state){
    kint("submit ?"); // never displayed
    die(); // doesn't work, the submit form page loaded successfully
}

function ccustommodule_myform_myvalidate(&$form, \Drupal\Core\Form\FormStateInterface $form_state){
    kint("Validate ?"); // never displayed
    die(); // doesn't work, the submit form page loaded successfully
}

```

# Answer
validate and submit handlers are added to the corresponding form element, e.g. `$form['actions']['submit']['#submit'][] = 'foo'`. and same for #validate.

Honestly no idea what those methods are used for, never used them. Maybe internally, during form processing.

Also note that the node form currently has multiple submit buttons (save as published, unpublished and so on), so you'd probably need to add your submit to all of those.
> 1 votes

# Answer
In Drupal 8.2 you can used below code inside file mymodule.module

```
function mymodule_form_node_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {

   if($form_id == "node_video_form") {
    foreach (array_keys($form['actions']) as $action) {
        if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
            $form['actions'][$action]['#submit'][] = 'mymodule_video_form_submit';
        }
    }
  }
}

function mymodule_video_form_submit(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {
  drupal_set_message('It works!');
}

```
> 1 votes

# Answer
You could use this foreach function to add the custom submit form to all submit buttons:

```
  // Set a custom submit function
  foreach (array_keys($form['actions']) as $action) {
    if ($action != 'preview' && isset($form['actions'][$action]['#type']) && $form['actions'][$action]['#type'] === 'submit') {
      $form['actions'][$action]['#submit'][] = 'mymodule_custom_submit';
    }
  }

```
> 0 votes

# Answer
kint("submit ?"); // never displayed die(); // doesn't work, the submit form page loaded successfully

If you use "die();" in submit or validate handle, then it will stop script, but will not print any data of form object or any other things which you want to print because it is not a custom form , it is a node form so simply you can use "\Drupal::logger" to store that values in recent log and then verify your required results to visit recen log message area in your Drupal site.

$data = "Any value you want to print here". Use this : \Drupal::logger('YOUR\_module\_name')-\>info($data1);
> 0 votes

---
Tags: 8, forms
---


# Question
Title: How can I print recipient mail address in webform email handler body with twig?
In the webform e-mail handler configuration I can see that `webform` twig variable is available. I looked to the context with xDebug and it looks like I should be able to print e-mail address of the recipient with in the mail body. But it doesn't work, the body is empty. Do you know why and how can I fix this?

```
{{ webform.handlers.e_mail.settings.to_mail }}

```

Edit: I also tried to use token like this:

```
{{ webform_token('[webform:handler:e_mail:settings:to_mail]', webform_submission, [], options) }}

```

,but the token didn't get replaced.

# Answer
> 1 votes
The module maintainer says it's by design: https://www.drupal.org/project/webform/issues/3231110

---
Tags: theming, webforms
---


# Question
Title: PHP Fatal error: Uncaught ArgumentCountError on Drush run
After I updated my site to Drupal 8.9.16 and Drush to 10.5.0 I get the following error `PHP Fatal error: Uncaught ArgumentCountError: Too few arguments to function` when running any Drush command. This only happens on my remote site not on my local site.

The site is still working ok so I was able to clear cache and update the database from the backend of Drupal. I was hoping this would fix the problem but it didn't. I also searched for a solution but none of the topics I found got me the right solution.

Hopefully one of you have a better understanding of what this error means, and can help me fix it.

The full error message is:

```
PHP Fatal error:  Uncaught ArgumentCountError: Too few arguments to function Drush\Application::configureAndRegisterCommands(), 3 passed in /home/user/domains/domain.com/public_html/vendor/drush/drush/src/Runtime/Runtime.php on line 113 and exactly 4 expected in /home/user/domains/domain.com/vendor/drush/drush/src/Application.php:313
Stack trace:
#0 /home/user/domains/domain.com/public_html/vendor/drush/drush/src/Runtime/Runtime.php(113): Drush\Application->configureAndRegisterCommands(Object(Drush\Symfony\DrushArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput), Array)
#1 /home/user/domains/domain.com/public_html/vendor/drush/drush/src/Runtime/Runtime.php(49): Drush\Runtime\Runtime->doRun(Array, Object(Symfony\Component\Console\Output\ConsoleOutput))
#2 /home/user/domains/domain.com/public_html/vendor/drush/drush/drush.php(72): Drush\Runtime\Runtime->run(Array)
#3 /home/user/domains/domain.com/public_html/vendor/drush/drush/drush(4): require('/home/deb in /home/user/domains/domain.com/vendor/drush/drush/src/Application.php on line 313
Fatal error: Uncaught ArgumentCountError: Too few arguments to function Drush\Application::configureAndRegisterCommands(), 3 passed in /home/user/domains/domain.com/public_html/vendor/drush/drush/src/Runtime/Runtime.php on line 113 and exactly 4 expected in /home/user/domains/domain.com/vendor/drush/drush/src/Application.php:313
Stack trace:
#0 /home/user/domains/domain.com/public_html/vendor/drush/drush/src/Runtime/Runtime.php(113): Drush\Application->configureAndRegisterCommands(Object(Drush\Symfony\DrushArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput), Array)
#1 /home/user/domains/domain.com/public_html/vendor/drush/drush/src/Runtime/Runtime.php(49): Drush\Runtime\Runtime->doRun(Array, Object(Symfony\Component\Console\Output\ConsoleOutput))
#2 /home/user/domains/domain.com/public_html/vendor/drush/drush/drush.php(72): Drush\Runtime\Runtime->run(Array)
#3 /home/user/domains/domain.com/public_html/vendor/drush/drush/drush(4): require('/home/deb in /home/user/domains/domain.com/vendor/drush/drush/src/Application.php on line 313

```

# Answer
I had the same problem before and this helped me.

> Drush 10 changed some of its services' definitions and before the composer update Drupal DI container was precached. The next call to drush resulted in a service creation error because a cached container had stale service definition.

> The solution is to clean the cache\_container table (or another place where the container cache is stored) however as was said this brings some discomfort because before using drush deployed somewhere you have to take care of clearing that cache in an automated way. And it can't be drush itself. It can't be something like `drush sqlq "truncate table cache_container"` or `drush sql-connect` and SQL query.

hope to work for you too.
> 0 votes

# Answer
I just had this exact problem. In my case, it was caused by duplicate `vendor` directories after reorganizing the project to follow the recommended project layout.

I had a new `./vendor/` directory in the project root, but I also still had the old `./docroot/vendor/` directory in the document root. (My project is hosted on Acquia; you may need to check for a `./web/vendor/` directory instead.)

To resolve this issue, try deleting the duplicate directory from `./docroot/vendor/` (or `./web/vendor/`), committing the changes to your git repo, and deploying the code change to the upstream environment.

That did it for me!
> 0 votes

---
Tags: 8, drush
---


# Question
Title: Programmatically set latitude and longitude exposed input
I've been using geolocation 8.x-1.12 for a while now. I have a REST route that gets a view with my exposed form and returns the results.

Previously I did:

```
$plugin = \Drupal::service('plugin.manager.geolocation.geocoder');
$geocoder = $plugin->getGeocoder('google_geocoding_api');
$geocode = $geocoder->geocode($zip_code);

$view = Views::getView('local_pharmacies');
$view->setDisplay('block_1');
$exposed = [
  'field_geolocation_proximity-lat' => $geocode['location']['lat'], // No longer exists in 3.x
  'field_geolocation_proximity-lng' => $geocode['location']['lng'], // No longer exists in 3.x
  'field_geolocation_proximity' => "50",
];
$view->setExposedInput($exposed);
$view->preExecute();
$view->execute();

```

I updated to 8.x-3.7 because I plan to upgrade to D9 soon. The above is no longer working. I think because field\_geolocation\_proximity-lat and field\_geolocation\_proximity-lng no longer exist. I tried diving into the source as well as kinting form alters to figure out how to properly set the coordinates but I cannot figure it out. Any ideas?

# Answer
I finally figured out how its supposed to be formatted. Kinting after the view execute rather than before exposed the field names.

```
$exposed = [
  'center' => [
    'coordinates' => [
      'lat' => $geocode['location']['lat'],
      'lng' => $geocode['location']['lng'],
    ],
  ],
  'field_geolocation_proximity' => "50",
];

```
> 2 votes

---
Tags: 8, location
---


# Question
Title: How to print token in webform-confirmation.html.twig?
I would like to output a submitted value as a token on the confirmation page through the twig. The token works just fine when added into the message box of webform as:

```
[webform_submission:values:score_percentage]

```

But I can't seem to get the same value to output through the twig. I have tried:

```
{{ webform_token('webform_submission:values:score_percentage') }}
{{ webform_token('[webform_submission:values:score_percentage]') }}
{{ drupal_token('webform_submission:values:score_percentage') }}
{{ drupal_token('[webform_submission:values:score_percentage]') }}

```

But they all just print the token itself, like:

```
webform_submission:values:score_percentage
[webform_submission:values:score_percentage]
[webform_submission:values:score_percentage]
[[webform_submission:values:score_percentage]]

```

I saw another post about (what I think is) the same thing here? But I haven't been able to see my error...

As well as this old issue, which by the looks of it would be fixed now.

I have the latest versions of Twig Tweak (8.x-2.9) and Token (8.x-1.9) installed. Am I doing something fundamentally wrong here?

# Answer
> 2 votes
For the code that implements `webform_token`, you can check the *src/Twig/WebformTwigExtension.php* file, line 102.

```
public function webformToken($token, EntityInterface $entity = NULL....) {
  // Allow the webform_token function to be tested during validation without
  // a valid entity.
  if (!$entity) {
    return $token;
  }
  // …
}

```

If you do not pass an entity, the string passed in, for example, `{{ webform_token('webform_submission:values:score_percentage') }}` will be returned.

If you look at the *templates/webform-confirmation.html.twig* file, you can see the following variables are available.

* progress: Progress bar
* message: Confirmation message
* back\_url: URL to the previous webform submission

The other available variables can be found on `template_preprocess_webform_confirmation()`.

* webform
* webform\_submission
* source\_entity

It means you can use `{{ webform_submission.data.field_name }}` in the *webform-confirmation.html.twig* file, instead of using tokens as you did.

Try to avoid using Twig extensions in template files. It will make debugging and maintenance easier.

# Answer
> -1 votes
You need to install the Twig Tweak module and use `{{ drupal_token('site:name') }}`.

---
Tags: theming, webforms, tokens
---


# Question
Title: How to add a user role as a body class to the admin theme, Seven?
I need to add a user role class to the body tag in the Seven theme, our admin theme. What is the best way to manage that without touching Seven? Is it even possible?

Ultimately, I'm trying to hide a field element in the Manage Form Display from showing to certain roles so as to avoid confusion for that role, but I want to keep it for Administrators. So I'm open to other options for this.

# Answer
> 1 votes
You can add the class to the body attributes in a hook\_preprocess\_html(). See Add the user role to the body class

Hooks of the front-end theme are not invoked in the back-end and vice versa. You would need to sub-theme Seven if you want to place a custom hook. Or put the preprocess hook in a module. In this case you can check the current theme, if you don't want to add the class to all themes. See Find out which theme is loaded in a given page

This is not the only way to solve the second part of the question and as always Drupal has a lot more. You could for example set #access to FALSE in a form alter hook.

---
Tags: 8, theming
---


title: How to close modal after form submit?

text:
# Question
Title: How to close modal after form submit?
I am building an entity reference widget, which displays the reference link, next to the input field, to the target entity's edit form. I make it to open in a modal, with the following attributes on the link:

```
 'class' => ['use-ajax'],
          'data-dialog-type' => 'modal',
          'data-dialog-options' => json_encode([
            'height' => 700,
            'width' => 900,
          ]),

```

That works perfectly. However when I click submit on the modal form, I got redirected to the referenced entity view page, instead of the modal being closed and stay on the original form, where this widget is being used.

Is there any special attributes (like "data-dialog-type") which tells to the modal form's submit button to close the modal instead of redirecting to the original view?

***UPDATE***

Adding this to the URL actually pretty much solves the problem:

```
    'query' => [
      'destination' => $this->requestStack->getCurrentRequest()->getRequestUri(),
    ],

```

This redirects the to the original page, with the potential values being updated (referenced item title), which is actually a pretty good thing!

That being said, I am still interested in the "ajax submit" version!

# Answer
> 5 votes
You need to implement and use your own EntityEditForm - is this the case ? Then skip to the last code block :D

Otherwise you'll need to accomplish this first. See this answer (Overriding an entity add/edit form through alterroute) for an approach to 'inject' a custom form. Here the crucial code to it (adapted to NodeForm):

**modules/custom/form\_overwrite/form\_overwrite.services.yml**

```
services:
    route_subscriber:
        class: Drupal\form_overwrite\Routing\RouteSubscriber
        tags:
 - {name: event_subscriber }

```

**modules/custom/form\_overwrite/src/Routing/RouteSubscriber.php**

```
 <?php

/**
 * @file
 * Contains \Drupal\form_overwrite\Routing\RouteSubscriber.
 */

namespace Drupal\form_overwrite\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
 * Listens to the dynamic route events.
 */
class RouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  protected function alterRoutes(RouteCollection $collection) {
     if ($route = $collection->get('entity.node.edit_form')) {
  $route->setDefault('_entity_form', '\Drupal\form_overwrite\Form\NewEditForm');
     }

   }
}

```

**modules/custom/form\_overwrite/src/Form/NewEditForm.php**

```
<?php

namespace Drupal\form_overwrite\Form;

use Drupal\node\NodeForm;

/**
 * Form handler for the node edit forms.
 */
class NewEditForm extends NodeForm {}

```

There you make sure the #ajax is set, like:

```
<?php

public function form(array $form, FormStateInterface $form_state) {
   ...
   $form['actions']['DESIRED_EXISTING_ACTION'] = array(
      ...
      '#type' => 'submit',
      '#ajax' => array(
        'callback' => '::ajaxSubmit',
        'event' => 'click',
      ),
      ...
    );
   ...
}

```

and overwrite the ajaxSubmit function, adding the CloseModalDialogCommand, like:

```
public function ajaxSubmit(array &$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();

    if ($form_state->getErrors()) {
      ...
    }
    else {
      ...
      $response->addCommand(new \Drupal\Core\Ajax\CloseModalDialogCommand\CloseModalDialogCommand());
    }

    return $response;
  }

```

# Answer
> 3 votes
I solved this by only using a event subscriber in a custom module.

modalCloseSubscriber.php

```
<?php

namespace Drupal\custom_module\EventSubscriber;

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseDialogCommand;
use Drupal\Core\Session\AccountProxyInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Custom module event subscriber.
 */
class ModalCloseSubscriber implements EventSubscriberInterface {

  /**
   * Current logged in user.
   *
   * @var \Drupal\Core\Session\AccountProxyInterface
   */
  protected $currentUser;

  /**
   * Constructs event subscriber.
   *
   * @param \Drupal\Core\Session\AccountProxyInterface $current_user
   *   Current logged in user.
   */
  public function __construct(AccountProxyInterface $current_user) {
    $this->currentUser = $current_user;
  }

  /**
   * Kernel response event handler.
   *
   * @param \Symfony\Component\HttpKernel\Event\FilterResponseEvent $event
   *   Response event.
   */
  public function onKernelResponse(FilterResponseEvent $event) {
    $response = $event->getResponse();
    if (!$response instanceof AjaxResponse) {
      return;
    }
    if ($response->getCommands()) {
      $commands = $response->getCommands();
      if (empty($commands)) {
        return;
      }
      elseif (!empty($commands)) {
        foreach ($commands as $command) {
          if ($command['command'] == 'insert' && $command['selector'] == '#layout-builder') {
            // leave blank for default modal window to close.
            $response->addCommand(new CloseDialogCommand());
          }
        }
      }
    }

  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return [
      KernelEvents::RESPONSE => ['onKernelResponse'],
    ];
  }

}

```

This closes the modal after i create a block with layout builder.

# Answer
> 0 votes
I achieved it by `hook_form_alter` into the form, check if the current request is an Ajax request and then add a callback to fire the `CloseDialogCommand()`.

```
/**
 * Implements hook_form_alter().
 */
function MYMODULE_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id === 'MY_FORM_ID') {
    $request = \Drupal::request();
    // Check if Ajax request.
    if ($request->isXmlHttpRequest()) {
      $form['actions']['submit']['#ajax']['callback'] = '_MY_MODULE_MY_FORM_submit_ajax_callback';
    }
  }
}

/**
 * Custom Ajax callback.
 */
function _MY_MODULE_MY_FORM_submit_ajax_callback(array &$form, FormStateInterface $form_state) {
  // If form is valid then close the dialog.
  if (!$form_state->hasAnyErrors()) {
    $response = new \Drupal\Core\Ajax\AjaxResponse();
    $response->addCommand(new \Drupal\Core\Ajax\CloseDialogCommand());
    return $response;
  }
  // Otherwise call the default #ajax callback.
  $form_object = $form_state->getFormObject();
  $response = $form_object->submitAjaxForm($form, $form_state) ;
  return $response;
}

```

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


title: hook_schema install, but not uninstall

text:
# Question
Title: hook_schema install, but not uninstall
I can't figure how it is possible that the table I define in a hook\_schema is created when I enable my module, but it isn't deleted when I uninstall the module (after disabling).

Drupal 7 documentation sais that the table should be automatically created and deleted when these events occours.

Here is the relevant part of the code inside `my_module.install`:

```
function my_module_schema(){
    $schema = array();
    $schema["my_module_table_xyz"] = array(
            ...
    );
    return $schema;
}

```

I don't know if it could be related to the difference between the modue name and the table name... or from the code present in the `hook_uninstall`... or something else...

Considering I also define a node type, the `hook_uninstall` should delete it (see following code), then `system` should automatically uninstall previously defined schema.

```
function my_module_uninstall(){
    ...
    node_delete_multiple(...);
    // delete custom fields
    node_type_delete(...);
    field_purge_batch(...);
}

```

What do you think about? Thanks

**NOTE:** I use Drush to disable, uninstall and reinstall the module and I get the error `Table my_module_table_xyz already exist`.

---

**Update:** I just verified that the same code in a clean Drupal installation works as expected (table defined in hook\_schema have been successfully removed).

In the "problematic" Drupal installation I also tried to explicit run `drupal_uninstall_schema("my_module_table_xyz")` at the end of the `hook_uninstall` (and I inserted a log instruction just after that line, to verify it runs without breaking), but nothing change. The table is stille there!

Any idea/hypothesis about will be really appreciated.

# Answer
> 4 votes
I had the same issue and finally I just manually did it in `hook_uninstall()`, I could find no other recourse.

```
function mymodule_uninstall() {
  $table_name = 'mytable';
  if (db_table_exists($table_name)) {
    db_drop_table($table_name);
  }
}

```

Hope this saves someone else some time.

# Answer
> 1 votes
For recent usage in Drupal 8-9, this is the equivalent:

```
function mymodule_uninstall() {

  $table_name = 'mytable';
  $schema = \Drupal\Core\Database\Database::getConnection()
    ->schema();
  if ($schema->tableExists($table_name) ) {
    $schema->dropTable($table_name);
  }

}

```

---
Tags: 7, entities, database
---


# Question
Title: Calling setExposedInput() from a Drush command doesn't have any effect
We have a custom Drush command implemented using the following code.

```
class JobApplicationExportCommands extends DrushCommands {

  /**
   * Exports Dorea Job Applications since the last run to csv
   *
   * @command dummy:job-application-export
   * @aliases duje
   */
  public function drush_dummy_export() {
    $applicationWebformIds = Drupal::entityQuery('webform')
      ->condition('category', 'Bewerbungsformulare')
      ->execute();

    $applicationView = Views::getView('all_applications');
    $applicationView->setDisplay('default');
    $applicationView->setExposedInput([
      'webform_ids' => array_keys($applicationWebformIds),
      'submitted' => '2021-01-01'
    ]);

    $applicationView->execute();

    // This outputs 0, which is wrong.
    print_r(count($applicationView->result));
  }

}

```

The view configuration is the following.

>

If I execute the same logic via a custom controller / normal request, the view does return values.

Am I missing something? Does anybody know why the exposed input of the view is ignored?

# Answer
Alright, a colleague saved me again: The access checks can be dissabled individually per view via Query settings \> Disable SQL rewriting

For this particular view and usecase this is exactly what is needed, as it is only callable by backend processes.
> 0 votes

---
Tags: views, webforms, drush
---


# Question
Title: How can I load an entity's bundle object from a loaded entity?
If I want to get an entity's bundle object, with a node, I can do something like:

```
$bundle_object = \Drupal::entityTypeManager()
  ->getStorage('node_type')
  ->load($node->bundle());

```

But this seems a little long-winded. Is there a way to get the object directly from an entity? Something like `$entity->getBundleObject()`?

# Answer
> 2 votes
The bundle field is a reference field and you can load the bundle object via the field property `entity`:

```
$node_type = $node->type->entity;

```

More generic for any content entity:

```
if ($entity->getEntityType()->hasKey('bundle')) {
  $bundle = $entity->get($entity->getEntityType()->getKey('bundle'))->entity;
}

```

---
Tags: entities
---


title: There is no token table

text:
# Question
Title: There is no token table
I installed the latest Drupal 8 version (8.9.18) on my host with the *Rules* (8.x-3.0-alpha6), the *Token*, and the *Rules Token* modules.

I can't see any table showing the list of the allowed tokens, in the rules action form. I want to use the node title or the node author for the *Send mail* action, but there is no token information or guidance.

I tried to add *\[node:title\]* and *\[node:nid\]* in the mail body, but they aren't replaced with the node title and the node ID.

What's the problem? How can I resolve it?

# Answer
Note: What you refer to as the "token table" is actually a form element (named "token\_tree") that is provided by the contributed Token module. You need the contributed Token module in both Drupal 7 and Drupal 8 if you want to use this form element - it is not part of Token module functionality included in core Drupal 8, you still need the contributed Token module.

That said, Token module tokens are not used by Rules in Drupal 8. Instead, Rules uses typed-data Twig tokens, similar to how Views works. See for example https://www.drupal.org/docs/contributed-modules/d8-rules-essentials/token-replacement and related pages in that documentation guide (which includes many examples of how to use these tokens, how to find out what tokens are available, how to modify token values, etc.)
> 1 votes

---
Tags: 8, rules, tokens
---


# Question
Title: How to get product variation media file url using jsonapi?
I'm using the following jsonapi GET request to retrieve product variations for a product:

```
/jsonapi/commerce_product/default/0ea927c7-b62d-45c9-8bec-dc3d16215276/variations?include=field_images

```

However, the response does not include the file url for the media:

```
{
"type": "media--image",
"id": "6af50149-ae35-4a3b-802d-b21c5d863235",
"links": {
"self": {
"href": "http://myurl/en/jsonapi/media/image/6af50149-ae35-4a3b-802d-b21c5d863235?resourceVersion=id%3A4"
}
},
"attributes": {
"drupal_internal__mid": 4,
"drupal_internal__vid": 4,
"langcode": "en",
"revision_created": "2021-09-03T08:03:04+00:00",
"revision_log_message": null,
"status": true,
"name": "image-940375_1920.jpg",
"created": "2021-09-03T08:02:55+00:00",
"changed": "2021-09-03T08:02:55+00:00",
"default_langcode": true,
"revision_translation_affected": true,
"metatag": null
},
"relationships": {}
},

```

How do I add the media file url to the request?

# Answer
> 2 votes
I figured it out:

```
/variations?include=field_images.field_media_image&fields[file--file]=uri,url

```

---
Tags: commerce, media, uri
---


# Question
Title: Unable to create a custom form tableselect
```
    /**
     * An example controller.
     */
    class GenerateCertificateTable extends ControllerBase {

      /**
       * Returns a render-able array for a test page.
       */
      public function content($nid) {
            $query = \Drupal::database()->select('users_field_data', 'u');
            $query->fields('u', ['uid','name','mail']);
            //For the pagination we need to extend the pagerselectextender and
            //limit in the query
            $pager = $query->extend('Drupal\Core\Database\Query\PagerSelectExtender')->limit(10);
            $results = $pager->execute()->fetchAll();
            // dump($results);
            // Initialize an empty array
            $header = [
                'uid' => t('UID'),
                'mail' => t('mail'),
                'name' => t('Username'),
            ];
            $output = array();
            // Next, loop through the $results array
            foreach ($results as $result) {
             if ($result->uid != 0 && $result->uid != 1) {
                $options[$result->uid] = [
                    'uid' => $result->uid,
                    'mail' => $result->mail,
                    'name' => $result->name,
                ];
             }
           }

           $form['table'] = [
            '#type' => 'table',
            '#header' => $header,
            '#options' => $output,
               '#js_select' => TRUE,
              '#multiple' => TRUE,
              '#required' => TRUE,
            ];
            // Finally add the pager.
            $form['pager'] = array(
              '#type' => 'pager'
            );
       $build[] = $form;
return $build;
 }
}

```

I am trying to create table form using tableselect element but even after I get the data it shows empty data value.

# Answer
You have used wrong array index key for rows output. It should be  `'#rows' => $output` not `'#options' => $output,` .
> 1 votes

---
Tags: 8, forms
---


# Question
Title: Site error on Drupal 9 on Acquia Dev Desktop
```
[Sat Sep 04 15:52:46.939952 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:49930] mod_fcgid: stderr: #21 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\index.php(19): Drupal\\Core\\DrupalKernel->handle(Object(Symfony\\Component\\HttpFoundation\\Request))
[Sat Sep 04 15:52:46.939952 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:49930] mod_fcgid: stderr: #22 {main}
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: ArgumentCountError: Too few arguments to function Drupal\\hello_world\\Logger\\MailLogger::__construct(), 0 passed in C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php on line 257 and exactly 2 expected in C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\modules\\custom\\hello_world\\src\\Logger\\MailLogger.php on line 41 #0 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(257): Drupal\\hello_world\\Logger\\MailLogger->__construct()
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #1 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(171): Drupal\\Component\\DependencyInjection\\Container->createService(Array, 'hello_world.log...')
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #2 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(432): Drupal\\Component\\DependencyInjection\\Container->get('hello_world.log...', 1)
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #3 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(271): Drupal\\Component\\DependencyInjection\\Container->resolveServicesAndParameters(Array)
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #4 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(171): Drupal\\Component\\DependencyInjection\\Container->createService(Array, 'logger.factory')
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #5 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(432): Drupal\\Component\\DependencyInjection\\Container->get('logger.factory', 1)
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #6 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(247): Drupal\\Component\\DependencyInjection\\Container->resolveServicesAndParameters(Array)
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #7 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(171): Drupal\\Component\\DependencyInjection\\Container->createService(Array, 'logger.channel....')
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #8 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(432): Drupal\\Component\\DependencyInjection\\Container->get('logger.channel....', 1)
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #9 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(235): Drupal\\Component\\DependencyInjection\\Container->resolveServicesAndParameters(Array)
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #10 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(171): Drupal\\Component\\DependencyInjection\\Container->createService(Array, 'form_validator')
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #11 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(432): Drupal\\Component\\DependencyInjection\\Container->get('form_validator', 1)
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #12 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(235): Drupal\\Component\\DependencyInjection\\Container->resolveServicesAndParameters(Array)
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #13 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal\\Component\\DependencyInjection\\Container.php(171): Drupal\\Component\\DependencyInjection\\Container->createService(Array, 'form_builder')
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #14 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\lib\\Drupal.php(599): Drupal\\Component\\DependencyInjection\\Container->get('form_builder')
[Sat Sep 04 15:54:08.049773 2021] [fcgid:warn] [pid 8276:tid 4] [client 127.0.0.1:50615] mod_fcgid: stderr: #15 C:\\Users\\jeanp\\Sites\\devdesktop\\drupal-9-project-9.0.3\\core\\modules\\views\\src\\Plugin\\views\\exposed_form\\ExposedFormPluginBase.php(134): Drupal::formBuilder()

```
* The class *MailLogger* has two parameters that are fed in the module's *services.yml* file:

```
hello_world.logger.mail_logger:
    class: Drupal\hello_world\Logger\MailLogger
    arguments: ['@logger.log_message_parser', '@config.factory']
    tags:
      - { name: logger }

```
* I don't understand why the 2 parameters of *MailLogger* are considered missing ?

# Answer
1. Your first point of contact should be the author of that code, who got paid to write that code. That is the person who should be providing the support.
2. Search the internet. If that code is faulty, then there will certainly be a bug report somewhere that reports the same error as you. If you can't find a similar report, chances are the problem is on your end and not with the code.
3. That code seems to be written for Drupal 9.0. That is not the current version of Drupal. If you are using as more current version of Drupal, it's entirely possible that changes to Drupal have caused that code to stop working. Use the version of Drupal that the code was designed for and see if it works there. If it does, then the code needs to be updated.
4. If you have changed the code in any way, like changing the name of the module, then again chances are you've done something wrong. Don't make any changes at all, no matter how trivial, until after you get the code running.
> 1 votes

---
Tags: 9, log-messages, symfony-services
---


# Question
Title: How do I programmatically render a view with contextual filters?
How do I programmatically render a view with contextual filters in Drupal 8?

In Drupal 7, I generally use the following code.

```
$view = views_get_view('test_view'); //test_view is the view machine name
$view->set_display("block"); //block is the view display name
$view->set_arguments($tid); //$tid is the argument to pass
$view->pre_execute();
$view->execute();
$content = $view->render();

```

Is there any alternative way to achieve this in Drupal 8?

# Answer
Basing on the code used by `views_get_view_result()`, I would use the following code, as code equivalent to the one you show in the question.

```
  $args = [$tid];
  $view = Views::getView('test_view');
  if (is_object($view)) {
    $view->setArguments($args);
    $view->setDisplay('block');
    $view->preExecute();
    $view->execute();
    $content = $view->buildRenderable('block', $args);
  }

```
> 47 votes

# Answer
The easiest way to render a view in Drupal 8 is using the render element provided by core: https://api.drupal.org/api/drupal/core%21modules%21views%21src%21Element%21View.php/class/View/8.9.x

```
  $view = [
    '#type' => 'view',
    '#name' => 'test_view',
    '#display_id' => 'block',
    '#arguments' => [$tid],
    '#embed' => TRUE,
  ],

```
> 16 votes

# Answer
```
/**
 * Return the rendered view with contextual filter.
 * @param string $viewId - The view machine name.
 * @param string $displayId - The display machine name.
 * @param array $arguments - The arguments to pass.
 *
 * @return object $result
 */
function getView($viewId, $displayId, array $arguments)
{
    $result = false;
    $view = Views::getView($viewId);

    if (is_object($view)) {
        $view->setDisplay($displayId);
        $view->setArguments($arguments);
        $view->execute();

        // Render the view
        $result = \Drupal::service('renderer')->render($view->render());
    }

    return $result;
}

/**
 * Get json output.
 * @return array $data
 */
function jsonData() {
    $data = [];
    $viewId = 'rest_comments';
    $displayId = 'rest_export_1';
    $arguments = [$nid];

    // Get the view
    $result = getView($viewId, $displayId, $arguments);

    if(is_object($result)) {
        $json = $result->jsonSerialize();
        $data = json_decode($json);
    }

    return $data;
}

/**
 * Get the view object.
 * @return object $view
 */
function view() {
    $viewId = 'rest_comments';
    $displayId = 'rest_export_1';
    $arguments = [$nid];

    // Get the view
    $view = getView($viewId, $displayId, $arguments);

    return $view;
}

```
> 13 votes

# Answer
To get the actual JSON output of the REST Export display you can do something like this:

```
$view = Views::getView('view_id');
$render_array = $view->buildRenderable('display_name', $args);
$rendered = \Drupal::service('renderer')->renderRoot($render_array);
$json_string = $rendered->jsonSerialize();
$json_object = json_decode($rendered);

```
> 5 votes

# Answer
This works almost everywhere I use it:

```
use Drupal\views\Views; // above

$activeContestId = 100;
$view = Views::getView('mymodule_contestants');
$view->setDisplay('block_1');
// contextual relationship filter
$view->setArguments([$activeContestId]);
$view->execute();
$rendered = $view->render();
$output = \Drupal::service('renderer')->render($rendered);

```

Source: Render a view with contextual filters programmatically in Drupal 9
> 2 votes

---
Tags: views, 8
---


# Question
Title: Fill multi-value field from comma separated values in a field
I have data in xml which I want to import into drupal. Which works fine. But one field in the xml is filled with a comma separated list of terms. There is a target field in drupal which is a multi-valued field. I do not need those as a taxonomy, just as multi-value for solr search. I just want to expand the `one,fourty,flower,...` values to fill the multiple-value field.

It absolutely will not work. Any help?

Here is the latest iteration (I tried a lot in the last two days) which fails spectacularly with an error like so:

```
Error: Unsupported operand types in /var/www/dev.diercke.com/web/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php on line 206 #0 /var/www/dev.diercke.com/web/core/modules/migrate/src/MigrateExecutable.php(399): Drupal\migrate\Plugin\migrate\process\SubProcess->transform(Array, Object(Drupal\migrate_tools\MigrateExecutable), Object(Drupal\migrate\Row), 'field_stichwort...')
#1 /var/www/dev.diercke.com/web/core/modules/migrate/src/MigrateExecutable.php(205): Drupal\migrate\MigrateExecutable->processRow(Object(Drupal\migrate\Row))
#2 /var/www/dev.diercke.com/vendor/drush/drush/includes/drush.inc(206): Drupal\migrate\MigrateExecutable->import()
#3 /var/www/dev.diercke.com/vendor/drush/drush/includes/drush.inc(197): drush_call_user_func_array(Array, Array)
#4 /var/www/dev.diercke.com/web/modules/contrib/migrate_tools/src/Commands/MigrateToolsCommands.php(958): drush_op(Array)
#5 [internal function]: Drupal\migrate_tools\Commands\MigrateToolsCommands->executeMigration(Object(Drupal\migrate\Plugin\Migration), 'karte', Array)
#6 /var/www/dev.diercke.com/web/modules/contrib/migrate_tools/src/Commands/MigrateToolsCommands.php(418): array_walk(Array, Array, Array)
#7 [internal function]: Drupal\migrate_tools\Commands\MigrateToolsCommands->import('karte', Array)
#8 /var/www/dev.diercke.com/vendor/consolidation/annotated-command/src/CommandProcessor.php(257): call_user_func_array(Array, Array)
#9 /var/www/dev.diercke.com/vendor/consolidation/annotated-command/src/CommandProcessor.php(212): Consolidation\AnnotatedCommand\CommandProcessor->runCommandCallback(Array, Object(Consolidation\AnnotatedCommand\CommandData))
#10 /var/www/dev.diercke.com/vendor/consolidation/annotated-command/src/CommandProcessor.php(176): Consolidation\AnnotatedCommand\CommandProcessor->validateRunAndAlter(Array, Array, Object(Consolidation\AnnotatedCommand\CommandData))
#11 /var/www/dev.diercke.com/vendor/consolidation/annotated-command/src/AnnotatedCommand.php(311): Consolidation\AnnotatedCommand\CommandProcessor->process(Object(Symfony\Component\Console\Output\ConsoleOutput), Array, Array, Object(Consolidation\AnnotatedCommand\CommandData))
#12 /var/www/dev.diercke.com/vendor/symfony/console/Command/Command.php(255): Consolidation\AnnotatedCommand\AnnotatedCommand->execute(Object(Drush\Symfony\DrushArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#13 /var/www/dev.diercke.com/vendor/symfony/console/Application.php(1027): Symfony\Component\Console\Command\Command->run(Object(Drush\Symfony\DrushArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#14 /var/www/dev.diercke.com/vendor/symfony/console/Application.php(273): Symfony\Component\Console\Application->doRunCommand(Object(Consolidation\AnnotatedCommand\AnnotatedCommand), Object(Drush\Symfony\DrushArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#15 /var/www/dev.diercke.com/vendor/symfony/console/Application.php(149): Symfony\Component\Console\Application->doRun(Object(Drush\Symfony\DrushArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#16 /var/www/dev.diercke.com/vendor/drush/drush/src/Runtime/Runtime.php(118): Symfony\Component\Console\Application->run(Object(Drush\Symfony\DrushArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))
#17 /var/www/dev.diercke.com/vendor/drush/drush/src/Runtime/Runtime.php(48): Drush\Runtime\Runtime->doRun(Array, Object(Symfony\Component\Console\Output\ConsoleOutput))
#18 /var/www/dev.diercke.com/vendor/drush/drush/drush.php(72): Drush\Runtime\Runtime->run(Array)
#19 /var/www/dev.diercke.com/vendor/drush/drush/drush(4): require('/var/www/dev.di...')
#20 {main}
Error: Unsupported operand types in Drupal\migrate\Plugin\migrate\process\SubProcess->transform() (line 206 of /var/www/dev.diercke.com/web/core/modules/migrate/src/Plugin/migrate/process/SubProcess.php).
 [warning] Drush command terminated abnormally.

```

```
...
process:
...
  field_stichworte: tags
  field_stichworte_einzeln:
    - plugin: explode
      source: tags
      limit: 10000
      delimiter: ,
    - plugin: deepen
    - plugin: sub_process
      process:
        field_stichworte_einzeln:
          - plugin: extract
            index:
              - 0
...

```

# Answer
> 2 votes
I found a solution:

```
fields:
    ...
    -
    name: keywords_with_comma
    label: 'keywords'
    selector: keywords
    ...
process:
    ...
    field_keywords_multi:
        - plugin: explode
          delimiter: ','
          source: keywords_with_comma
        - plugin: single_value
        - plugin: multiple_values
    ...

```

---
Tags: migrations, 9
---


# Question
Title: Find value of another field in a fieldformatter
This may be complicated to explain

I have a content type with field\_1, field\_2 etc

field\_1 is a taxonomy reference

field\_2 is a custom field with various sub-values

I have a custom formatter for field\_2 which does all sorts of things to hang the sub-values into the desired output, however, I now have a condition for a certain value of field\_1 which requires a different formatting to happen to field\_2 that is not dependent on the field\_2 values.

I need the formatter to handle this as the field will be required in various output scenarios (custom module, views, XML export) and I don't want to have to build multiple mechanisms for handling the data.

My question therefore is how I can grab field\_1 from within the formatter of field\_2 so that I can apply conditional format logic to it.

I could modify field\_2 to contain a flag to control this formatting, however, there are \> 20K records to add a value to whereas it's 1 additional field in a taxonomy record where there are less than 25 values, it would also allow an editor to set the formatting flag independently of the selected taxonomy and potentially an incorrectly displayed value. I can pass values to the formatter from custom module code, however, this needs to be applied when a "normal" user creates their own view or other brings back the field into a view or page.

Hope this makes sense

# Answer
You can grab the host entity inside your field formatter with `$items->getParent()->getEntity()`, and then query all the other fields, e.g.:

```
class MyCustomFormatter extends FormatterBase {
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $parentEntity = $items->getParent()->getEntity();
    $otherFieldValue = $parentEntity->get('field_foo')->first()->getValue();
    foreach ($items as $delta => $item) {
      $elements[$delta] = your_custom_formatter_logic_here($otherFieldValue);
    }
    return $elements;
  }
}

```

If you are querying other entities in here, don't forget to merge those into `$elements[$delta]['#cache']['tags']`
> 2 votes

---
Tags: 9
---


title: deleting comments in bulk

text:
# Question
Title: deleting comments in bulk
how can I delete all comments at once? I have seen how to do it with nodes and bulkdelete module, How to delete all nodes of a given content type? but am looking at a similar solution for comments.

I am looking for a solution that does not leave any artifacts in the database. Is Views Bulk Operations the best solution?

# Answer
AFAIK, VBO should be able to do the job, but I haven't tried it myself to delete comments.

Another way is to run some code (in a module or in Devel module's 'execute php' block) that gets a list of all queries from the db, builds an array of the comment IDs and passes that array to the comment\_delete\_multiple function. Note that this can take a while to complete (depending on server performance and the number of comments), so you may have work your way around that, for instance by using set\_time\_limit (http://php.net/manual/en/function.set-time-limit.php) or Drupal's batch API.

\[update: see Chris Cohen's answer for example code based on this approach.\]
> 7 votes

# Answer
This is not an alternative answer, more an elaboration on marcvangend's, but I couldn't comment on his answer and leave example code. So the manual approach, using devel's execute code block, would look a bit like:

```

$cids = db_select('comment', 'c')
  ->fields('c', array('cid'))
  ->execute()
  ->fetchCol();

comment_delete_multiple($cids);

```

As marcvangend points out, this is going to be limited to the execution time on your server, so you will need to temporarily raise it if you have a lot of comments. Thanks to manarth and instanceofjamie for the dbtng assistance.
> 7 votes

# Answer
Personally, I'd go for the Views Bulk Operations module.

> This module augments Views by allowing bulk operations to be executed on the displayed rows. It does so by showing a checkbox in front of each node, and adding a select box containing operations that can be applied. Drupal Core or Rules actions can be used.
> 2 votes

# Answer
Honestly when I needed to do this I just did it in the database. You delete the comments, fix the comment statistics and poof, all the comments are gone. I'd avoid doing this if you have modules interacting with the comments in some odd fashion, otherwise its what I'd suggest.

TRUNCATE TABLE comments

UPDATE node\_comment\_statistics SET comment\_count = 0
> 0 votes

# Answer
Some UI Tools You may install the modules below

Views - drupal.org/project/views

Every Drupal site needs, I believe... It generates SQL at the backend and displays results with configurable settings, filters, sorting, paging...etc

VBO - http://drupal.org/project/views\_bulk\_operations To allow bulk operations (i.e. delete comments for this thread)

Administration Views - http://drupal.org/project/admin\_views Take advantages of Views and VBO, replace original contnet, comment, user admin pages by menu\_alter...

1. After enabling above modules, go back to comment admin page
2. Tick select all (**be careful**, ensure you would like to delete all comments...)
3. Select "Delete" and "Submit" (**be careful**, no more confirm button later...)
> 0 votes

# Answer
Achieved deleting about 45,000 comments by using the Backup and Migrate module. In the advanced set up in 'Exclude the data from the following tables' - first press Ctrl key then select comment in the list - (be careful because here the unnecessary cache tables are already selected) - backup - restore from this backed up file. Hurrah!
> 0 votes

# Answer
This answer is similar to an already listed answer but I modified it to prevent an 'out of memory error' for about 27,000 comments. This will take a while to execute depending on the number of comments. Simply truncating the comments table may not be a good idea; it's best to let Drupal handle the deleting of content.

I created a PHP script:

```
$cids = db_select('comment', 'c')
  ->fields('c', array('cid'))
  ->execute()
  ->fetchCol();

foreach($cids as $cid)
{
  comment_delete($cid);
}

```

...then ran the script with Drush

```
drush @my_alias php-script my_script.php

```
> 0 votes

# Answer
I would usually recommend to use VBO to delete comments or nodes in bulk but if you are in a situation when you have hundreds of thousands of comments and you don't have too much time, here is a sql query which will delete all unapproved comments along with all the revisions and data related to those comments which in my case was taking 1.2Gb of space in DB

```
DELETE c, rcb, dcb
FROM
    comment AS c
JOIN field_revision_comment_body AS rcb ON (c.cid = rcb.entity_id)
JOIN field_data_comment_body AS dcb ON (rcb.entity_id = dcb.entity_id)
WHERE
    c. STATUS = 0

```
> 0 votes

# Answer
For anyone who interested in Drupal 8/9 solution you can use built-in drush `entity:delete` command.

```
# delete comments only for specific comment type
drush entity:delete comment --bundle=COMMENT_TYPE

# delete all comments
drush entity:delete comment

```
> 0 votes

# Answer
Enable the PHP filter, and create a basic page with the following code:

```
<?php
  db_query("TRUNCATE TABLE {comment}");
  db_query("UPDATE {node_comment_statistics} SET comment_count = 0");
?>

```
> -2 votes

---
Tags: 7, comments, views
---


# Question
Title: Map profile_id based on previously mapped uid when migrating user profiles from CSV file
I'm trying to migrate users and user profiles to site, where both entities might be already present. In this case I would like to overwrite specified fields and leave others in the original state. I'm trying to map `profile_id` like this:

```
  uid:
    plugin: migration_lookup
    no_stub: true
    # previous user migration
    migration: mayors_users
    # property in the source data
    source: lau
  profile_id:
    plugin: entity_lookup
    entity_type: profile
    bundle: profile
    bundle_key: type
    value_key: uid
    source: '@uid'

```

However, this fails, so `profile_id` is `null`.

Do you happen to know, how can I use entity\_lookup (or another) plugin for this?

EDIT: It looks like this might be a Drupal Core issue. I debugged the code of `EntityLookup.php` plugin and printed the actual DB query generated from the entity query:

```
SELECT base_table.revision_id AS revision_id, base_table.profile_id AS profile_id
FROM profile base_table
         INNER JOIN profile profile ON profile.profile_id = base_table.profile_id
WHERE (profile.uid = '153')
  AND (profile.type = 'profile')

```

This works fine and return following result when used directly against MySQL server:

| revision\_id | profile\_id |
| --- | --- |
| 87 | 87 |

However, `$query->execute()` still returns an empty array. Why?

EDIT: It looks like this might be a bug: https://www.drupal.org/project/migrate\_plus/issues/3230477

# Answer
> 0 votes
In the end, the solution was creating my own migration process plugin, the key part of which is:

```
$statement = \Drupal::database()
  ->select('profile', 'p')
  ->fields('p', ['profile_id'])
  ->condition('p.uid', $value, '0')
  ->execute();
$result = $statement->fetchAllAssoc('profile_id');
return array_keys($result)[0];

```

# Answer
> 1 votes
If I understand your question correctly and it is indeed a bug (so that there is no proper solution to your problem) I can think of at least 2 ways you could work around this.

## 1. hook\_migrate\_prepare\_row / hook\_migrate\_MIGRATION\_ID\_prepare\_row

You could use hook\_migrate\_prepare\_row or hook\_migrate\_MIGRATION\_ID\_prepare\_row to preprocess your source data and fetch the uid and profile id manually, something like this:

```
/**
 * Implements hook_migrate_MIGRATE_ID_prepare_row().
 */
function my_module_migrate_MIGRATE_ID_prepare_row(Row $row, MigrateSourceInterface $source, MigrationInterface $migration) {
  $raw_data = (object) $row->getSource()['raw'];
  // Here the database queries as needed.
  // $uid = \Drupal::database()->select ...
  // $profile_id = \Drupal::database()->select ...
  $row->setSourceProperty('uid', $uid);
  $row->setSourceProperty('profile_id', $profile_id);
}

```

Note that Migrate Plus provides an object-oriented alternative to those hooks: https://www.drupal.org/docs/upgrading-drupal/customize-migrations-when-upgrading-to-drupal-8-or-later#s-migrate-plus-provides-a-prepare-row-event

## 2. Write your own process plugin

There is good documentation on how to write a process plugin on drupal.org: https://www.drupal.org/docs/8/api/migrate-api/migrate-process/writing-a-process-plugin

It basically looks like this:

```
<?php

namespace Drupal\my_module\Plugin\migrate\process;

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

/**
 * Provides a 'ExtractProfileIdFromLau' migrate process plugin.
 *
 * @MigrateProcessPlugin(
 *  id = "extract_profile_id_from_lau"
 * )
 */
class ExtractProfileIdFromLau extends ProcessPluginBase {

  /**
   * {@inheritdoc}
   */
  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
    // Fetch profile id.
    $profile_id = \Drupal::database()->select ...
    return $profile_id;
  }

}

```

And it can be referenced in your migration.yml file under the `process` section, something like this for example:

```
process:
  profile_id:
    -
      plugin: extract_profile_id_from_lau
      source: lau

```

Not quite sure which way would work best for you, but those are the 2 ideas that would come to mind. At least that's how I would try it.

---
Tags: 8, users, migrations
---


# Question
Title: The service "redirect.request subscriber" has a dependency on a non-existent service "path.alias_manager"
While upgrading D8.9 to D9.1 got the below issue. Tired all solution nothing works. Because on this issue site is down and unable to process anything.

> \[php7:notice\] \[pid 26850\] Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: The service "redirect.request\_subscriber" has a dependency on a non-existent service "path.alias\_manager". in /var/www/xxxx/xxxx/xxxx/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php on line 86

Could anyone faced this issue or how to overcome?

# Answer
In Drupal 8.8 `path.alias_manager` was deprecated and in Drupal 9 it was removed. You need to update the Redirect module to a version compatible with Drupal 9.

The current version contains the correct service definition having `path_alias.manager` as dependency:

*modules/contrib/redirect/redirect.services.yml*

```
redirect.request_subscriber:
  class: Drupal\redirect\EventSubscriber\RedirectRequestSubscriber
  arguments: ['@redirect.repository', '@language_manager', '@config.factory', '@path_alias.manager', '@module_handler', '@entity_type.manager', '@redirect.checker', '@router.request_context', '@path_processor_manager']
  tags:
    - { name: event_subscriber }

```
> 0 votes

# Answer
One or more of your modules use "path.alias\_manager" instead of "path\_alias\_manager". It will not necessarily be the Redirect module. Just look for the string "path.alias\_manager" in your files and you will know which module needs updating. In my case it was module Cookiebot. There might be other ones.
> 0 votes

---
Tags: 9, upgrading
---


title: Update.php: Page not found

text:
# Question
Title: Update.php: Page not found
Currently using D7 (specifically the Commerce Kickstart installation profile). When trying to reach update.php, I get a "Page Not Found" error. I also noticed that the url Drupal is trying to reach is /core/update.php.

Has anyone else encountered this?

# Answer
> 4 votes
Do you have the `.htaccess` file from 8.x instead of the one from 7.x?
The directory structure of Drupal core changed from 7.x to 8.x, and 8.x includes additional mod\_rewrite rules to redirect to the changed locations of `update.php` and `install.php`

# Answer
> 1 votes
This type of redirect to `/core/` is likely to originate from a `.htaccess` file from Backdrop or Drupal 8+. The problem can occur even when using the `.htaccess` file from Drupal 7, if the browser has previously seen a Backdrop or D8+ site running at the same URL.

Those `.htaccess` files use a `301` Redirect (permanent redirect) which is remembered by the web browser. In this case it's necessary to clear (or temporarily disable) the cache in the browser, and then try the request again.

---
Tags: 7
---


title: How can I upgrade to core 9?

text:
# Question
Title: How can I upgrade to core 9?
I have Drupal 8.8.\* and I would like to migrate to Drupal 9 using Drush 8. I know, we can use composer however I just wanted to confirm, whether we can do by using Drush command?

I tried using Drush but it's showing no updates available.

```
$ drush pm-update drupal-9.0.0
Update information last refreshed: Thu, 06/11/2020 - 11:42
 Name    Installed Version  Proposed version  Message
 Drupal  8.9.0              8.9.0             Specified version not found

No code updates available.

```

# Answer
> 2 votes
No, you can't. `drush pm-update` has been deprecated for a while. The command is still available in the Drush 8.x branch but in later revisions it only exists as a signpost to inform the user how to move to Composer:

> The pm-updatecode command was removed. Please see `composer update --dry-run` and `composer update`.

Noting that Drush 8 isn't supporting revisions past 8.3.x or 9.x, you should look into upgrading Drush and moving to a Composer-driven upgrade process.

# Answer
> 0 votes
While this not neither bulletproof, here is what I did now to move from Drupal 8 to 9 using composer:

1. make sure you are on the latest drupal 8 version (let's call this d8)
2. verify you meet the d9 server requirements: php min 7.3, mysql min 5.7.8
3. do yourself a favor and make a database backup (I did not out of lazyness)
4. create a new project standard drupal 9 somewhere: `composer create-project drupal/recommended-project d9` (let'S call it d9)
5. use `composer require drupal/module-name-xy` in the new d9 folder for every contrib module the d8 site is using - chances are pretty high, that they are all compatible with 9 already - if not composer will tell you and ideally also some options to fix it
6. optional: if you are not using drush jet: `composer require drush/drush`
7. add `core_version_requirement: ^8 || ^9` to your custom `my-module.info` and `my-theme.info` files
8. override the d8 `composer.json` with the d9 one
9. run `composer update` in the d9 folder - now the main update is happening
10. some files that have been changed by this automatically might need a rollback depending on your local deveopment settings: `web/sites/development.services.yml` and `web/.htaccess` in particular
11. update the DB (I'm using drush): `drush --yes updb`
12. start drupal and check the php error logs - you might encounter a few coding issues in your custom modules and thems, but they should be relatively straight foreward to identify and fix.
13. in the end have a short look to `/admin/reports/status`

Fingers crossed and best of luck!

(feel free to edit and extend this answer to make the best possible upgrade guide out of it)

---
Tags: drush
---


title: Customized email twig templates

text:
# Question
Title: Customized email twig templates
Can anyone tell me if there is a mechanism for creating user registration acceptance / rejection emails from different template files for the default email system ?

In *admin/config/people/accounts*, the **account activation** section seems the correct area for crafting the registration acceptance email. BUT, I don't think anyother section is right for te registration rejection email.

So, I tried to find a means of using twig templates for a various scenarios I am trying to fufil without success. Webforms seems to have this functionality but I need it for the default drupal email system.

# Answer
You want the Easy Email module: https://www.drupal.org/project/easy\_email

It is definitely the best mail solution I've found in all my years of Drupal, allowing for the creation of an on-site editing experience for HTML emails, that can be themed with TWIG templates.
> 1 votes

---
Tags: theming, emails, 9
---


# Question
Title: "The website encountered an unexpected error" when creating contrib and custom folders
My Bootstrap Theme in Drupal is currently in the location *var/www/html/project/themes/bootstrap* on my laptop. However, when I create a new directory- *contrib* (inside the themes directory) and move the *bootstrap* directory into it, I get the 'website encountered error' message. I launch the website via chrome using *.localhost/project*

# Answer
You need to clear the cache after you move thing around. Typically you would do this with Drush from your command line:

```
drush cr

```
> 0 votes

---
Tags: theming
---


# Question
Title: Product Attributes that do not require product variations
I am trying to figure out if it is possible to have product attributes that do not require individual SKUs and do not have to be entered as product variations. My use case is this: We are selling dinners with three different entrees and three different desserts. We do not need to charge different amounts for each combination, but we do need to know how many of each have been ordered. I can make this work by creating a separate product variation for each combination, but is there an easier way??

I have looked at commmerce\_pricing\_attributes and commerce\_option but the project pages for these modules say that they only work with D7.

I am running commerce 8.x-2.24 on version 9.2.4 of Drupal

# Answer
What you're looking for aren't attributes as Drupal Commerce considers them. Using your example as a model, we'd say the "product" being sold is the dinner and the precise entree / dessert selections are customizations or options of the underlying product (a nice dinner : ).

The way to accommodate these is to use order item fields that are exposed to the Add to Cart form. This is a bit simpler in Commerce 2.x, as Drupal core added form modes, so you should find what you ned in the field management interface for your order item type.

If the site sells other kinds of products, bear in mind that you have the freedom to create as many order item types as you need and just need to associate them properly from different product types.
> 0 votes

---
Tags: commerce
---


# Question
Title: How to add conditions to display product variations in Drupal commerce?
In the products page, I want to limit product variations based on user roles. For example, I only want admin to be able to see some of the product variation. I tried to achieve this by adding an extra field in variation and then checking that field in twig template (commerce-product.html.twig). Unfortunately, this method only works with rendered entity and I couldn't use the "add to cart" functionality. Is there a way to run a condition before displaying a product variation (along with the add to cart form)?

# Answer
> 2 votes
I solved this issue by subscribing to ProductEvents::FILTER\_VARIATIONS event. You can write custom condition in your event subscriber. Reference: https://docs.drupalcommerce.org/commerce2/developer-guide/products/displaying-products/add-to-cart-form

---
Tags: 8, commerce
---


title: Token to get the latest revision's URL

text:
# Question
Title: Token to get the latest revision's URL
I am using the Content Moderation and the Workflows modules along with the Workbench Email module to generate email templates. The Workbench Email module uses tokens to create dynamic email templates. We have a requirement to provide the URL of the latest revision inside the email body to the reviewer, to make accessing the latest revision easier.

If I create a node that needs moderation, the /node/NID/latest page doesn't exist; the reviewers will need a link to /node/NID. When the content is already published and gets edited, the link in the email should be /node/NID/latest. If we just provide /node/NID in the URL, it won't show the the latest revision.

Since we can have only one template to handle both of the above conditions, I was looking for a token which could provide me either /node/NID or /node/NID/latest based on whether the content is new or already published.

How can I achieve this?

I am using Drupal 9.1.5.

# Answer
This worked for me: \[node:url:unaliased\]/revisions/\[node:vid\]/view
> 0 votes

# Answer
The token needs to be available in the email? I've not created custom tokens in D8 yet but in d7 We'd make a custom token and the value would be set in the token definition based on condition.
> 0 votes

---
Tags: tokens, 9, workflows, workbench
---


# Question
Title: How disable submit button after call OpenModalDialogCommand in Ajax callback?
I have a block that has a button, when pressing that button an ajax is triggered that shows a popup with the OpenModalDialogCommand event, after closing the popup I want to deactivate the submit button, does anyone know how to do that?

The form

```
    $form['actions']['submit'] = array(
      '#type' => 'submit',
      '#value' => $this->t('Get cupon'),
      '#prefix' => '<div id="cupon_form_wrapper">',
      '#suffix' => '</div>',
      '#attributes' => $results > 0 ? array('disabled' => 'disabled') : [],
      '#ajax' => array(
        'callback' => '::_modal_form_cupon_ajax_submit',
        'event' => 'click'
      ),
    );

```

```
function _modal_form_cupon_ajax_submit(array $form, FormStateInterface &$form_state) {
    $response = new AjaxResponse();
    if ($form_state->getErrors()) {
      unset($form['#prefix']);
      unset($form['#suffix']);
      $form['status_messages'] = [
        '#type' => 'status_messages',
        '#weight' => -10,
      ];
      $response->addCommand(new HtmlCommand('#cupon_form_wrapper', $form));
    }
    else {
      $content = 'Lorem ipsum';
      $title = 'Download';
      $response = new AjaxResponse();
      $response->addCommand(
        new OpenModalDialogCommand(
          $title,
          $content,
          array(
            'width'=>'300'
          )
        ),
        $form
      );
    }

    return $response;
}

```

# Answer
Its as simple as adding an extra Command to your AjaxResponse class.

Something like this should work. Make sure you change the css selector (first argument) so it matches your button (or form).

```
$response->addCommand(new InvokeCommand('.button-selector', 'hide', []));

```
> 0 votes

---
Tags: ajax
---


# Question
Title: How do I check if the site is in maintenance mode?
How do I call `MaintenanceMode::applies(RouteMatchInterface $route_match)` from `hook_theme_suggestions_page()`?

# Answer
From a procedural hook you'll probably need to use something like:

```
use Drupal\Core\Routing\RouteMatch;

...

$maintenance_mode = \Drupal::service('maintenance_mode');
$route_match = RouteMatch::createFromRequest(\Drupal::request());

if ($maintenance_mode->applies($route_match)) {
  // ...
}

```
> 5 votes

# Answer
In case someone needs a different approach to the accepted answer above. I use this to remove status messages when the site is in maintenance mode.

```
$maintenance_mode = \Drupal::state()->get('system.maintenance_mode');
  if (!empty($maintenance_mode)) {
  //use can do other stuff here, but in my case I want to remove status message
   \Drupal::messenger()->deleteByType('status');

  }

```
> 0 votes

---
Tags: maintenance-mode
---