title: How to debug D8 library loading?

text:
# Question
Title: How to debug D8 library loading?
I'm having trouble attaching a library using the new #attached mechanism in Drupal 8. Is there an easy way to debug and see which libraries Drupal is trying to load, and possibly, what goes wrong?

**Motivation**

In a form class, I'm returning a large render array. One of the elements has an `#attached` property:

```
$form['contact'] = array(
    '#type' => 'fieldset',
    '#title' => t('Contact'),
);
$form['contact']['#attached']['library'][] = 'my_module/contact';

```

In file my\_module.libraries.yml:

```
contact:
  version: 1.x
  css:
    theme:
      css/contact.css: {}

```

I'm suspecting that contact.css is either not found, not loaded, or altogether ignored. Therefore I'd like to follow the process in which Drupal loads the library and integrates it into the page.

# Answer
> 6 votes
> How to debug D8 library loading?
> ...Therefore I'd like to follow the process in which Drupal loads the library and integrates it into the page.

There some ways to attach a library (look here to see them), this make a bit hard, the task to create a debug workflow following each process.

> ...which libraries Drupal is trying to load, and possibly, what goes wrong?
> ...Can someone add a general method of how to debug D8 library loading?

Well, there are some ways to see what are attached, I know two options to 'debug'.

**Option 1 (check libraries)**

Use a function to inspect which library was attached in your page.

```
function module_page_attachments_alter(&$page) {
  $array_libraries = $page['#attached']['library']; //Use a breakpoint at this line to see libraries.
}

```

**Attention:** It is not safe to see all libraries, remember, any other module or theme can use this function too (and you don't know which is called for last), said that, use this option just to check libraries of your own module/theme if they are included, if not, you messed up (misspell, attach at wrong place), you need to check your 'attach' code.

**Option 2 (check for files attached in a library)**

First, like pointed by @cilefen, you must turn off CSS and js aggregation in performance config tab.

Then you can check all CSS and js files at your browser.

For CSS is easier, they are organized in `<head>` tag:

All CSS files are grouped in by one `<style>` tag for each type of media. In this screen has three `<style>` group with media 'all', the first is base theme, the second is the core (admin bar stuff), and the last one is my theme. If you expand you will see all files:

For js, there two places, if you specified, you will find at `<head>` tag, if not they are all in end of your `<body>` tag.

Now,
\- if you miss a file, check your library if is really defined your file;
\- if not loaded (4xx, 5xx, responses to a file), check your file location;
\- and make sure that you cleared the cache.

---

To keep on track of my libraries I just follow some rules.

* When theming, I usually avoid add things in `preprocess` or other function, and attach all libraries in twig template.

Using this code:

```
{{ attach_library('theme/library') }}

```
* When creating a module, I just add essential code and always at end of build function and in a top level of `$build` var (just created a standard for me and always follow this rule).

This way is easier to find where is wrong.

**Very important:** Considering that you follow all rules of a .yml file and follow a schema for a library definition, sometimes its just tabs that your text edit insist to use, you indentation is wrong or you misspell something.

# Answer
> 2 votes
I think you want:

`$form['#attached']['library'][] = 'my_module/contact';`

# Answer
> 0 votes
Just adding that my library did not add because my install profile was the same name as my theme. As soon as I updated the profile name, my library was applied globally.

Hopefully that saves people the time I wasted finding that out!

---
Tags: 8
---


# Question
Title: Twig: Display media library reference user image at particular resolution with alt tag (on /user/1231 page)
On our user page (/user/12345) we want to change the profile image field to be a media library reference field instead. I've created for the user object a new field called field\_profile\_image that is an entity reference/media library reference.

In my twig template for this user page I can display the full rendered user image in the default display mode with a bunch of extraneous information by using {{ content.field\_profile\_image }}

What I would like to do is display just the image at 136x156 (a media display mode I've set up), preferably with an alt tag.

I've tried various solutions with or without twig tweak, and am still having trouble showing just the referenced image with an alt tag.

Note that I see a lot of examples for twig tweak have something like {% set media\_uri = node.field\_media|file\_uri %} {% if media\_uri is not null %} {{ media\_uri|image\_style('thumbnail') }} {% endif %}

but node is null since this is not on a node, and replacing node.field\_media with content.field\_profile\_image in the above script doesn't render anything at all.

How can I display a media library image in a particular display mode preferably with alt tag?

# Answer
> 0 votes
> but node is null since this is not on a node

In user template there is `{{ user }}` variable wich holds user entity. So just replace "node" with "user" in your snippets.

---
Tags: theming, media
---


# Question
Title: How to use addTranslation() on an entity's multi-value paragraph?
I'm trying to programmatically update a multivalue paragraph field and add a translation. In the code below **field\_product\_description** is the paragraph's field that I'm updating and **field\_images\_descriptions** is the node's field that references the paragraph. The code only updates the first iteration (\[0\]) of the paragraph. How can I also update the other paragraph values?

```
<?php
                  $lang_node->field_images_descriptions->entity
              ->addTranslation($lang_code, [
                  // field_product_description is a multi-value field
                  // how can I update it's other values
                  'field_product_description' => $desc1,
              ])->save();
    ?>

```

SOLVED: Working code:

```
<?php

foreach ($lang_node->field_images_descriptions as $delta => $item) {

          $item->entity->addTranslation($lang_code, [
              'field_product_description' => $desc1[$delta],
          ])->save();
        }

        $lang_node->save();

```

# Answer
You have to loop over the multi-value field:

```
foreach ($lang_node->field_images_descriptions as $delta => $item) {
  $item->entity->addTranslation($lang_code, [
    'field_product_description' => $desc[$delta],
  ]);
}

$lang_node->save();

```
> 1 votes

---
Tags: i18n-l10n
---


title: Send mail to author of content

text:
# Question
Title: Send mail to author of content
I use **Drupal 9.1.4**., core **Contact module**, **Contact email** module and **Contact storage** module.

How to use the author as a referenced entity to send email to author of content (in this case autor of article) when submiting simple Contact module form?

Thanks, Tom.

# Answer
Users already have a personal contact form if you enable the contact form for users.

This way, you can place the link to the user's personal contact form, and then the email will automatically be sent to the author.
> 0 votes

---
Tags: forms
---


title: Create a file field programmatically

text:
# Question
Title: Create a file field programmatically
In a module I am working on, I'd like to create a file field. I am baffed why I can't find any proper documentation on that.

```
$fields['fid'] = BaseFieldDefinition::create('file')
  ->setLabel('Image')
  ->setSettings([

```

... so what settings are available? What can I do with a field of type file? How do paths work under Drupal, what about permissions... Is there somewhere a proper, complete documentation for these things?

# Answer
The settings depend on the field type, widget and formatter plugins you use, which can be core, contrib or custom. These plugins usually don't have documentation, but they provide the options in UI. So the easiest way would be to configure the field in UI, export the config and then transfer YAML to PHP array syntax of the base field definition. Most times a better approach, though, is to keep the field in configuration and install it as module default config.
> 1 votes

---
Tags: 8
---


# Question
Title: Place custom block on particular content type pages and home page
I have a custom block which I want to place on all the pages of one content type AND on the home page. The home page is a custom twig file that pulls in the region where the block is placed. Right now I have the custom block limited to the content type I want but of course that precludes being able to put it on the home page. Is there an elegant way to get it in both places? I'm also using Twig Tweak if that will help.

(Worst case I'll duplicate the block content and put it right into the twig file but I'm trying to avoid that.)

Thanks!

# Answer
> 0 votes
You can create two instances of the block on the manage blocks page. One instance can be limited to the content types on which you want it shown, and the other instance can be limited by path, which you will then set to `<front>`.

---
Tags: blocks
---


# Question
Title: How can I update a map to display view results with an exposed filter?
I want to use a view to render locations on a map, and dynamically update the map when a user filters the locations.

I have a view that displays a list of "Location" content types. That view exposes a "county" filter so that users can filter down to the Location's county. But this view is only able render the location text, and what I want is the locations rendered on a map.

How can I render a map that displays the locations, and updates when the user changes the county filter?

>

# Answer
> 1 votes
Check out the Geofield Maps module (https://www.drupal.org/project/geofield\_map). You should then duplicate your Locations List View into a new view and change the display to be "Map". This will show markers for each of those locations. If desired you can then place that new Map View in the HEADER area of your above Locations List View (to get it placed where you mentioned in the picture).

In regards to the county filter, make sure the same filter exists in the new Map View also, then hide it with css. Now when you update the County filter, both the Map and List views will be filtered appropriately.

There's obviously a bit more nuance to setting up the Geofield Map view, but this should point you in the right direction.

---
Tags: 8, views, google-maps
---


# Question
Title: Force an image to display as block (not inline)
I have a field of type image that I would like to display in a column alone, with all following content displaying beneath, even if the image width is narrower than the width of the display.

Even when using the layout builder, the following content always flows inline with the image. The image is in a block in a single column section. The following content is in a two-column section. Instead of a single column showing the image followed by two columns with other content, the resulting display appears as three columns: Image of 1st section, 1st column of 2nd section, then 2nd column of 2nd section all in a single row.

Drupal version: 9.1.4

Any assistance in solving this?

# Answer
This looks to be a CSS issue, not a Drupal issue. Leverage "display:block" and "min-width:100%" on whichever wrapper div you want to stay on top. But you'll need some CSS massaging and experimenting to get it working as you need.
> 0 votes

---
Tags: blocks, 9
---


# Question
Title: How can I fix this error and upload files?
I have a simple form with just a field to upload a file on a Drupal 8 site using the Webform module 6.0.1. If I test the form using webforms test tool, the file gets uploaded fine, it displays the loading icon for couple seconds and its ready to upload, but if I try the same in a page with the form embedded as a block, I can not upload the file it will always show me the following message if I try to submit the form, no matter how long I wait.

```
"File upload in progress. Uploaded file may be lost. Do you want to continue?"

```

Just for testing, I increased the max upload file to 2GB and the file I'm uploading is just 5kb. All the .js libraries I can think of are on my template.info.yml file. (core/drupal, core/jquery, core/drupal.ajax) The private folder has been set up in my settings.php and has the permissions set correctly the .htaccess file is also set as recommended for Drupal. I have try to upload the files in the public folder just as desperation but I get the same error

Any help will be appreciate.

# Answer
I figure out what the problem was. I'm posting the solution for my case just in case someone has the same problem. My problem was that I had change the submit button ID in the input.html.twig file. I replaced it to the original and it works fine.
> 1 votes

---
Tags: 8, files, webforms
---


# Question
Title: Render published content or comments on new created content using a link
I was looking without luck for a way to be able to make a link or button with the functionality of making a new content showing some content or comment already posted above, something like the Retweet option to be more clear.

Is there a module or combination of modules to achieve this?

Edit:

Now after an answer I know it is easily rendered with a reference field, all I need now is a way to create a link that will auto fill the reference field. That way the user clicking the link never see the field, my idea is that that field is not visible in 'Manage form display'.

Edit 2:

Prepopulate module do the desired link. If I disable the field on 'Manage form display' it stop working. So I used Popup field group

As I told in the comments, this module makes a Popup with only desired fields, but instead doing it, no Popup is opened and the form is rendered with all the fields except the ones supposed to appear on the Popup, so I use the module to get my reference field only on the Popup group and that way this field disappear on create or edit content. Because I am solving this taking advantage of a module that did not do correctly what it should do, if someone thinks that this solution is not a safe way to do it let me know other way to achieve it.

# Answer
You can use an Entity Reference field. In Drupal, most of the "content" that you see, including nodes and comments, are entities.

Entities can be linked to each other with an Entity Reference field.

Here's a tutorial video.

One challenge when working with Entity Reference is that each field can only reference one type of entity-- so you can have an Entity Reference field for nodes, or for comments, but not both at the same time; to have both, you need two fields.

Out of the box, Entity Reference can be configured to select the content by autocomplete or by a select list, which can be the output of a view you have customized, so it's quite flexible.
> 1 votes

---
Tags: nodes, comments, 9
---


# Question
Title: Combine photos from parent node and referenced nodes into a single list (for slideshow)
Drupal 8

I have two content types. Department and Employee.

Department has an entity reference field that references Employee(s).

Department and Employee both have a field called “field\_photos”. (Same field name in both).

In views (or via Twig in a node template), I’d like to display all “field photos” from both the Department Node AND Employee(s) nodes referenced by that Department… into a single list output.

So the end output will be a slideshow for each department showing all “field\_photos” from that Department and referenced Employees.

# Answer
As always there is more than one way of solving problems in Drupal. There is a way you could build a DB query with only Views that would combine the ER reference through Relationships.

But there is a way to solve this that is (arguably) "more Drupal", and that with the help of Content View Modes. They are not to be confused with Views module, we will actually combine the two separate features, View modes and Views (module), to build your solution.

## Use View Modes on ER Fields in Views

View modes are different combinations of entity fields visibility and output settings. With View modes you can create many different "views" of the same content. For example, "Full" and "Teaser" are ubiquitous View Modes.

In your case you want a special View Mode of the Employee CT that shows their photos. Create a new View mode on the `Structure > Display modes > View modes` (you can also get to this page through each CT "Manage display" page).

Enable that mode, visit it (it becomes a sub-tab) and disable all Fields you don't need, configure the photos field to your liking.

In Views create a list of all Departments, add the Photos and Employees ER Fields.

When configuring the Employees field set the Formatter to the View mode you had created especially for this. ER fields usually only show ID of the referenced entities, exceptionally their titles, but with View modes you can pull any info from the referenced item.

This is how you get a list of all Departments with all the Department and referenced Employees photos listed.

## Slideshow

The slideshow part of the Q depends on how you plan to build that in. You'll probably use some external library with a module that implements it into Views.

Depending on how a particular library and module work you will be able to apply it to each Views row, or to each Field.

To combine photos from both fields use the `Exclude from display` on the top field and `Rewrite results` on the bottom field. Use `Replacement patterns` to construct the HTML output that your slideshow library can use. In some cases you'll need to override with twig templates.
> 2 votes

---
Tags: 8
---


# Question
Title: How do I integrate third-party payment gateways?
I need to integrate third-party payment gateways like Razorpay, Payu with Drupal 8 Webform.

Is there any way to achieve this?

# Answer
> 1 votes
I don't think there's a module available for Drupal 8. Payment for Webform existed for Drupal 7 but it is no longer being developed.

Instead, I would look at Drupal Commerce if you need a full-featured solution to handle lots of options.

If your needs are more simple and you just need to embed a form and take payment, there are several non-Drupal solutions that you can integrate into Drupal the same as any other CMS (like Wordpress).

---
Tags: 8, webforms, payment-gateways
---


# Question
Title: Change the cardinallity ratio of a an already existing field from 1 to unlimited
I've created a webform with a text field which has cardinality of 1 and there are submissions made for that webform. I now want to change the cardinality to unlimited, but I can't do it in the webform UI. I'm not able to change the value.

This is the tootltip shown when I hover over the *Allowed number of values* field in webform form element settings Allowed number of values field.

> There is data for this element in the database. This setting can no longer be changed.

>

>

I tried to programmatically change it using `hook_form_alter()`.

```
function mymodule_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'form_id') {
    $form['field_name']['cardinality']['#default_value'] = FIELD_CARDINALITY_UNLIMITED;
  }
}

```

That didn't work either. Where am I going wrong?

# Answer
It is possible to change an element with a singular cardinality via the YAML source without any data loss. You would definitely lose data going from multiple cardinality to singular.

In the YAML source, add the `'#multiple': true` property to the element.

```
name:
  '#type': textfield
  '#title': 'Name'
  '#multiple': true

```
> 3 votes

---
Tags: 8, webforms
---


# Question
Title: Node edit form with embedded form not executing custom submit handler
I'm porting a module that currently works with Blocks/BlockForms to Paragraphs/NodeForms. I'm inserting an embedded form inside a Paragraph inside a Node Edit page using a `hook_field_widget_entity_reference_paragraphs_form_alter`. The general structure where the form gets inserted is:

```
$form['field']['widget'][0]['settings'][form here]

```

After this the form displays as expected on the node edit page.

The inserted form goes through a number of `#process` steps. The element in question is a select form that when the button underneath it is pressed, is supposed to retrieve some data via a custom submit handler and place it on the page with ajax:

The array for this element looks like this:

You can see the custom submit handler that is supposed to fire when 'Select Segment Set' is pressed

After debugging, I've found that the entire NodeForm appears to be submitted to the backend, and the only handler that is found is from some other field that uses ajax. In short 'updateSegmentSet' is never discovered as a submit handler. When I debug the original module based on block/blockforms, I do see the correct submit handler being discovered. Now in the latter case, of course a blockForm is submitted to the back end with the correct plugin. Given that this is basically a form within a form within a form, is there something special I have to do to get the custom submit handler to run? I've read a few things online e.g. the 'settings' key and '#tree' = true.

**EDIT**

The Ajax property looks like this:

```
      '#ajax' => [
        'callback' => [$this, 'updateSegmentSetAjax'],
        'wrapper' => $wrapper_id,
      ],

  public function updateSegmentSetAjax(array &$form, FormStateInterface $form_state) {
    $button = $form_state->getTriggeringElement();
    // Go one level up in the form, to the widgets container.
    return NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -2));
  }

```

As best I can tell, this is never called either.

# Answer
> 0 votes
I came across https://www.drupal.org/forum/support/module-development-and-code-questions/2015-09-03/put-a-custom-form-inside-node-form which, while old, claims that what I wanted to do is not possible. To get this to function the way I wanted I:

* Attached a JS event handler to the embedded form submit buttons that performed .preventDefault()
* This handler then .ajax'd a custom route that I created.
* In the Controller for that route, I had to perform all the primary operations for submitting the form and return markup back to the .ajax call.

---
Tags: 8, forms, paragraphs
---


# Question
Title: Fire custom submit handler in form embedded in node edit form
I have a form that is being inserted inside of a node edit form and the inserted form is given a custom submit handler. The inserted form's submit button is defined as follows:

```
    $form['decision_select']['update'] = [
      '#type' => 'submit',
      '#value' => $this->t('Select Segment Set'),
      '#submit' => [[$this, 'updateSegmentSet']],
      '#limit_validation_errors' => [],
      '#ajax' => [
        'callback' => [$this, 'updateSegmentSetAjax'],
        'wrapper' => $wrapper_id,
      ],
    ];

```

However, when I click 'Select Segment Set' the entire node form is submitted to the backend (I've verified this by printing the request/route objects sent to the backend). Is there any way to press that submit button and have only the inserted form sent to the backend along with this custom submit handler? The idea is to have this inserted form filled with values given to it via ajax before the node form is ever submitted to save the node.

# Answer
I came across https://www.drupal.org/forum/support/module-development-and-code-questions/2015-09-03/put-a-custom-form-inside-node-form which, while old, claims that what I wanted to do is not possible. To get this to function the way I wanted I:

* Attached a JS event handler to the embedded form submit buttons that performed .preventDefault()
* This handler then .ajax'd a custom route that I created.
* In the Controller for that route, I had to perform all the primary operations for submitting the form and return markup back to the .ajax call.
> 0 votes

---
Tags: 8, forms
---


title: Unable to uninstall a module

text:
# Question
Title: Unable to uninstall a module
When I try to uninstall the "Commerce license" module, the following error appears :

> drupal module:uninstall commerce\_license

```
[ERROR] SQLSTATE[42S02]: Base table or view not found: 1146 Table
         'www.domaine.com.mg433jdr_commerce_license__license_role' doesn't exist: UPDATE
         {commerce_license__license_role} SET deleted=:db_update_placeholder_0
         WHERE bundle = :db_condition_placeholder_0; Array
         (
             [:db_update_placeholder_0] => 1
             [:db_condition_placeholder_0] => role
         )

```

I do not know what to do. How to uninstall this module ?

Thank you

# Answer
> 1 votes
The solution for this, is a quite similar response for this question: Manually disable a module take a look. Hope that helps.

# Answer
> 0 votes
Where condition occurs, once you know no other module would be effected, after a DB backup, you may fix this simply temporarily skipping validation with

```
  public function validate($module) {

    return ;

```

inside `web/core/modules/field/src/FieldUninstallValidator.php`

Once your module is uninstalled, remove that `return;` absolutely crucial for an healthy site.

# Answer
> -1 votes
Uninstall module using drush with the command:
drush pmu commerce\_license -y

---
Tags: 8, database, console
---


# Question
Title: How to implement stateless authentication
I'm having a big problem with Drupal 8, I want Drupal to trust a downstream reverse proxy that performs authentication against a third party provider, then passes a JWT in a `X_ID_TOKEN` header.

As I didn't find any module that behaves as an authentication provider that trusts HTTP headers to authenticate the user, I developed a provider myself which is implemented as follows:

```
public function applies(Request $request) {
  // If you return TRUE and the method Authentication logic fails,
  // you will get out from Drupal navigation if you are logged in.
  $trusted_host = "127.0.0.1";
  $headers = $request->server->getHeaders();
  $server_addr = $request->server->get('SERVER_ADDR');
  return ($server_addr == $trusted_host) && $headers && $headers['X_ID_TOKEN'];
}

public function authenticate(Request $request) {
  $headers = $request->server->getHeaders();
  $jwt_token = explode('.', $headers['X_ID_TOKEN']);
  $user_data = json_decode(base64_decode($jwt_token[1]), true);
  if(!$user_data && !$user_data['email']){
    return NULL;
  }
  $users = \Drupal::entityTypeManager()->getStorage('user')
    ->loadByProperties(['mail' => $user_data['email']]);
  $user = reset($users);
  if ($user) {
    $uid = $user->id();
    $rids = $user->getRoles();
    $account = User::load($uid);
    return $account;
  }else{
    /** @var \Drupal\user\Entity\User $account */
    $account = User::create([
      'name' => $this->generate_username($user_data),
      'pass' => user_password(),
      'mail' => $user_data['email'],
      'init' => $user_data['email'],
      'status' => 1,
    ]);
    $account->save();
    // Store the newly created account.
    $this->save_user_info($account, $user_data);
    return $account;
  }
  return NULL;
}

```

Then the service is registered like this:

```
services:
  authentication.trust_openid_auth:
    class: Drupal\trust_openid_auth\Authentication\Provider\OpenIDAuth
    tags:
      - { name: authentication_provider, provider_id: open_idauth, priority: 0, global: TRUE }

```

This sort of works, but the pages we are rendering contain user personal data, and they are being cached by some Drupal internal cache. This cache is "per user" thanks to the native Drupal session cookie.

Problem: this cookie seems to be randomly set (when it's not there it randomly appears when navigating). When the session cookie is not set, the cache is global and results in rendering a page that contains the personal information of the last user that successfully rendered the page (not necessarily the current user!)

I have read that the session cookie starts existing when data is attached to the PHP session, which I'm not in control of.

I'm pretty lost at this point, the two solution I thought of are:

* Tell Drupal to trust a remote Cookie (set by the downstream reverse proxy) as the session Cookie, this cookie would contain the user's JWT
* Force the Drupal session Cookie even if there is no data attached to the session, just to contextualize the cache

The first solution would be ideal but I'm not sure how to achieve it. Any help on this would be welcome!

# Answer
> 0 votes
For some reason the Internal Page Cache module, which is supposed to "cache pages for anonymous users" kicks in **before** the authentication provider. I don't know why this module considers that a user is anonymous even before the authentication provider had a chance to do anything. Anyway, my solution was to disable this module.

# Answer
> 0 votes
If you tag this as middleware and weight it in your service definition, you can control when this runs. If you search through core you will find the Session and Page Cache also run as middleware. The Ban module in core is also tagged as middleware.

Hopefully this will help point you in the right direction.

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


# Question
Title: How can I restrict external URLs in link field to allow only certain domains?
After creating a Link field and use the Link with service icon format, I find out that there is no option to restrict external URLs to external domains that I want

For example, if I only want to allow Twitter links, something like add `https://www.twitter.com/*`.

Someone already asked here, but it seems that the Advanced Link module is not available for my Drupal version.

With what module and how can I filter my desired URLs in Drupal 9?

# Answer
There is a now a new module on drupal.org: Link Allowed Hosts – Will be working on this during the week so next week we can finally restrict the allowed hosts for link fields.
> 4 votes

# Answer
You need to write your own custom validation contraint and add this constraint to your field.

Docs: https://www.drupal.org/docs/drupal-apis/entity-api/entity-validation-api/providing-a-custom-validation-constraint

I've used that example to create a "force HTTPS" link field constraint

`src/Plugin/Validation/Constraint/Https.php`

```
<?php

namespace Drupal\MYMODULE\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;

/**
 * Checks that the submitted URL is starting with https://
 *
 * @Constraint(
 *   id = "MY_CONSTRAINT_ID",
 *   label = @Translation("Https", context = "Validation"),
 *   type = "string"
 * )
 */
class Https extends Constraint {
  public $notHttps = '%uri is not a secure site (not starting with https://)';
}

```

`src/Plugin/Validation/Constraint/HttpsValidator.php`

```
<?php

namespace Drupal\MYMODULE\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Validates the Https constraint.
 */
class HttpsValidator extends ConstraintValidator {

  /**
   * {@inheritdoc}
   */
  public function validate($items, Constraint $constraint) {
    $item = $items->first();
    if (!isset($item)) {
      return NULL;
    }

    foreach ($items as $item) {
      /* CHANGE THIS, e.g. here you can check for domain names */
      if (strpos($item->uri, 'https://') !== 0) {
        $this->context->addViolation($constraint->notHttps, ['%uri' => $item->uri]);
      }
    }
  }
}

```

`MYMODULE.module`

```
<?php

use Drupal\Core\Entity\EntityTypeInterface;

function MYMODULE_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) {
  if ($bundle === 'MY_ENTITY_BUNDLE' && $entity_type->id() == 'MY_ENTITY_TYPE') {
    if (isset($fields['MY_FIELD'])) {
      $fields['MY_FIELD']->addConstraint('MY_CONSTRAINT_ID', []);
    }
  }
}

```
> 4 votes

# Answer
A module exists with that capability, perhaps try https://www.drupal.org/sandbox/wombatbuddy/3183996
> 0 votes

---
Tags: uri, 9
---


# Question
Title: How to display a node edit form in custom URL
I have a node created (using Default content) as part of the site install and it is available to edit at `node/[nid]/edit`. However, this node holds some of the site-specific content (for example, content to display on sitewide banner) and should be available under the site configuration section instead of `node/[nid]/edit` so that I can restrict the edit access with specific permission.

Why not the configuration/settings form? Because the node type has rich fields like image upload, entity reference, etc, and would be nice to use the node/entity's field API and display modes.

Is there a way to get the edit page of **just** this node at `/admin/config/system/banner-settings`?

# Answer
Create a new menu item in a custom module

```
# mymodule.routing.yml

mymodule.banner_settings_form:
  path: /admin/config/system/banner-settings/{node}
  defaults:
    _entity_form: node.edit
    # Copy UUID from exported default content.
    node: 05d6a9e5-6e78-42bb-b3fe-b9a6344f4022
  requirements:
    _entity_access: node.update
    # Custom permission check.
    _permission: 'administer site banner configuration'
  options:
    _admin_route: true
    _node_operation_route: true
    parameters:
      node:
        type: 'entity:node'
        # Part of jsonapi module.
        converter: paramconverter.jsonapi.entity_uuid

```

Visiting `/admin/config/system/banner-settings` would take the default UUID value from the route and renders the form.

P.S: After saving the form it would redirect back to `node/[nid]` and this can be avoided by passing `?destination=<your path>` in the link.
> 1 votes

---
Tags: 8, nodes
---


# Question
Title: Removing HTML rendered for Block Regions
In my custom Drupal 8 theme, for all regions of my page, there is HTML looking like:

```
<div class="block-region-xxxx"></div>

```

where xxxx is the region name.

There are also empty 's rendered around my blocks.

This is my `block.html.twig`

```
{% block content %}
    {{ content }}
{% endblock %}

```

as you see, no divs there.

Here's my theme.info.yml , region part:

```
regions:
  header: Header
  hero: Hero
  help: Help
  top: 'Page Top'
  content: Content
  sub: 'Sub Content'
  bottom: 'Page Bottom'
  footer: Footer

```

Here's a screenshot of the actual HTML tree rendered:

essentially I'd like to remove everything between the .row and the .col..

# Answer
> 1 votes
This may help some one else who is having this issue.

So how to remove the extra black divs inside a region you would do the following:

Find "core/modules/system/templates/region.html.twig"

Change it from this –

```
{#
/**
 * @file
 * Default theme implementation to display a region.
 *
 * Available variables:
 * - content: The content for this region, typically blocks.
 * - attributes: HTML attributes for the region <div>.
 * - region: The name of the region variable as defined in the theme's
 *   .info.yml file.
 *
 * @see template_preprocess_region()
 *
 * @ingroup themeable
 */
#}
{% if content %}
  <div{{ attributes }}>
    {{ content }}
  </div>
{% endif %}

```

To this –

```
{#
/**
 * @file
 * Default theme implementation to display a region.
 *
 * Available variables:
 * - content: The content for this region, typically blocks.
 * - attributes: HTML attributes for the region <div>.
 * - region: The name of the region variable as defined in the theme's
 *   .info.yml file.
 *
 * @see template_preprocess_region()
 *
 * @ingroup themeable
 */
#}
{% if content %}
    {{ content }}
{% endif %}

```

---
Tags: theming
---


title: Is there a database lock mechanism?

text:
# Question
Title: Is there a database lock mechanism?
I have a parent child entity relationship which is driven by a REST API. The payload contains data for both the parent and the child. The parent can have many children.

When the (child) payload is posted the API first checks if the parent exists (based solely on an ID value in the payload). If it does exist, that parent entity is assigned to an entityref field when the child entity is created. If the parent doesn't exist; it is created and the newly created parent is assigned to the child.

This works great.. until. It seems now that the API user is publishing multiple children with the same parent at the same time (I assume some sort of multi-threaded process). So the breakdown occurs when the first 2 children are created (at the "same time") and they both determine there is no existing parent; and then create duplicate parents.

Is there some Drupal db method that allows me to lock creation of a certain entity type; triggered by the first spot in the API code where the parent is to be created? I assume they are not exactly the same time; but they are within 1 second of each other and more precisely they are within the time it takes to create the first parent. Perhaps even a REST function to handle threaded calls?

# Answer
> 0 votes
Does not sound like a multi-threading issue to me?

If you have two childs having the the same new parent in the entity reference field (BTW, what approach do use for creation, this is rather tricky ..), it will be probably created "twice", but with different ids - no?

Why don't you create the parent entity first and assign it afterwards to the entity-reference field target\_id or entity property (if you are controlling it yourself)?

---
Tags: database, 8
---


title: Error when importing the configuration

text:
# Question
Title: Error when importing the configuration
We have several sites running with Drupal.
On my local machine I run the test versions of each site in the Docker container to add new features or test new ones.

When switching between pages I do the following.
Shut down the container of page-A.
Change to the directory of page-B, start the container.
Then execute the following commands in the terminal in the container:

```
composer clearcache
composer install
drush sql-drop --yes;
drush sqlc < page-B_init.sql
drush updb
drush cim

```

When running **drush cim**, the following error message appears:

```
 [error]  Drupal\Core\Config\ConfigImporterException: There were errors validating the config synchronization.
Entity type mismatch on rename.  not equal to configurable_language for existing configuration system.site and staged configuration language.entity.en.
Rename operation for simple configuration. Existing configuration system.site and staged configuration language.entity.en. in Drupal\Core\Config\ConfigImporter->validate() (line 755 of /var/www/html/docroot/core/lib/Drupal/Core/Config/ConfigImporter.php).

In ConfigImportCommands.php line 261:

  The import failed due to the following reasons:
  Entity type mismatch on rename.  not equal to configurable_language for existing configuration system.site and staged configuration language.entity.en.
  Rename operation for simple configuration. Existing configuration system.site and staged configuration language.entity.en.

```

I suspect the problem is with the UUID, which I have in the files:

```
environments/_default/config/sync/system.site.yml
environments/_default/config/sync/language.entity.en.yml

```

adapted.
But I don't know any further.
Does anyone have an idea where the error lies?

Use Drupal 8.9.13

# Answer
> 1 votes
This might not be the best way, but I had this same issue today. I ended up renaming language.entity.en.yml to include .OLD at the end of the filename for a backup, then I re-ran drush cim. After that it accepted my system.site.yml file. Then I took a look at the language.entity.en.yml file and for some reason it had the exact same UUID as the system.site file. I suspect the import is confused about which file is which because they both had the same UUID.

---
Tags: 8, configuration, importing-exporting
---


# Question
Title: Migration doesn't work when executed with cron
I've set up a migration between 2 Drupal sites hosted on the same server (Drupal 8 -\> Drupal 9). I'm using migration support recently added to drush to run these commands. I've created a helper bash script, which contains:

```
#!/bin/bash
sites=(<mysite>)
for site in "${sites[@]}"; do
  drush -r /var/www/drupal -l $site mim <migration_id> --update --execute-dependencies >> /home/<myuser>/migration.log
done

```

This works fine, when I execute this script manually. However, it doesn't work (content isn't migrated), when it's executed by cron, defined like this:

```
0,5,10,15,20,25,30,35,40,45,50,55 * * * * /home/<myuser>/<myscript>.sh >> /home/<myuser>/migration.log

```

There's no output in the log and no errors in `/var/log/syslog`, where can I only see output like this every 5 minutes:

```
Feb 16 15:35:01 <hostname> CRON[22314]: (<myuser>) CMD (/home/<myuser>/<myscript>.sh >> /home/<myuser>/migration.log)

```

What can I do to debug this issue and resolve it?

# Answer
It seems that the path to drush was wrong when the script was running by cron. Lesson learned - I should be using full paths when working with cron.
> 0 votes

---
Tags: migrations
---


title: Debug arrays from hook_cron?

text:
# Question
Title: Debug arrays from hook_cron?
Does anybody know of the proper way to debug objects from within hook\_cron? I'm trying to set up a task that periodically deletes backups from my private folder, but I can't properly debug arrays that I define in my module. I've tried both the object log and devel debug log modules, but neither of them are properly working for me at the moment, so I feel completely stuck on how to access the information I need.

I've tried running kint() directly, but I'm assuming that doesn't work because it's not running on a page load but in the middle of the cron task.

EDIT: Ended up solving this particular piece of the issue, but am having errors doing some of the deletion as addressed in another issue.

# Answer
I ended up using Ultimate Cron to run my specific cron task on demand, but used a method other than `kint()` to print my info. I ended up setting my info to a variable `$folders` and using the following to print the information in a text file: `file_put_contents("$private_path/folders.txt", print_r($folders, true))`
> 1 votes

# Answer
You might want to try a module like Ultimate Cron that allows you to run individual cron jobs, outside of `cron.php`. This will allow you to use `kint()` and see the output.
> 2 votes

# Answer
It is possible to log an array in dblog :

```
Drupal::logger('my_cron_task')->notice('<pre><code>' . print_r($myArray, TRUE) . '</code></pre>');

```

---

Other way is to debug with cli, so in your hook\_cron() you print your array ...

```
print_r($myArray);

```

... then you launch your cron task from your cli with drush :

```
drush cron

```
> 1 votes

# Answer
`echo` are displayed with `drush` on `hook_cron`.

A quick but not complete solution could be to echo flat array using this way. It could do the trick depending of your need.
> 0 votes

---
Tags: 8, debugging, cron, log-messages
---


# Question
Title: How to insert a custom form into views header?
I have a custom form and I want to insert it into a views header. What is the Drupal 8 way to do it?

# Answer
> 2 votes
Thanks to @NoSssweat pointing me to views area plugins, here's how you insert a custom form into a views header (or any other views area).

### 1. Create the form

**my\_module/src/Form/MyModuleCustomForm.php**

```
namespace Drupal\my_module\Form;

use Drupal\Core\Form\FormBase;

class MyModuleCustomForm extends FormBase {
  // Skipping the class content here
  // @see https://api.drupal.org/api/drupal/core!core.api.php/group/form_api/
}

```

### 2. Create the views area plugin

**my\_module/src/Plugin/views/area/MyModuleCustomArea.php**

```
namespace Drupal\my_module\Plugin\views\area;

use Drupal\Core\Form\FormBuilderInterface;
use Drupal\views\Plugin\views\area\AreaPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\my_module\Form\MyModuleCustomForm;

/**
 * My module's custom form area handler.
 *
 * @ingroup views_area_handlers
 *
 * @ViewsArea("my_module_custom_area")
 */
class MyModuleCustomArea extends AreaPluginBase {
  /**
   * @var \Drupal\Core\Form\FormBuilderInterface
   */
  protected $formBuilder;

  public function __construct(array $configuration, $plugin_id, $plugin_definition, FormBuilderInterface $formBuilder) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->formBuilder = $formBuilder;
  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($configuration, $plugin_id, $plugin_definition, $container->get('form_builder'));
  }

  /**
   * @inheritDoc
   */
  public function render($empty = FALSE) {
    return $this->formBuilder->getForm(MyModuleCustomForm::class);
  }
}

```

Here it is important to have the `@ViewsArea()` annotation over the class name, and we'll describe the area id (`my_module_custom_area` in our example) in that annotation to Views in the next step.

### 3. Describe the views area plugin to Views.

**my\_module.views.inc**

```
/**
 * Implements hook_views_data().
 */
function my_module_views_data() {
  $data['views']['my_module_custom_area'] = [
    'title' => 'My module custom form',
    'help' => 'Provides a custom form for my module.',
    'area' => [
      'id' => 'my_module_custom_area',
    ],
  ];

  return $data;
}

```

### 4. Clear the caches

And done.

---
Tags: 8, views, forms
---


# Question
Title: How can I disable "Delete the account and its content"?
On the *Cancel account* page, is it possible to disable the option "Delete the account and its content"?

Some roles have the permission to cancel user accounts, but they should not have the option to delete the user's content.

# Answer
You can implement `hook_form_alter()` in a custom module or theme to either remove the radio button entirely, or disable it which grays it out. You'd need to add additional logic to check the role of the user and disable it appropriately. I've shown both examples in the code example below, just uncomment the one you want to use.

```
function mymodule_form_alter(&$form, &$form_state, $form_id) {
  if ($form['#id'] == 'user-multiple-cancel-confirm') {
    // Set '#access' to FALSE to remove the radio button.
    // $form['user_cancel_method']['user_cancel_delete']['#access'] = FALSE;

    // Set '#disabled' to TRUE to disable the radio button.
    // $form['user_cancel_method']['user_cancel_delete']['#disabled'] = TRUE;
  }
}

```
> 3 votes

# Answer
There are two routes to deleting a user in the admin UI. Vincent's example handles deleting a user from the People list. The following code also handles clicking the 'Cancel account' button on the user's profile edit form:

```
function mymodule_form_alter(&$form, &$form_state, $form_id) {

  /* Debug...
    file_put_contents(
      $_SERVER["DOCUMENT_ROOT"]."/sites/default/files/debug.log",
      "mymodule_form_alter()...form_id: ".$form_id."\nform: [\n".print_r($form, TRUE)."]\n\n-----------------------\n\n",
      FILE_APPEND
    );
  */

  switch ($form_id) {

    case 'user_cancel_confirm_form':
    case 'user_multiple_cancel_confirm':
    //
    // Only full Administrator accounts can delete user *and* their content...
    // Disable the cancel account options, apart from 'Delete the account and make its content belong to the Anonymous user.'
    //
    if (!user_access('administer modules'))  {
        //
        // Set '#disabled' to TRUE to disable the radio button.  (Still need to change the default value - see below)
        $form['user_cancel_method']['user_cancel_block']['#disabled'] = TRUE;
        $form['user_cancel_method']['user_cancel_block_unpublish']['#disabled'] = TRUE;
        $form['user_cancel_method']['user_cancel_delete']['#disabled'] = TRUE;

        // Set '#access' to FALSE to remove the radio button.  (Still need to change the default value - see below)
//        $form['user_cancel_method']['user_cancel_block']['#access'] = FALSE;
//        $form['user_cancel_method']['user_cancel_block_unpublish']['#access'] = FALSE;
//        $form['user_cancel_method']['user_cancel_delete']['#access'] = FALSE;
    }
    // For everyone, change the default radio button...
    $form['user_cancel_method']['user_cancel_block']['#default_value'] = 'user_cancel_reassign';
    $form['user_cancel_method']['user_cancel_block_unpublish']['#default_value'] = 'user_cancel_reassign';
    $form['user_cancel_method']['user_cancel_delete']['#default_value'] = 'user_cancel_reassign';
    $form['user_cancel_method']['user_cancel_reassign']['#default_value'] = 'user_cancel_reassign';
    break;

  }
}

```

Thanks again Vincent and hope this helps someone.
> 1 votes

---
Tags: 7, users
---


# Question
Title: How can I create a download link to a private file?
I have a views page that is only accessible by a certain user role. This user role also has permission to "view private files" and to "document: download any files" (coming from File Entity Module). The views page displays a table of all private .pdf files that lie in the private file directory and I would like to add a column to this table, using a Views PHP field (at least for prototyping), that displays the corresponding download link next to the file name. As mentioned above, any user that can view the table also has permission to view private files and to download documents, so this should be doable and not be a security issue.

For now, let's assume I always want to display the download link to a *fixed* private .pdf file, say with file id `$fid=17`. According to Working with files in Drupal,

> once configured, files stored in the private directory are inaccessible via a direct link; however, if Drupal constructs a link to the file, the file will be accessible to anyone who can see the link.

What precisely is meant by "if Drupal constructs a link to the file"? I have read many times that `file_create_url()` will create a direct link that, if the user has access to view private files, will take the user to the private file. So I tried in my Views PHP field as output code

```
<?php
$fid = 17;
$file = file_load($fid);
$uri = $file->uri;
$url = file_create_url($uri);
print l(t('Link'), $url);
?>

```

and the link gets displayed as it should (with reference to mysite.com/system/files/Name\_Of\_Private\_File\_17.pdf). But even though the user has permission to view and download private document files, clicking on the link will result in an "Access denied. You are not authorized to access this page."

Can anyone tell me the correct workaround?

# Answer
When I add the field 'File: Download link' to the view it works fine.

The views field handler for the 'File: Download link' has this snippet to check access:

```
if (!file_entity_access('download', $file)) {
   return;
}

```

and this snippet to construct the uri for the download link:

```
$uri = file_entity_download_uri($file);

```

The code for file\_entity\_download\_uri():

```
function file_entity_download_uri($file) {
  $uri = array(
    'path' => "file/{$file->fid}/download",
    'options' => array(),
  );
  if (!variable_get('file_entity_allow_insecure_download', FALSE)) {
    $uri['options']['query']['token'] = file_entity_get_download_token($file);
  }
  return $uri;
}

```

show the download token being added to the options query key of $uri which is returned.

Adding that to the PHP code field:

```
<?php
    $fid = $row->fid;
    $file = file_load($fid);
    if (file_entity_access('download', $file)) {
        $uri = file_entity_download_uri($file);
        print l(t('Download'), $uri['path'], array('query' => $uri['options']['query']));
    }
?>

```

results in a download link to the private file.
> 4 votes

# Answer
## Drupal 8

I needed to do this in Drupal 8. And then did it the same like I found it in `file_preprocess_file_link` in core. Doing it like that makes it agnostic, no matter if public or private file. You get the link.

```
use Drupal\Core\Link;
use Drupal\Core\Url;

$mime_type = $file->getMimeType();
$file_size = $file->getSize();
$file_name = $file->getFilename();
$options = [
  'attributes' => [
    'type' => $mime_type . '; length=' . $file_size,
    'title' => $file_name,
  ],
];
$url = $file->createFileUrl(FALSE);

$build['#link'] = Link::fromTextAndUrl(t('Download'), Url::fromUri($url, $options))->toRenderable();

```
> 1 votes

---
Tags: files
---


title: How to properly add inline Javascript?

text:
# Question
Title: How to properly add inline Javascript?
Now that `drupal_add_js(...., 'inline')` is no longer possible, how can I inject dynamic Javascript from a custom module's Controller? (I'm trying to upgrade a D6 module with as little refactorings as possible)

# Answer
> 3 votes
You can approach it a number of ways. You can add it to the #attached property in hook\_preprocess\_page or hook\_preprocess\_X. You can add it as a library in the #attached property of the array being returned for that request by the controller.

You will need to define some library definitions, as well.

See: https://www.drupal.org/node/2169605 and https://www.drupal.org/developing/api/8/assets

# Answer
> 5 votes
I found a slightly easier way that might help folks. I used this on a Drupal 9 site recently.

```
/**
* Implements hook_page_attachments().
*/
function mymodule_page_attachments(array &$attachments) {

  $useful = "Javascript could really use this";
  $js =  'console.log("i am here");window.usefulInfo = '. '"' . $useful . '"';
  $attachments['#attached']['html_head'][] = [
    [
      '#tag' => 'script',
      '#attributes' => [
        'type' => 'text/javascript',
      ],
      '#value' => $js,
    ],
    'key_for_this_snippet',
  ];
}

```

# Answer
> 4 votes
If you want *inline* javascript in order to pass some computed variables, then it seems that the only way to do it in D8 is to use a combination of `drupalSettings` and an attached library. The following snippets are copied from Attaching configurable JavaScript in the official docs.

In `mymodule.libraries.yml`, declare a library containing your javascript file, with a dependency on `drupalSettings` (and on `jQuery`):

```
cuddly-slider:
  version: 1.x
  js:
    js/cuddly-slider.js: {}
  dependencies:
    - core/jquery
    - core/drupalSettings

```

Then, when building (or altering) your render array, attach the library and save something to the settings:

```
$build['#attached']['library'][] = 'fluffiness/cuddly-slider';
$build['#attached']['drupalSettings']['fluffiness']['cuddlySlider']['foo'] = 'bar';

```

Presumably, you have something more interesting than `'bar'`. Finally, access the setting in your javascript file as `drupalSettings.fluffiness.cuddlySlider.foo`.

# Answer
> 3 votes
In some cases you would really want to add a snippet somewhere inside your code, inside *script* tags. This is how you do it: Let's say you want the snippet inside a controller. Create a custom module and add a file named **google\_snippet.routing.yml** with this content:

```
google_snippet.page:
  path: '/my-custom-path'
  defaults:
    _title: 'Here is my snippet'
    _controller: '\Drupal\google_snippet\Controller\snippetPage::render'
  requirements:
    _permission: 'access content'

```

Also add a file **google\_snippet.module** file to make the controller aware of a template file:

```
function google_snippet_theme($existing, $type, $theme, $path) {
  return [
    'google_snippet' => [
      'variables' => [
        'snippet' => NULL
      ],
    ],
  ];
}

```

Create a file in **src/Controller/** named **snippetPage.php**.

```
namespace Drupal\google_snippet\Controller;
use Drupal\Core\Controller\ControllerBase;

class snippetPage extends ControllerBase {
  public static function render() {
    return [
      '#theme' => 'google_snippet',
      '#snippet' => '
         <script>
          INSERT YOUR SNIPPET HERE
        </script>
      ',
    ];
  }
}

```

Then, inside a templates folder of your module a file named **google-snippet.html.twig** with the following content:

```
{{ snippet|raw }}

```

# Answer
> 2 votes
Ended up with something in the middle. Problem is: Without the template my JS code will end up escaped with HMTL entities.

```
/**
 * @file css_color_variables_ie11/css_color_variables_ie11.module
 */

/**
 * Implements hook_theme().
 */
function css_color_variables_ie11_theme($existing, $type, $theme, $path) {
  return [
    'css_color_variables_ie11' => [
      'variables' => [
        'script_source' => NULL
      ],
    ],
  ];
}

/**
 * Implements hook_page_attachments_alter().
 */
function css_color_variables_ie11_page_attachments_alter(array &$page) {

  // [...]

  $page['#attached']['html_head'][] = [
    [
      '#theme' => 'css_color_variables_ie11',
      '#script_source' => $sourcePath,
      '#tag' => 'script',
    ],
    'css_color_variables_ie11',
  ];
}

```

```
/*! ie11CustomProperties.js v4.1.0 | MIT License | https://git.io/fjXMN */
window.MSInputMethodContext && document.documentMode && document.write('<script src="{{ script_source }}"><\x2fscript>');

```

*css\_color\_variables\_ie11/templates/css-color-variables-ie11.html.twig*

**Result (HTML source)**

```
<script>/*! ie11CustomProperties.js v4.1.0 | MIT License | https://git.io/fjXMN */
window.MSInputMethodContext && document.documentMode && document.write('<script src="https://cdn.jsdelivr.net/gh/nuxodin/ie11CustomProperties@4.1.0/ie11CustomProperties.min.js"><\x2fscript>');
</script>

```

---
Tags: 8, javascript
---


# Question
Title: How do I manage breadcrumbs when the node uses multiple vocabularies?
I have a blog in Drupal 8 and it uses the *Categories* vocabulary to display breadcrumbs as *Home \> Blog \> \[Category\] \> Post title*.

I added taxonomies from the *Tags* vocabulary, which means every post can have one category, and multiple tags. Since I added the *Tags* vocabulary, it has taken over the breadcrumbs on individual blog posts, which are now *Home \> Blog \> \[Tag\] \> Post title*.

Is it possible to control which vocabulary should have priority when it comes to displaying breadcrumbs? Is it possible to control which vocabulary is displayed on blog posts based on where the user came from? For example, if the user is on the individual Tag page (*Home \> Blog \> \[Tag\]*) and clicks on a blog post belonging to that tag, the blog post should display the breadcrumbs using the *Tags* vocabulary (*Home \> Blog \> \[Tag\] \> Post title*). However, if the user is on the individual *Category* page (*Home \> Blog \> \[Category\]*) and clicks on a blog post belonging to that category, the blog post should display the breadcrumbs using the *Category* vocabulary (*Home \> Blog \> \[Category\] \> Post title*).

# Answer
Here's a solution that worked for me.

```
function [YOUR-MODULE-NAME]_system_breadcrumb_alter(\Drupal\Core\Breadcrumb\Breadcrumb &$breadcrumb, \Drupal\Core\Routing\RouteMatchInterface $route_match, array $context) {

  // Control Blog Post Breadcrumb Taxonomy Trail
  $blogPostBreadcrumb = new BlogPostBreadcrumb();
  $blogPostBreadcrumb->alter($breadcrumb);
}

use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Entity\EntityBase;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Url;
use Drupal\node\Entity\Node;
use Drupal\taxonomy\Entity\Term;
use Exception;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class BlogPostBreadcrumb
 *
 * The purpose of this class is to control Blog post breadcrumbs, as described here:
 *
 * RULE 1:
 * When the user is on the Tag page (Home > Blog > Tag) and clicks on a blog post, the blog post breadcrumbs will
 * display: Home > Blog > [Tag Name] > Blog Post Title
 *
 * RULE 2:
 * When the user is on the Category page (Home > Blog > Category) and clicks on a blog post, the blog post breadcrumbs
 * will display: Home > Blog > [Category Name] > Blog Post Title
 *
 * RULE 3:
 * When the user loads the blog post directly (i.e. Home > Blog, or comes from other sources unrelated to
 * Category or Tag), the blog post breadcrumbs should default to Category:
 * Home > Blog > [Category Name] > Blog Post Title
 *
 */
class BlogPostBreadcrumb
{
  /**
   * @param Breadcrumb $breadcrumb
   */
  public function alter(Breadcrumb &$breadcrumb): void
  {
    try {
      // current node
      $current_node = $this->currentNode();

      // nothing found, nothing to do
      if (empty($current_node)) {
        return;
      }

      // what is the current content type
      $content_type = $this->getField($current_node, 'type');

      // apply rule only to blog_post content type, otherwise let's stop the madness right here
      if ($content_type !== 'blog_post') {
        return;
      }

      // determine if the tag can be extracted from referrer. If not, default it to college_tag
      $altered_breadcrumb = $this->getTaxonomyLabelAndUrlByReferrer()
        ?? $this->getTaxonomyLabelAndUrlByCollege($current_node);

      // nothing matched - just let it be. Display blog_tags rather than nothing.
      if (empty($altered_breadcrumb)) {
        return;
      }

      // modify existing breadcrumb list by replacing the third link with proper tag
      // (Home > Blog > [college_tag/blog_tag] > Blog Title)
      $breadcrumb->getLinks()[2]->setText($altered_breadcrumb['label']);
      $breadcrumb->getLinks()[2]->setUrl($altered_breadcrumb['url']);

      // we have to disable caching, otherwise whichever taxonomy opens first, it will get cached!
      // load menu_link_content entity
      $entity =  \Drupal::entityTypeManager()
        ->getStorage('menu_link_content')
        ->load($current_node->getEntityTypeId());
      // disable caching
      $breadcrumb->addCacheableDependency($entity);
    } catch (Exception $e) {
      // if any exception is thrown, we don't want to stop the page from loading.
      // Worse case scenario, it will load blog_tags into breadcrumbs.
    }

  }

  /**
   * Get Field from node
   * Helper method for retrieving field value from given node.
   *
   * @param EntityInterface $node
   * @param string $fieldName
   * @return mixed|null
   */
  protected function getField(EntityInterface $node, string $fieldName)
  {
    return $node->get($fieldName)->getValue()[0]['target_id'] ?? null;
  }

  /**
   * Load node from current url
   *
   * @return EntityBase|null
   */
  protected function currentNode():? EntityBase
  {
    if ($nid = \Drupal::routeMatch()->getParameter('node')) {
      return Node::load($nid->id()) ?? null;
    }
    return null;
  }

  /**
   * Determine Taxonomy Breadcrumb Label and Url by referrer
   * We want to display Breadcrumb category depending from where the user is coming from:
   * Blog College (category) or Blog tag page
   *
   * @return array|null
   */
  protected function getTaxonomyLabelAndUrlByReferrer():? array
  {
    // capture referrer the "Drupal way"
    $route_parameters = $this->referrer();

    // if type is not a taxonomy term, it's not used to us
    if (empty($route_parameters['taxonomy_term'])) {
      return null;
    }

    // load node (taxonomy term)
    $term = Term::load($route_parameters['taxonomy_term']);

    // get taxonomy type
    $taxonomy = $this->getField($term, 'vid');

    // check if taxonomy belongs to college_tags or blog_tags
    if (empty($taxonomy) && !in_array($taxonomy, ['college_tags', 'blog_tags'])) {
      return null;
    }

    // if we can't find the url or the label
    if (empty($term->url() || empty($term->label()))) {
      return null;
    }

    return [
      'label' => $term->label(),
      'url' => Url::fromUserInput($term->url())
    ];
  }

  /**
   * Determine Taxonomy Breadcrumb Label and Url by college
   * This method will be used when referrer page doesn't exist, or the referrer is not Blog Category or Blog Tag page
   *
   * @param EntityInterface $node
   * @return array|null
   */
  protected function getTaxonomyLabelAndUrlByCollege(EntityInterface $node):? array
  {
    // blog can have one college tag (category)
    $taxonomy_id = $this->getField($node, 'field_college');
    $term = Term::load($taxonomy_id);

    // if we can't find the url or the label
    if (empty($term->url() || empty($term->label()))) {
      return null;
    }

    return [
      'label' => $term->label(),
      'url' => Url::fromUserInput($term->url())
    ];
  }

  /**
   * Referrer node
   * Load referrer node the "drupal way"
   *
   * @return mixed
   */
  protected function referrer()
  {
    // this would be college_tag or blog_tag page
    $previousUrl = \Drupal::request()->server->get('HTTP_REFERER');
    // fake the request to previous page, so we can get more info
    $fake_request = Request::create($previousUrl);
    // build url object.
    $url_object = \Drupal::service('path.validator')->getUrlIfValid($fake_request->getRequestUri());
    if ($url_object) {
      return $url_object->getRouteParameters();
    } else {
      return null;
    }
  }
}

```
> 0 votes

---
Tags: nodes, taxonomy-terms, breadcrumbs
---


# Question
Title: What is the significance of dumping the tablespaces?
While recently running `drush sql-dump` on a server where there were never any error messages, I have started to get:

> mysqldump: Error: 'Access denied; you need (at least one of) the PROCESS privilege(s) for this operation' when trying to dump tablespaces

It still produces a file I can import locally and I don't seem to be having any problems. But I am still curious: What *is* the significance of dumping the tablespaces when it comes to the average Drupal sysadmin?

**Environment**

* Drush: Drush Commandline Tool 10.3.2
* Drupal: 8.9.13
* DB: Server version: 5.7.31-34-log Percona Server (GPL), Release '34', Revision '2e68637'
* Acquia Cloud hosted

# Answer
Tablespaces are used to define the physical file location of one (or more) tables - chances are if you were using them for something beyond the default innodb space, you'd know about it. It's likely safe to ignore.

The error will have started when MySQL was updated to 5.7.something, they introduced a breaking change in a minor version because it addressed a security flaw, and world + dog was greeted with this error message.

There's a way around it:

```
drush sql:dump --extra-dump=--no-tablespaces

```

or, if using drush 8:

```
drush sql:dump --extra=--no-tablespaces

```
> 9 votes

---
Tags: database, drush
---


# Question
Title: Add drop down selection to shipping method
I need to add an additional drop down field when a particular shipping method is selected, on the order information page during checkout. I only found how to add additional plugin option when adding a new shipping method through the UI. This is for a custom omniva parcel machine location implementation. Can anyone help me out where to get started with this? EDIT: im using drupal 8 and commerce 2. UPDATE: i tried creating a custom pane, thanks to the suggestion of Berry Dingle. I added the drop down and managed to pass the value to the summary page but i can't figure out how to get the value in the email receipt. I saved the selected value like this but how can i access it in the email template?

This is how i saved the value.

```
$form = $form_state->getValue($pane_form['#parents']);
$val = $pane_form['omniva_parcel_machines']['#options'][$form['omniva_parcel_machines']];
$this->order->setData('omniva_parcel_machines', $val);

```

This is how i built the summary pane.

```
public function buildPaneSummary()
{
    if ($parcel_machine = $this->order->getData('omniva_parcel_machines')) {
        return [
            '#plain_text' => $parcel_machine,
        ];
    }
    return [];
}

```

Is it even possible to access the value in the email receipt twig template or i have to pass it somehow? I tried using

```
{{ order_entity.getData('omniva_parcel_machines') }}

```

as well as

```
{{ order_item.getData('omniva_parcel_machines') }}

```

but so far nothing.

# Answer
> 1 votes
I resolved the issue by adding a field to the order type and then instead of using Order interface

```
$this->order->setData('field_omniva_parcel_machines', $val);

```

i used FieldableEntityInterfaces' set

```
$this->order->set('field_omniva_parcel_machines', $val);

```

and i accessed the value in the commerce-order-receipt.html.twig by using

```
      {% if order_entity.field_omniva_parcel_machines.value %}
         {{ order_entity.field_omniva_parcel_machines.value }}
      {% endif %}

```

Thanks again, Berry, for getting me started with this!

---
Tags: commerce
---


title: Popup map block

text:
# Question
Title: Popup map block
I'm trying to get a map to appear in a modal but haven't worked out a solution yet.

I have a list of items and I would like a map with their locations to appear when I click a 'view map' button. I'm using Leaflet maps and Zurb Foundation, although I'm not sure if this affects the solution.

I can get this to sort of work if I include the map block in a the hidden modal div, but I would really only like the map to be loaded on request. (Also there seem to be map resizing issues when it is placed in a modal)

Another approach I tried was to register a path (of a views page) with hook\_menu and then load this URL into the modal. This worked BUT included the site header & footer in the modal.

So I guess one solution is how to have just the unthemed views content attached to a path.

Any ideas?

Many thanks, Chris

# Answer
I know this post is old, but for anyone else looking for a quick solution and working in Drupal 8...

Try creating a View Page with the map and markers. Then link to that page with a Modal Link, like so...

```
<a class="use-ajax" data-dialog-type="modal" href="/your-view-page">View Map</a>

```

If contextual filters are needed within the view, just add that contextual filter to the href, just as you would that page.

```
<a class="use-ajax" data-dialog-type="modal" href="/your-view-page/123">View Map</a>

```
> 0 votes

---
Tags: 7, javascript
---


# Question
Title: How can I bulk delete Menu Itemes in Drupal 8
is it possible to bulk delete and bulk edit menu items in Drupal 8?

Question for Drupal 7: Any way to bulk delete menu items?

# Answer
> 2 votes
## Bulk delete

there is module https://github.com/robdecker/menu\_delete which you can use that provides checkboxes for easier delete of menu items.

its at the time of this writing missing a SELECT ALL feature which would make it even more helpful

its proposed to be included in core but there is no sign that it will https://www.drupal.org/node/2772961

so you can install it and take advantage of it using following commands

```
cd modules
git clone https://github.com/robdecker/menu_delete.git
drush en menu_delete -y

```

and then go into your menu and you should have available checkboxes and `delete selected` button

## Bulk delete alternative process

```
1. create a custom menu
2. edit items that you want to delete and try to put them under 1 parent (or few parent items)
3. edit those parent menu items and reassign them to the custom menu
4. delete the custom menu

```

## Bulk edit

For bulk edit the https://www.drupal.org/project/menu\_editor module is not yet ported to drupal 8 but it will be a good candidate if it gets ported

# Answer
> 2 votes
Menu Delete module is now available for modern Drupal (Drupal 8 and Drupal 9)!

---
Tags: 8, navigation
---


# Question
Title: Is it possible to dynamically select between two different template files for the same content type?
We are rolling out changes on a content type with a new theme and field structures for existing content.

Is it possible to dynamically select one of two template files for a content type?

For example, if a field on the content type is checked then use node--product.html.twig but otherwise use node--product-old.html.twig.

# Answer
Yes. You can implement hook\_theme\_suggestions\_HOOK\_alter() to set up different templates based on the field.

In your case, you want to add templates for nodes, so the theme hook is `node`. As such, you would implement the following:

```
function hook_theme_suggestions_node_alter(array &$suggestions, array $variables) {
  $node = $variables['node'];
  if ($node->hasField('some_field') && $node->some_field->value == 1) {
    $suggestions[] = 'node__product';
  }
}

```

With this code, when `some_field` does not exist, or does not have a value of `1`, the default `node.html.twig` template will be used, and when `some_field` has a value of `1`, the template `node--product.html.twig` will be used. Adjust accordingly.
> 3 votes

---
Tags: theming, nodes
---


# Question
Title: How do I set a condition to only show a block to a group members?
Is there a way to check whether a user is a group member when the user visits the group page? I have some blocks that should be hidden if an user is not a member.

# Answer
Programmatically you can use `Group::getMember()` to determine if an account is a member of a group.

```
if ($group->getMember(\Drupal::currentUser())) {
  // the current user is a member of the group.
}

```

Note that `Group::getMember()` returns a `GroupMembership` entity.

You could then create a condition plugin, using the above methodology to determine if the current user is a member of the group. I've created a tutorial on how to use the Conditions API to create conditions plugins, using this example of a condition where a member is a member of the group: https://www.jaypan.com/tutorial/custom-block-visibility-plugins-and-condition-plugin-api
> 4 votes

---
Tags: 8, group
---


title: Discount issue?

text:
# Question
Title: Discount issue?
I am working on a big Drupal 7 commerce site and I have some issues with the commerce discount module on order discount. Both Drupal 7, commerce, commerce discount and rules is on newest stable releases.

When going through the checkout and a order discount is attached to the order (either with a discount code or direct) it's visible in the commerce\_order\_total\_data field in the field\_data\_commerce\_order\_total table.

When going from checkout\_review -\> payment the discount is suddenly removed from this order and not getting back.

Cannot figure out what caused this neighter where it happens.

And a sitecomment here is that it works on dev and stage server, but not production (same code and every thing).

# Answer
There's no real way for anyone to answer this without being part of your site and debugging along side of you. The best I can do is say look into what about the production configuration might cause conditions that must be met for those order items to be created / updated to no longer apply. ♂
> 2 votes

---
Tags: 7, commerce
---


title: Dynamic query with left join

text:
# Question
Title: Dynamic query with left join
I need to collect comments that belong to certain user and submitted on pages of certain content type nodes. Currently I'm making two queries:

```
      $nodes = db_select('node', 'n')
      ->fields('n', array('nid'))
      ->execute()->fetchAll();
      unset($node_list);
      foreach ($nodes as $node) {
        $node_list[] = $node->nid;
      }

      $comments = db_select('comment', 'c')
      ->fields('c', array('cid', 'nid', 'created'))
      ->condition('c.nid', [$node_list], 'IN')
      ->execute()->fetchAll();
      foreach ($comments as $comment) {
        some actions
      }

```

and it's working fine. However, I believe I can make just one query for `comment` table by using some kind of database `join` to `node` table and check if a node belongs to `$content_type`. How can I do that?

# Answer
Here is the documentation on joins which should put you on the right path to answering the question.

Untested, but something like this should work:

```
$query = db_select('node', 'n');
$query->join('comment', 'c', 'n.nid = c.nid');
$query
  ->fields('n', array('nid', 'title'))
  ->condition('n.type', 'page')
  ->condition('n.status', '1')
  ->orderBy('n.created', 'DESC')
  ->addTag('node_access');

```
> 2 votes

---
Tags: 7, database
---


title: Query user_field_data in Drupal

text:
# Question
Title: Query user_field_data in Drupal
I need to query the user\_field\_data table to see if a user exists. Through a query string, I pass to a php script that is on the server username and password in clear text. This script connects to the database, and then it should encrypt the password to do the query, but it doesn't work. Anyone knows why don't work? thank you

<?php
        $nome_ut = $_GET['nome'];

        use Drupal\Core\DrupalKernel;
        use Symfony\Component\HttpFoundation\Request;
        // Boot Drupal.
        $autoloader = require __DIR__ . '/autoload.php';

        $request = Request::createFromGlobals();
        $kernel = DrupalKernel::createFromRequest($request, $autoloader, 'prod', FALSE);
        $kernel->boot();

        // Get password hasher service.
        $password_hasher = $kernel->getContainer()->get('password');

        // Hash password.
        if (isset($_GET['pwd']) && !empty($_GET['pwd'])) {
            $pass_ut =  $password_hasher->hash($_GET['pwd']);
        }
        else {
            die('password non impostata');
        }

        print("pass_ut : ".$pass_ut."
");
        $loggato = false;
        $tabella = "users_field_data";
        print ("nome_ut:". $nome_ut."
");
        // dati del Database
        $servername = "localhost";
        $username = "root";
        $password = "root";
        $dbname = "prova";
        if ($nome_ut == "")
    {
        die ("Inserire Nome Utente!
");
    }
        // Creo la connessione
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Verifico connessione
        if ($conn->connect_error)
            {
                die("Connessione fallita: " . $conn->connect_error);
            }
        else {
            print("Connessione eseguita!
");
                //verifico l'esistenza di nome utente e password
            $query = "SELECT * FROM users_field_data WHERE name = '$nome_ut' AND pass = '$pass_ut'";
            $result = mysqli_query($conn, $query);
        if (mysqli_num_rows($result) > 0)        {
            print ("accesso eseguito!
");
            $numero_righe = mysqli_num_rows($result);
            print ("numero righe =". $numero_righe."
");
            $loggato = true;
        }
        else
        {
            print ("accesso negato
");
        }
                }
    ?>```
</code></pre>

# Answer
Drupal core already has code to verify the login credentials are correct. Since Drupal implements the necessary Symfony services, it's not even necessary to directly access the database.

I use the `UserLoginForm` class as guideline to write code to verify the login credentials. I will leave out the part for bootstrapping Drupal.

```
use Drupal\user\UserAuthInterface;
use Drupal\user\UserInterface;
use Drupal\user\UserStorageInterface;

$user_auth = \Drupal::service('user.auth');
$user_storage = \Drupal::entityTypeManager()->getStorage('user');

$accounts = $user_storage->loadByProperties(['name' => $username, 'status' => 1]);
$account = reset($accounts);

if ($account) {
  if ($user_auth->authenticate($username, $password)) {
    // The credentials are correct.
}

```

I first checked there is an account with the given username, as `$user_auth->authenticate()` doesn't check the account hasn't been blocked. Without that part, the code is even shorter.

```
use Drupal\user\UserAuthInterface;

$user_auth = \Drupal::service('user.auth');

if ($user_auth->authenticate($username, $password)) {
  // The credentials are correct.
}

```

`$user_auth->authenticate()` returns the user ID, which is helpful if you need to load the User entity that matches the login credentials.
> 1 votes

---
Tags: authentication-authorization, external-scripts
---


# Question
Title: Attempting to merge in an array of items into Twig classes
I have a Twig template where I'd like to merge in an array of items as classes. So far I have this code:

```
{% set classes = [
  'media',
  'media--type-' ~ media.bundle()|clean_class,
  not media.isPublished() ? 'media--unpublished',
  view_mode ? 'media--view-mode-' ~ view_mode|clean_class,
] %}

 {% for item in content.field_category | children(true) %}
   {% set classes = classes|merge(item) %}
 {% endfor %}

<section{{ attributes.addClass(classes) }}>

etc...

```

***Note*** that `{% for item in content.field_category | children(true) %}` is using Twig Tweak.

In this case for example, `item` represents term values for each item in plain text as:

```
Nature
Travel
Architecture

```

and then with `<section{{ attributes.addClass(classes) }}>`, I'd like the set classes as well as my custom classes to all be merged together. However, I am getting an error:

```
Notice: Array to string conversion in Drupal\Core\Template\AttributeArray->__toString() (line 73 of core/lib/Drupal/Core/Template/AttributeArray.php).

```

So this tells me, I did not merge the array of items properly but I am lost after this, not sure how to fix it. My guess is, I need to do this without a `for` loop somehow?

# Answer
> 3 votes
Twig's merge filter expects an array as an argument, not a string.

Updating your for loop should resolve:

```
{% for item in content.field_category|children(true) %}
  {# Merge classes array with an array with one item, item #}
  {% set classes = classes|merge([item]) %}
{% endfor %}

```

---
Tags: 8, theming, taxonomy-terms, debugging
---


# Question
Title: How do I access a custom field from an action?
I want to access a custom field names field\_heat in a Rules action in D8 and it does not accept it. This is my condition:

And this is my action which cannot be accepted:

If I use a build field like node.title.value it works OK so the problem must be with custom fields. I am using Rules 8.x-3.0-alpha1.

# Answer
# Preface

Be aware of what's written in comment nr 7 of issue nr 2574691:

> rules 8.x-3.0-alpha1 ... is a **preview release** and is **not intended for production sites**. Use at your own risk.

With that in mind, read on for more details to do a similar experiment with rules 8.x-3.0-alfa1.

# Verify setup of content type and field

* I'll use content type "Article", which already has a field with machine name "`field_image`" (out of the D8-box).
* Navigate to `/admin/structure/types/manage/article/fields` to verify this.

# Create a rule

* Enable the Rules module.
* Navigate to `/admin/config/workflow/rules` and create a new rule, with these details:
    + Use **Rules Event** "Before saving content"
    + Add a **Rules Condition** like "Entity has field" (for the `field_image` field). To do so, click on "Value" (within the "Entity" box), and select `node`. And also click on "Value" (within the "Field" box), and select `field_image`. Then click the `Save` button (to save the Rules Condition).
    + Add a **Rules Action** "Set a data value",and continue like so: click on "Value" (within the "Data" box), and select `node:field_image:value` (note that for this Data Selector I'm using `:` (twice), instead of `.` (twice) as in your screenprint). And also enter some "Value" (within the "Value" box), eg `myNiceImage`. Then click the `Save` button (to save the Rules Action).
    + You are then returned to the "edit rules reaction" screen (for the rule you are editing. And it shows a message like "*You have unsaved changes.*". Click the `Save` button (to save the rule). Then a message will be shown like "Reaction rule ABC has been updated." (ABC = the label you gave to your rule).

# Verify if the rule got saved

* Navigate to `/admin/config/workflow/rules` to ensure the rule was really saved (that it does show up there).
* Navigate to `admin/config/development/configuration/single/export` and as "Configuration type" select "Reaction Rule". Then select the label of your rule as the "Configuration name".
* You should then see the exported rule, which should look similar to mine, i.e.:

```
uuid: ab289332-0b45-484f-a1ae-38842620b7e4
langcode: en
status: true
dependencies: {  }
id: check_a_field_before_saving_a_node
label: 'Check a field before saving a node'
events:
  -
    event_name: 'rules_entity_presave:node'
description: ''
tags:
  - ''
config_version: '3'
expression:
  id: rules_rule
  uuid: 354332c5-8307-4097-b33c-0e77307a5e0e
  conditions:
    id: rules_and
    uuid: e82407a4-05c6-45d3-8195-1c1b5f34a07d
    conditions:
      -
        id: rules_condition
        uuid: 3c9094ed-95ec-4202-8398-5a6ca000604a
        context_values:
          entity: node
          field: field_image
        context_mapping: {  }
        context_processors: {  }
        provides_mapping: {  }
        condition_id: rules_entity_has_field
        negate: false
  actions:
    id: rules_action_set
    uuid: 3313095c-f75a-46f2-8d11-f845d12a90f2
    actions:
      -
        id: rules_action
        uuid: 23a3a68e-893e-48c4-a7ee-102201af5a25
        context_values:
          data: 'node:field_image:value'
          value: myNiceImage
        context_mapping: {  }
        context_processors: {  }
        provides_mapping: {  }
        action_id: rules_data_set

```
* The above export should illustrate that I could perfectly save this ... because otherwise I could not have exported it, right?

# Pushing the limits

So far so good, but next I wanted to **update** the value to be assigned in my Rules Action, let's say `myNiceImage` should be updated to `myNewestNiceImage`. So I returned to my Rules Action, and started to edit it. But, that resulted in an error message like so:

> The context Data may only be configured using a selector.

By clicking on the `Switch to data selection` button (so that the button label changed to `Swith to direct input mode`), and trying again, I got another error message like so:

> Data selector node:field\_image for context Data is invalid. Unable to get variable node:field\_image, it is not defined.

# There has to be a way to do it ...

So it seems like updating a Rules Action is not what you should try to do (at least not in the current D8 release of the Rules module).

However, here are the steps I performed to actually get the value updated (from `myNiceImage` to `myNewestNiceImage`) anyhow:

* delete the Rules Action (with the old value `myNiceImage`).
* create a new Rules Action (with the new value `myNewestNiceImage`).

Voilà!

PS: did you notice I'm using "***Entity has field***", and not "***Entity is of type***"?
> 1 votes

# Answer
Looks like to get access to a Content Type fields the condition needed is 'Entity is of bundle' as stated in this issue comment, and fill it with:

* **Entity:** node
* **Type:** node
* **Bundle:** Your content type machine name
> 1 votes

# Answer
I have received the same error. What I have done is:

1. Go to configuration sync (Configuration \> development \> configuration synchronisation)
2. Export single item: Reaction rule \> YOUR RULE. Copy the generated text.
3. Delete the previous rules you have built
4. Import single item: Reaction rule \> Paste the generated text. This time, change the value of the field by hand, that the rule was not accepting previously.
5. If you constructed the structe correctly, the rule works.
> 0 votes

---
Tags: entities, 8, rules
---


# Question
Title: How can I have default field values for the node add form as arguments in the URL?
I have a path in **drupal 6**, which allow me to add new content with 2 fields completed. For example, path `node/add/my_content_type/4/6` means that I am on page `/node/add/my_content_type`, and first field has value "Philip" and second field has value "Oleg". Those names are in database, because user put them in in another content type.

I try to do the same in **Drupal 8**, but I cannot put arguments after /mycontent\_type/. So right now, on the /node/add/my\_content\_type I see a form with fields, I can select names in input select, but nothing shows when I put more arguments in url.

I will give an example:

I have a module with students and school trip. On custom content **"students"**, I add students names in text input. Those names are saved in database.

Let's say, that my second content type is **"trip"**. I have a function, which allow me to add a trip, when students names are given. I can simply click add content 'trip' and select names in select fields, but I want to make it more simple and redirect to page /node/add/trip/4/6 where 4 is id of "Philip" and 6 is id of "Oleg". In this way I have a form with to fields already completed. It is posible in drupal 6, but no in drupal 8. Have can i do that?

I think that one of the problem could be the fact, that Drupal 8 require field "Title". So I have to modify url a little bit /node/add/trip/**??TITLE??**/4/6.

I need exactly this -\> https://www.drupal.org/forum/support/module-development-and-code-questions/2020-04-27/webform-field-default-value-from-url but for custom content :)

# Answer
I figured it out.

in .module, hook\_form\_after()

```
$value = \Drupal::request()->query->get('q');
$value = Html::escape($value);
$form['student']['widget']['#default_value'] = [0 => $value];

```

with url /node/add/trip?q=6, where 6 is id of student Oleg
> 0 votes

---
Tags: 8, nodes, routes
---


# Question
Title: Increase maximum amount of characters for entity reference field (tag style)
I have a Drupal 9 installation running Commerce 2. My products use a taxonomy entity reference field (tag style). There's one products category, where I need to have more references in the tag input field than currently allowed (1024 characters).

I looked it up and found a similar post where someone suggested to write a module to increase the maximum input value like so:

```
function MODULE_field_widget_form_alter(&$element, &$form_state, $context) {

  if ($context['widget']->getPluginId() == 'entity_reference_autocomplete_tags') {
    if ($element['target_id']['#maxlength'] == 1024) {
      $element['target_id']['#maxlength'] = 3072;
    }
  }
}

```

So I did that, but it still doesn't let me input more than 1024 characters. Any help would be appreciated. Thank you!

# Answer
> 0 votes
I didn't manage to increase the maxlength of the input, but installed "Autocomplete deluxe" module, which implements the widget input field via jQuery chosen. Now I can set as many values as I like.

---
Tags: entities, 9
---


# Question
Title: metatag_display_extender plugin does not exist
I am migrating a Drupal site over, the following error is being received... I have clear cache, did a rebuild and no luck. Any suggestions

> **The website encountered an unexpected error. Please try again later.**
>
> Drupal\Component\Plugin\Exception\PluginNotFoundException: The "metatag\_display\_extender" plugin does not exist. Valid plugin IDs for Drupal\views\Plugin\ViewsPluginManager are: default in Drupal\Core\Plugin\DefaultPluginManager-\>doGetDefinition() (line 53 of core/lib/Drupal/Component/Plugin/Discovery/DiscoveryTrait.php). Drupal\Core\Plugin\DefaultPluginManager-\>getDefinition('metatag\_display\_extender') (Line: 16) Drupal\Core\Plugin\Factory\ContainerFactory-\>createInstance('metatag\_display\_extender', Array) (Line: 83) Drupal\Component\Plugin\PluginManagerBase-\>createInstance('metatag\_display\_extender') (Line: 161) Drupal\views\Plugin\views\display\DisplayPluginBase-\>initDisplay(Object, Array) (Line: 91) Drupal\views\DisplayPluginCollection-\>initializePlugin('default') (Line: 38) Drupal\views\DisplayPluginCollection-\>\__construct(Object, Object) (Line: 728) Drupal\views\ViewExecutable-\>initDisplay() (Line: 1754) Drupal\views\ViewExecutable-\>access('page\_1') (Line: 60) Drupal\views\Element\View::preRenderViewElement(Array) call\_user\_func\_array(Array, Array) (Line: 100)

# Answer
> 1 votes
I had this issue when trying to add `metatag_views` to an install profile.

I fixed this issue by adding a config dependency on `metatag_views` to the top of `views.settings.yml`:

```
dependencies:
  module:
    - metatag_views

```

There's more information on this Drupal.org issue.

---
Tags: 8
---


title: Creating a Select List + Textfield

text:
# Question
Title: Creating a Select List + Textfield
I'm trying to create a supplies field made up of a select list (or entity reference) and a number field. Users should be able to create several of these.

For example, the link field has a URL and Title element, (but for this supplies field, there would be a select list instead of the URL field).

Try to find a standalone field (rather than using paragraphs or field collection) for ease of use with JSON:API.

# Answer
Currently looking at:

> The **reference value pair** combines an **entity reference** with a **free text value** field in one new field type.
>
> Source: https://www.drupal.org/project/reference\_value\_pair

Other related projects:
> 0 votes

---
Tags: 8, entities
---


# Question
Title: Installing Acquia BLT on an existing site
We have a working Drupal 9 installation (running within Docksal), which has pretty much the whole install living in `docroot/` except for the `config/` directory, which is a sibling of `docroot/`. This application is fairly plain-vanilla--no custom modules, just some well-known contrib modules and normal config. I will refer to it herein as the "working app."

In order to get this application onto Acquia Cloud and set up our CI/CD we hope to use their BLT utility.

We have tried several approaches to get BLT working with this application:

1. Create a Docksal Drupal 9 BLT boilerplate application and attempt to use `composer install` to get the same set of modules as the working app, and then import the working app's configuration with `fin drush cim`.
2. Create a Drupal 9 BLT boilerplate application and hand-edit `composer.lock` with selections from the working app's `composer.lock` file, run `composer install`, and then import the working app's configuration using `fin drush cim`.
3. Install BLT within the working app as described here: https://docs.acquia.com/blt/install/adding-to-project/.

Approaches 1 & 2 did not work because of incompatibilities between the BLT boilerplate app's composer configuration requirements (`minimum-stability dev` and `prefer-stable true`) and those configurations in the `composer.json` file of the working app. There were also version incompatibilities between the contrib modules in the working app and those which the BLT boilerplate app wanted to install. Hand editing the `composer.json` file also proved equally fruitless.

Using approach 3 we got as far as installing BLT in that the `blt/` directory and associated files are now present, but `blt doctor` complains of a missing `docroot/docroot` directory. Looking at the differences in the filesystem layout between the BLT boilerplate app and the working app made it seem like it might be worth trying to move `vendor/`, `sites/`, `composer.json` and `composer.lock` up one level from within `docroot/` such that those two directories and two files are now siblings of `docroot/` and seeing if that satisfies `blt doctor`. Doing this of course breaks the application and makes composer unhappy. I have tried the following:

1. Deleting everything in `vendor/` and running `composer install`
2. Running `composer dump-autoload`
3. Hand-editing `docroot/autoload.php` looking for and attempting to edit incorrect filesystem locations within the relocated `vendor/` directory

As you can imagine, none of the above have worked and we are just about at the end of our patience with this endeavor.

I have a few general questions:

1. Are any of the three approaches above likely to result in a successful BLT install?
2. With regard to approach 3, is there a generally accepted method of moving either `vendor/`, `composer.*` and/or the `sites/` directory as described above?

Thank you in advance for any general or specific help you can offer.

# Answer
> 0 votes
Composerize Drupal looked like it would be the ideal solution for our problem--it would nuke our composer.\* files, put directories where best practices dictated, and re-composerize the application. Sadly, it's just too far out of date (it hasn't been updated in 2 years) and I ran into several problems installing it either globally on my machine or within docksal.

The solution that worked was Approach #1 in my question above (also what leymannx had suggested). That said, it certainly was not as simple as `cp -R working-app/config/* blt/config/` followed by `fin drush -y cim`.

We had to do the following, in this order:

1. Within the blt drupal run `fin drush cex` to generate baseline config export files.
2. Within the working app run `fin drush cget system.site uuid` and then set that as the site uuid in the blt app `fin drush set system.site uuid xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`
3. Within the blt app, run `composer require` for all the contrib modules in the working app.
4. Hand copy the custom theme from the working app to blt's `docroot/themes/custom` Hand-merge both apps' `config/default/core.extensions.yml` files, with specific importance on making sure to override blt's `minimal` install profile with the working app's `standard` install profile and to make sure the custom theme from the working app was present in the blt `core.extensions.yml`.
5. Once that was done, `fin drush -y cim` worked (as did `fin drush uli` just to make sure), and `fin blt doctor` reported no issues.

# Answer
> 0 votes
You have two distinct problems here:

1. "Composerizing" your codebase
2. Installing BLT

The latter should be pretty painless once you've got the former (theoretically more painful) out of the way.

Fortunately, the Composerize Drupal plugin should get you most if not all of the way there. From the description of your project, you'll want to run this in the root folder (the one containing config/ and docroot/). You don't need to move anything out of the docroot/ folder yourself, anything that needs to be updated will be.

Once that process is complete, run database updates (contrib modules may have been updated to more recent versions), clear cache, verify the site is working, and commit the changes.

At this point you have the structure BLT is expecting, so following the installation instructions again (link in your third approach) should work out a bit better.

---
Tags: composer, 9, acquia-cloud
---