title: #States required not working

text:
# Question
Title: #States required not working
I'm trying to use "#states". When my checkbox is true, I want to make "required" another field. Drupal prints the "required" asterisk but not correctly.

Here it's the code:

```
  // Return origin.
  $form['search']['return']['return_ori'] = [
    '#attributes'    => [
      'class'       => ['field-autocomplete', 'ret-ori-name'],
      'data-type'   => 'busstop',
      'placeholder' => t('Write your origin', [], ['context' => 'Backend']),
      'required'    => TRUE,
    ],
    '#default_value' => !empty($_GET['return_ori']) ? $_GET['return_ori'] : '',
    '#prefix'        => '<div class="row"><div class="col-md-5">',
    '#states'        => [
      'required' => [
        ':input[name="search_return"]' => [
          'checked' => TRUE,
        ],
      ],
    ],
    '#size'          => 40,
    '#suffix'        => '</div>',
    '#title'         => t('Return origin'),
    '#type'          => 'textfield',
  ];
// Return trip.
  $form['search']['search_return'] = [
    '#default_value' => !empty($_GET['search_return']) ? $_GET['search_return'] : FALSE,
    '#prefix'        => '<div class="row"><div class="col-md-5">',
    '#suffix'        => '</div></div>',
    '#title'         => t('Search return trip'),
    '#type'          => 'checkbox',
    '#attributes'    => [
      'class' => ['search-return-trip'],
    ],
  ];

```

The submit button has not specific method, so Drupal should handle it. When I press it, the form is sended ignoring my new required field.

Thanks all for help!!

# Answer
In order to toggle the required state you need to target the widget rather than the form element. Answer courtesy of this very helpful comment on Drupal.org.

In your case the code will be something like:

```
$form['search']['return']['return_ori']['widget'][0]['value']['#states']= [
  'required' => [
    'input[name="search_return[value]"]' => ['checked' => TRUE],
  ],
];

```
> 2 votes

# Answer
Check the "name" attribute of your search return checkbox by inspecting it within your browser. You may find the name="" isn't actually name="search\_return". It may instead be name="search\[search\_return\]" or something similar. So you need to update your states code to whatever the name is
> 0 votes

---
Tags: forms
---


# Question
Title: How do I display a view block next to the branding block in the header?
I have created a view (*Slideshow*) containing a Flex Slider slideshow I want to display in the free header region right of and next to the branding block. I'm using the Bartik theme; I was disappointed to learn that seemingly blocks in the header always come out above or below each other. (I'd prefer blocks to overlap partially and use the view as a kind of background, but for now that's another cup of tea.)

I've tried to put the view in the Header region, change the weight for *Branding* and *Slideview*, and set them identical, but I cannot achieve it.

Also, I looked for any kind of format/position/size setting for blocks, but this seems to go against Drupal conceptually.

Then I wanted to tweak the block's CSS by adding a float-class similar to this one.

```
.float-right {
 text-align: right;
 color:rgba(121, 121, 121, 1);
 font-size: 12px;
 font-style: italic;
 position: relative;
 top:-10px;
 }

```

I cannot find the file to alter.

What am I missing? Any hint would be highly appreciated. (As you might guess, I'm no Drupal-programmer.)

# Answer
> 1 votes
As it's 2022 you really don't want to be using float for layouts - it's hard to control and requires various hacks (like clears) to clean up subsequent element layouts.

If you start off by adding this to your stylesheet:

```
.region-header {
  display: flex;
}

```

You'll see straight away that the branding block and your view appear next to each other.

You can then use align-items, justify-content, gap, etc. to arrange and space the elements as required.

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


# Question
Title: "drush up" is changing my selinux context
Disclaimer: I have found a way to fix this problem short-term, but I'm curious if anyone can explain to me why it's happening, or if someone has found a better fix than what I'm doing. If it exists already, Google has not revealed it to me.

Problem: (on a LAMP Server) When I use 'drush up' to update a module, or even core, the selinux context on the files is changed. This is new behavior as far as I can tell. I have used 'drush up' to update core and modules in the past with no problems. The changed selinux context results in a WSOD. To fix this, I run restorecon -R on the drupal root, which results in a series of

> unconfined\_u:object\_r:user\_tmp\_t:s0-\>unconfined\_u:object\_r:httpd\_sys\_content\_t:s0

and then things work again, until the next 'drush up'. If I have multiple modules to update I either update and restorecon repetitively, or take my chances and drush up -y, restorecon, and then hope for the best (not ideal obviously).

Drush 7 and Drush 8 both behave this way. Oddly enough, when I 'drush dl' a module, it's brought in to the modules folder with the appropriate selinux context. Based on an ll -Z of files in the temp folder, I'm guessing (emphasis on guessing) that the files are getting moved from there rather than copied during an update, but I do not know enough about the inner workings of drush to be able to trouble shoot. Any insight would be welcome. Thank you.

# Answer
> 1 votes
Drush downloads the new files into /tmp, which creates them with the wrong SELinux context. Drush then renames (moves) the new files rather than copying them, which maintains the wrong context.

There's more info at https://github.com/drush-ops/drush/issues/2412

```
diff --git a/includes/filesystem.inc b/includes/filesystem.inc
index 0d0f499..878b7d8 100644
--- a/includes/filesystem.inc
+++ b/includes/filesystem.inc
@@ -323,7 +323,7 @@ function drush_move_dir($src, $dest, $overwrite = FALSE) {
     return drush_set_error('DRUSH_DESTINATION_NOT_WRITABLE', dt('Destination directory !dest is not writable.', array('!dest' => dirname($dest))));
   }
   // Try rename. It will fail if $src and $dest are not in the same partition.
-  if (@drush_op('rename', $src, $dest)) {
+  if (FALSE && @drush_op('rename', $src, $dest)) {
     return TRUE;
   }
   // Eventually it will create an empty file in $dest. See

```

---
Tags: drush
---


# Question
Title: How to pass group context to custom form page using group module
I have a custom block that is displayed within each group on every page. The block visibility is set to `/league/*`

The custom block shows up fine for `/league/{gid}`, `/league/{gid}/members`, `/league/{gid}/edit`, `/league/{gid}/invitations` etc.

I created a custom form with a route of `/league/{gid}/segments`, but my block is not rendering correctly on that page because of this line in my block:

`if (($group = $this->getContextValue('group')) && $group->id()) {`

I got that line from the group module `/src/Plugin/Block/GroupOperationsBlock.php`

`$this->getContextValue('group'))` is not defined.

How can I pass the group context to that form page? I tried adding the options of group to the route like this, but no luck:

```
mymodule.segments:
  path: '/league/{gid}/segments'
  defaults:
    _title: 'Segments'
    _form: 'Drupal\mymodule\Form\SegmentsForm'
  requirements:
    _permission: 'authenticated'
  options:
    parameters:
      group:
        type: 'entity:group'

```

Any ideas?

# Answer
In order for the Group to be part of the page context, it needs to be named `{group}` in your path. So you will need to change this:

```
path: '/league/{gid}/segments'

```

To this:

```
path: '/league/{group}/segments'

```
> 1 votes

---
Tags: 9, group
---


# Question
Title: Can't seem to format date in twig from UTC to User's locale
I am trying to format the date field from an event content type that I've created so that I can pass the date into an event exporter that creates events in calendars such as Google, Apply, Yahoo, and Microsoft. I use calendar\_link which takes a few fields and the dates to create the appropriate calendar event.

```
{# calendar_link(link_type, title, start_date, end_date, all_day, description, location) #}
{% set linkGoogle = calendar_link("google", node.field_event_title.value|raw|replace({'[html format="full_html" different_values="0"]': "", '[/html]': ""})|striptags, date(dateStartField), date(dateEndField), false, "", "") %}
{% set linkICS = calendar_link("ics", node.field_event_title.value|raw|replace({'[html format="full_html" different_values="0"]': "", '[/html]': ""})|striptags, date(dateStartField), date(dateEndField), false, "", "") %}
{% set linkYahoo = calendar_link("yahoo", node.field_event_title.value|raw|replace({'[html format="full_html" different_values="0"]': "", '[/html]': ""})|striptags, date(dateStartField), date(dateEndField), false, "", "") %}
{% set linkWebOutlook = calendar_link("webOutlook", node.field_event_title.value|raw|replace({'[html format="full_html" different_values="0"]': "", '[/html]': ""})|striptags, date(dateStartField), date(dateEndField), false, "", "") %}

```

This works fine. However, when I grab the date field, it's in UTC and not in the user's locale. I understand why, because Drupal stores dates as UTC in the database. (Note: node.field\_event\_start\_date.value is equal to dateStartField as I just do some simple formatting with twig)

```
{{ node.field_event_start_date.value }}

```

I've found some suggestions such as the use of Intl extension of Twig which would give a Twig filter, localizeddate or format\_datetime (I think localizeddate is the old version), but when I used composer to install the twig extensions (https://twig.symfony.com/doc/3.x/filters/format\_datetime.html):

```
composer require twig/intl-extra
composer require twig/extra-bundle

```

it doesn't work. The filters aren't recognized by Twig. I've tried looking at information from here. I've seen others reference the notion of enabling Twig extensions for Symfony projects but I'm not sure where that would be on the backend of the Drupal site. See image attached for the filter error:

Code with format\_datetime that is suppose to take into account the user's locale (On https://twig.symfony.com/doc/3.x/filters/format\_datetime.html the default use of format\_datetime is suppose to take into account the current locale):

```
<span>Calendar Start Date TimeZone Format: {{ calStartDate|format_datetime }}</span>

```

I'm almost at my wits end on trying to format my UTC dates into a localized date via Twig that I can feed into a calendar link exporter. I know I can format a date to a specific timezone with the basic Twig filters, but I can't check for what the user's locale is, thus making this approach void since the locale would be dynamic and not static.

Is there a better approach? Should I create a php hook that modifies the date fields for node--event.html.twig? Would this be appropriate? I don't think I'd need to create a module just for this simple issue but I'm not sure.

Let me know if you have any leads or solutions to any of my problems.

Thanks,
Tanner

# Answer
> 0 votes
It's hard to handle Drupals UTC date format with non-Drupal libraries, get the Unix timestamp:

```
{{ node.field_date.date.gettimestamp }}

```

Or better format Drupal fields with Drupal field formatters. In Twig you can use the `|view` filter of Twig Tweak:

```
{{ node.field_date[0]|view }}

```

You can add an array as argument for the field formatter settings. Even if you want to solve this in code only, configure a field formatter in UI temporarily and export the resulting config. Then you know the settings for `|view()`. See https://git.drupalcode.org/project/twig\_tweak/-/blob/3.x/docs/cheat-sheet.md#view

You can do more things in PHP. See How to get formatted date string from a DateTimeItem object

---
Tags: theming, datetime
---


title: Text pasted in CKEditor isn't clean

text:
# Question
Title: Text pasted in CKEditor isn't clean
On a Drupal 8 installation, with CKEditor enabled for Full HTML format, when I paste text from Word with cmd+V, the source code includes format that makes the code dirty.

Example:

```
<p><span style="font-size:12pt"><span style="line-height:115%"><span style="font-family:Helvetica">Lorem ipsum dolor.</span></span></span></p>

```

How can I force it to clean the code from Word?

# Answer
> 0 votes
Two options:

* there is a special "Paste from Word"-button in CKeditor, add it to your toolbar
* limit allowed HTML tags, it will strip unwanted tags attributes when saving the node (by default `span`s are allowed, but `style` attributes will be removed by default)

Both can be done in `Configuration > Content authoring > Text formats and editors`

# Answer
> 2 votes
For reference, there was a backwards-compatibility break in CKEditor v4.6 - it removed some of its own paste-from-Word button's cleaning. See this discussion on the Drupal side: https://www.drupal.org/project/drupal/issues/2871539

Note comment #6 there offers another workaround - responding to the `afterPasteFromWord` CKEditor event in some custom Javascript and filtering exactly as desired.

# Answer
> 2 votes
This answer is only for **CKEditor in Drupal**. I can recommend two modules to clean up pasted text (not only from Word) into the CKEditor:

CKEditor Paste Filter. This module **works out of the box** without further settings.

Paste Format (filter, clean-up pasted text). This module has **no stable release** (Feb 2022) for Drupal 8/9, but the linked port to Drupal 8/9 works quite well. Nevertheless, **I prefer it** to the first module, because it works by using a "normal" textformat like "Plain Text". Because of that you have the opportunity **to further tweek and restrict the pasted text**. I am using a custom textformat "Pasteformat" with "Convert line breaks into HTML" and "Limit allowed HTML tags and correct faulty HTML" enabled for the following tags:

```
<a href title> <i> <b> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type='1 A I'> <li> <dl> <dt> <dd> <h2> <h3> <h4> <h5> <h6><br><p> <table> <th> <tr> <td> <thead> <tbody> <tfoot>

```

For "Paste Format" i also recommend the installation of the following modules and enabling them in your textformat for pasting text:

No Non-breaking Space Filter to **remove  ** (has to be the first filter in the textformat).

Filter Empty Tags to **remove empty tags** and lines (last filter in the textformat).

After all i can safely give the website to customers which want to paste text from word into the editor – without the risk of breaking design and typography. ;-)

---
Tags: 8, wysiwyg
---


# Question
Title: Event called when an order line is removed
In Drupal Commerce what event do i need to subscribe to when an order line is removed?

This questions talks about an order being removed/deleted: Which events are invoked when an order is removed or cancelled?

The Commerce documentation also only refers to entire orders in terms of events: https://docs.drupalcommerce.org/commerce2/developer-guide/orders/workflows/react-to-workflow-transitions

However I am not seeking an event when the entire order is removed/deleted, only when an individual line is removed/deleted from an order.

Also if I susbcribe to an event that is called when an order line is removed, will that same event be called for each line when an entire order is deleted?

# Answer
> 1 votes
I found the event i needed:

`commerce_order.commerce_order_item.delete`

The second part of my question I will post as a new question to make it more clear.

---
Tags: commerce
---


title: Module Broken Link – installation fails

text:
# Question
Title: Module Broken Link – installation fails
The ›Broken Link‹ module yields an ›unexpected error‹ during installation. Afterwards everything *seems* to be fine and the module is listed as installed, but a node Administration-\>Configuration-\>System-\>Broken Link is missing.

What am I missing?

The error seems to be:

```
Type    php
Date    Thursday, February 17, 2022 - 10:39
User    me
Location    https://mydomain.at/admin/modules
Referrer    https://mydomain.at/admin/modules
Message     Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: You have requested a non-existent service "user.private_tempstore". in Drupal\Component\DependencyInjection\Container->get() (line 156 of /var/www/drupal-9.3.6/core/lib/Drupal/Component/DependencyInjection/Container.php).
Severity    Error
Hostname    myhost
Operations

```

# Answer
When you have a problem with a module, the first place to look is the module's issue queue.

Sometimes there are a lot of issues to search through, but in this case, the error is described in the first issue.

You can download the patch in the issue and apply it to fix the problem.
> 0 votes

---
Tags: 9
---


# Question
Title: Commerce order delete and order item delete events
Quick question I hope someone can easily answer.

There are two order events for order delete listed here: https://github.com/drupalcommerce/commerce/blob/8.x-2.x/modules/order/src/Event/OrderEvents.php

`commerce_order.commerce_order.delete`

and

`commerce_order.commerce_order_item.delete`

I want to delete some related entities when an order line is deleted, so i can hook into commerce\_order.commerce\_order\_item.delete, but my question is if an entire order is deleted will this event also be triggered for each individual line, or do i need to repeat my code also for commerce\_order.commerce\_order.delete and loop through each line on the order?

# Answer
> 2 votes
> if an entire order is deleted will this event also be triggered for each individual line

Yes it will - the commerce order entity has a `postDelete` method which loops through the order items and deletes them one by one

```
public static function postDelete(EntityStorageInterface $storage, array $entities) {
  parent::postDelete($storage, $entities);

  // Delete the order items of a deleted order.
  $order_items = [];
  /** @var \Drupal\commerce_order\Entity\OrderInterface $entity */
  foreach ($entities as $entity) {
    foreach ($entity->getItems() as $order_item) {
      $order_items[$order_item->id()] = $order_item;
    }
  }
  /** @var \Drupal\commerce_order\OrderItemStorageInterface $order_item_storage */
  $order_item_storage = \Drupal::service('entity_type.manager')->getStorage('commerce_order_item');
  $order_item_storage->delete($order_items);
}

```

Deleteing the order item will invoke the event you're subscribing to, so no need to do anything else.

---
Tags: commerce
---


# Question
Title: Keep only the last revision of content with multi-version module
We are using Drupal 8 with the multi-version module version 1.0.0-alpha12.

As part of our dev/test workflow, we SQL dump the production database and move it into dev and test environments. Recently this process has been becoming increasingly slow and after some investigation into the composition of the database, I notice we have ~8G of data in the `node_revision__body` table.

I would therefore like to prune content in the database to keep only the most recent revision when we are working in our dev and test environments.

How can I achieve this with Drupal 8 and the multi-version module? I have come across the Node Revision Delete module, but that has a version for Drupal 7.

# Answer
> 2 votes
Actually, now (March 30 2018) it has a 8.x version. So this is your module:

Node Revision Delete

> The Node Revision Delete module lets you to track and prune old revisions of content types.
>
> Features:
>
> * Define the max amount of revisions to keep per content type.
> * Run on Drush, cron run or on a different period (daily, weekly, etc).

# Answer
> 0 votes
The node revision limit module if you happen to have multilingual sites. The node revision delete do not work properly with Content Translation.

https://www.drupal.org/project/node\_revision\_limit

---
Tags: 8
---


# Question
Title: How to show cart with number of items in Ubercart?
For his cart, my client wants a cart icon with the number of items in it. Not a list of all items. I searched around a little bit but didn't find anything.

# Answer
Assuming the ubercart core 'shopping cart' block doesn't work for what you need:

Then you'll need to output it in your theme or create it as your own custom block. Use the uc\_cart\_get\_contents() function. This loads an array of all the items in their cart, which allows you to get a quick count() on to get your number. From there it is trivial to overlay this output on to your cart icon.

```
// Load the current shopping cart.
$items = uc_cart_get_contents();

// Display a message if the cart has more than 5 products.
$item_count = count($items);

print "<span class='count'>$item_count</span><img src='your_cart_icon.gif'>";

```
> 0 votes

# Answer
As for D8 latest version, it looks like uc\_cart\_get\_contents is not working anymore. So here is how I managed to do it :

```
/** @var \Drupal\uc_cart\CartManager $cartManager */
$cartManager = \Drupal::service('uc_cart.manager');
$items = $cartManager->get()->getContents();
$variables['nbr_cart_items'] = count($items);

```
> 1 votes

# Answer
The code supplied works "OK" as a quick fix, but it actually counts the **number** of distinct products in the shopping cart, not the number of items.

Here's a snippet that counts the number of **items** using a different Ubercart function than the one employed above: **uc\_cart\_get\_total\_qty()**

```
if (module_exists('uc_cart')) {
  $cart_item_count = uc_cart_get_total_qty();
  print $cart_item_count;
}

```
> 1 votes

---
Tags: views, ubercart
---


# Question
Title: ElasticSearch Views integration not working with multiple words
In Drupal 9 I have setup ElasticSearch 7. I have added a Search API View in which I have added field to search through the "rendered HTML" field.

This seems all pretty basic if you ask me, however it doesn't work as expected.

For example my page contains text like "Lorem ipsum dolor sit amet".

* If I search for "ipsum" I get the page as a result
* If I search for "dolor" I get the same result
* But if I search for "ipsum dolor" I get no results at all

Do I miss configuration in either my view, or my ElasticSearch index, or is this some weird missing feature in the views integration. I believe I know enough of both to say that I haven't missed a checkbox or processor, but who knows.

I also haven't found any issues other than this one, which is open for 3 years already. If this is an actual bug I would expect more activity on it, so I expect that I am missing something.

# Answer
> 0 votes
It turns out that I simply used the wrong type of filter.

When looking for filter options in the view I typed "search" and the first result was "Combine fields filter - Combine multiple fields together and search by them.", so I used that without looking further.

Instead I had to use "Fulltext search - Search several or all fulltext fields at once."

---
Tags: views, 9
---


title: Allow module configuration per language

text:
# Question
Title: Allow module configuration per language
I have a module that lets site editors enter plain text title and description for a sitewide element. This site supports several languages - how can I enable entering values for each enabled language?

I see documentation here:

https://www.drupal.org/docs/drupal-apis/configuration-api/configuration-schemametadata#intro

Do I simply update my schema for a langcode and add a language selector on the configuration form?

# Answer
> 3 votes
No, you don't need to add anything to the config form. Once you have created the schema and cleared the cache the translation form is built automatically (if the Configuration Translation module is enabled) and you can access it via the Translate tab. It looks by the way completely different than the original form and contains only values which are translatable according to the schema.

As @Kevin commented Drupal expects more, to be able to connect the translation tab to a base route. For simple configuration, as in this case, define a *mymodule.config\_translation.yml* file.

Example for /admin/config/system/site-information:

*system.config\_translation.yml*

```
system.site_information_settings:
  title: 'System information'
  base_route_name: system.site_information_settings
  names:
    - system.site

```

And a tab, so that the tabs are displayed when the second translation tab is generated:

*system.links.task.yml*

```
system.site_information_settings_tab:
  route_name: system.site_information_settings
  title: Settings
  base_route: system.site_information_settings

```

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


title: create a child node via api

text:
# Question
Title: create a child node via api
Running Drupal 9.3, I have two content types, job and and Job detail. Every job has many job details.

Lets say i created a job with node ID of 5. I have a field in job detail called "field\_job\_id" that will take the node ID of the parent, in this case "5".

When creating a job detail node, i have tried inputting the node ID as a int, as a string and nothing works.

```
    "_links": {
    "type": {
      "href": "https://domain.com/rest/type/node/job_detail"
    }
  },
  "title": [
    {
      "value": filename
    }
  ],
  "field_job_id": [
    {
      "value": jobTitle
    }
  ],
  "field_document_type": [
    {
      "value": "PDF"
    }
  ],
  "field_author": [
    {
      "value": author
    }
  ],
  "field_remediation_cost": [
    {
      "value": "0"
    }
  ]
})
headers = {
  'Content-Type': 'application/hal+json',
  'Authorization': 'Basic HDHBdbdb83hcn8echw8fy389hfeuivbwe'
}

```

The node get posted but the field that should display the parent node is blank every time. Is there something i am doing wrong?

# Answer
FINALLY figured it out. since I am dealing with a entity ref, that being "field\_job\_id" I had to add a field

```
  "field_job_id":[{"target_id":8}],

```

with 8 being the node of the job it is referencing
> 1 votes

---
Tags: entities, 9
---


# Question
Title: Linkit Module - Pointing the link's title attribute to a custom field. Hook available?
Currently the Linkit module delivers the link's `title` attribute by pulling the related node's `title` field.

We would like it to point to another field in the node.

How can we achieve this?

I looked into Editor Advanced Link module, but I need this to be automatic, and my custom field changes based on content type.

Maybe someone has a hook idea?

# Answer
There are (at least) 2 options:

1. Write a custom filter plugin, basing it on the `LinkitFilter` plugin included with the Linkit module. In the `process()` method, where the title is currently set, introduce you own logic to set the title field instead of the existing `$entity->label()`.
This method has the benefit of auto-updating when a referenced node's title changes, but does mean you'll have to maintain your filter alongside the Linkit module's releases. The `process()` method does a lot more than just setting the title, and new features/bug fixes in the module will need to be incorporated into your code.
2. Alter the link dialog form (like Editor Advanced Link does), and get the title into the markup while it's still in the editor. This method is a bit easier, and less maintenance, but the `title` attribute won't update when the node title does. It will only update when the link dialog form is saved again.
If that's acceptable, this is a rough but working example to get started:

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

function custom_module_form_editor_link_dialog_alter(&$form, FormStateInterface $form_state, $form_id) {
  array_unshift($form['#validate'], '_custom_module_link_dialog_validate');
}

function _custom_module_link_dialog_validate(array &$form, FormStateInterface $form_state) {
  $attributes = $form_state->getValue('attributes');

  if (isset($attributes['data-entity-type']) && $attributes['data-entity-type'] == 'node') {
    $node = \Drupal::service('entity.repository')
      ->loadEntityByUuid('node', $attributes['data-entity-uuid']);
    if ($node instanceof NodeInterface) {
      $override_title = '';
      switch ($node->getType()) {
        case 'page':
          $override_title = $node->field_title_override->value;
          break;
        case 'foo':
          // ...
          break;
      }
      if (strlen($override_title)) {
        $form_state->setValue(['attributes', 'title'], $override_title);
      }
    }
  }
}

```
> 3 votes

---
Tags: uri, meta-tags, wysiwyg
---


title: Configuration Menu Items

text:
# Question
Title: Configuration Menu Items
How can I add a section to the admin/config route and populate it with my own modules? In Drupal 7 it was easy, but I can't figure it out now in Drupal 8. The closest I can get is adding my modules to the Configuration Menu List that appears in the sidebar.

module.links.menu.yml

```
module.admin_settings:
  title: 'Module Admin Title'
  description: 'Module Admin Desc.'
  route_name: my_module.my_module_settings
  parent: system.admin_config

```

# Answer
> 1 votes
You must add a menu link and a router item for the page:

1. Add a menu link in `my_module.links.menu.yml`. See core/modules/system/system.links.menu.yml:

```
my_module.my_group_menu:
  parent: system.admin_config
  route_name: my_module.my_group

```
2. Add a router item in `my_module.routing.yml`, which can re-use the same controller: SystemController::systemAdminBlockPage(). See core/modules/system/system.routing.yml for an example.

```
my_module.my_group:
  path: '/admin/config/my-group'

```
3. Then add your menu link to your settings page as a parent to the menu link you created in #1.

# Answer
> 2 votes
You should assign your menu link to one of the specific groups on /admin/config by setting the correct path. You can find most of them in system.links.menu.yml and it usually matches the path, e.g. `parent: system.admin_config_media`.

# Answer
> 2 votes
The accepted answer is right, but I found it hard to understand.

The sections on admin/config are actually a page. Take a look at the breadcrumbs after clicking on 'basic site settings': you can click `up` one level to a page for `system`.

So you need two links, and two routes. The first link defines a page you will rarely use, but also creates the block on the admin/config page.

mymodule.links.menu.yaml:

```
system.admin_config_mysite:
  route_name: system.admin_config_mysite
  parent: system.admin_config
  title: MySite Settings
  description: 'Configure MySite'
  weight: 100

mymodule.settings:
  title: 'MyModule Settings'
  parent: system.admin_config_mysite
  description: 'Settings for MyModule'
  route_name: mymodule.settings
  weight: 100

```

mymodule.routing.yml

```
system.admin_config_mysite:
  path: '/admin/config/mysite'
  defaults:
    _controller: '\Drupal\system\Controller\SystemController::systemAdminMenuBlockPage'
    _title: 'MySite Settings'
    _title_context: 'mysite'
  requirements:
    _permission: 'access administration pages'

mymodule.settings:
  path: '/admin/config/mysite/mymodule'
  defaults:
    _form: '\Drupal\mymodule\Form\MyModuleSettingsForm'
    _title: 'MyModule Settings'
    _title_context: 'mysite'
  requirements:
    _permission: 'administer site configuration'

```

---
Tags: routes, 8
---


# Question
Title: Cannot resave nodes with entity->save(), no particular error
I'm trying to write a drush command to resave all the nodes on my site.

I searched for a module and found the Resave All Nodes module, but its drush command isn't ready yet. So I decided to try to write it myself.

However, I can't get my nodes to re-save with `$entity->save()`, and I don't understand why.

```
<?php

namespace Drupal\resave_all_nodes\Commands;

use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\node\Entity\Node;
use Drush\Commands\DrushCommands;

/**
 * A Drush command class for Resave All Nodes module conversions.
 */
class ResaveAllNodesCommands extends DrushCommands
{

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  private $entityTypeManager;

  /**
   * Constructs a ResaveAllNodesCommands object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager)
  {
    $this->entityTypeManager = $entity_type_manager;

    parent::__construct();
  }

  /**
   * Resave all nodes.
   *
   * @command resave-all-nodes:resave
   *
   * @usage drush resave-all-nodes:resave
   *   Resave all nodes on the site.
   *
   * @aliases ran
   */
  public function resaveAllNodes()
  {
    $my_node = Node::load(1);
    $my_node->save();
    \Drupal::logger('resave_all_nodes')->notice("node 1 saved!");
  }
}

```

When I run the command, the logs show the logger notices:

* I see "node 1 saved!" in the logs
* I have another log message in `hook_entity_presave()`, which also appears

But, when I go to `/admin/content`, the "date updated" for node 1 has not changed. Also, the content of the node is not resaved.

If I go to `node/1/edit` and re-save manually, the node is re-saved as I would expect (the updated date is updated, and the field values are updated).

So, why does `node->save()` silently fail (the update date and field values remain the same), when saving manually works?

I have a few custom modules and I disabled them and rebuilt the cache, but the problem remains.

# Answer
> 2 votes
Thanks to @4k4 and @Clive I was able to get this working. This drush command saves all nodes. The code follows, but first some notes:

* After calling `batch_set()`, for drush commands, you have to call `drush_backend_batch_process()` or the batch will never be run.
* The Drush 9 Batch Processing Example module is a very helpful example.
* In your `batchOperation()` command, if you typehint `$context`, you have to use `\DrushBatchContext|array $context` not just `array` because drush will crash hard. There are dozens of issues on drupal.org about this.

Ok, here's my code:

```
<?php

namespace Drupal\resave_all_nodes\Commands;

use Drupal\Core\Batch\BatchBuilder;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drush\Commands\DrushCommands;

/**
 * A Drush command class for Resave All Nodes module conversions.
 */
class ResaveAllNodesCommands extends DrushCommands
{
  use StringTranslationTrait;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  private $entityTypeManager;

  /**
   * Constructs a ResaveAllNodesCommands object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager)
  {
    $this->entityTypeManager = $entity_type_manager;

    parent::__construct();
  }

  /**
   * Resave all nodes.
   *
   * @command resave:nodes
   *
   * @usage drush resave:nodes
   *   Resave all nodes on the site.
   *
   * @aliases ran
   */
  public function resaveAllNodes()
  {
    // An array with lots of node IDs.
    $nids = $this->getNodeIds();
    // Chop array into sub-arrays (chunks) of specified size.
    $chunks = array_chunk($nids, 250);
    $num_chunks = count($chunks);

    // Now resave all nodes chunk by chunk.
    $batchBuilder = new BatchBuilder();
    for ($i = 0; $i < $num_chunks; $i++) {
      $batchBuilder->addOperation('\Drupal\resave_all_nodes\Batch\ResaveAllNodesBatch::batchOperation',
        [$chunks[$i]]
      );
    }

    $batchBuilder->setTitle(t('Resaving nodes'))
      ->setFinishCallBack('\Drupal\resave_all_nodes\Batch\ResaveAllNodesBatch::batchFinished');

    batch_set($batchBuilder->toArray());
    drush_backend_batch_process();
  }

  /**
   * Get an array node IDs.
   *
   * @return array|int
   *   An array of node IDs at best.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function getNodeIds() {
    $query = $this->entityTypeManager->getStorage('node')->getQuery();
    $nids = $query->execute();
    # To get node types.
    # $nids = $query->condition('type', $node_types, 'IN')->execute();

    return $nids;
  }
}

```

---
Tags: nodes, drush, 9
---


# Question
Title: Cannot add new user due to "Integrity constraint violation: Duplicate entry" error
Starting December 14, 2021, my site began creating users with low user IDs, even though the highest-used user ID was 9317. I *thought* something had been changed in a core update to reuse IDs that had been freed up by canceling a user account. However, I discovered that since that date, the site has been trying to reuse every ID starting with 1. My error log is filled with errors like this:

```
Drupal\Core\Entity\EntityStorageException: SQLSTATE[23000]: Integrity constraint violation:
1062 Duplicate entry '281' for key 'users.PRIMARY': INSERT INTO "users" ("uuid", "langcode")
VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1); Array (
[:db_insert_placeholder_0] => 5ff1347c-439f-437e-ba3f-762f7350fda3
[:db_insert_placeholder_1] => en ) in Drupal\Core\Entity\Sql\SqlContentEntityStorage->save()
(line 811 of /home/drupal/webroot/rsc.byu.edu/web/core/lib/Drupal/Core/Entity/
Sql/SqlContentEntityStorage.php).

```

The above example says `Duplicate entry '381'`. The next error will say `Duplicate entry '382'` and so on.

I read posts suggesting the `sequences` table contains the next user ID value. My `sequences` table contains the value `9330`, which would be fine if it were being used. But it's not.

# Answer
After long looking, I noticed on a backup from before December 14, 2021, the `users` table `uid` field was defined as Attributes: UNSIGNED. NOW (February 18, 2022), the `uid` field is defined as **Attributes: nothing and Extra: AUTO\_INCREMENT**. The AUTO\_INCREMENT is new.

This led me to test with a backup copy of my site. Sure enough, prior to December 14, 2021, each time I add a user, the value in the `sequences` table is incremented. That no longer happens in the updated site. Instead, it crashes as described above.

The solution was to run the following query in the database:

```
ALTER TABLE users AUTO_INCREMENT = 3918; # highest existing ID was 3917

```

This solved the problem. I assume that in a core update installed on December 14, 2021, the code changed from using the `sequences` table to using AUTO\_INCREMENT on the `uid` field in the `users` table and that somehow, I failed to do a database update that would have correctly set the AUTO\_INCREMENT value in the `users` table to avoid this mess.

I hope this report of my pain will help someone.
> 6 votes

---
Tags: users, 9
---


# Question
Title: How do I use DependencySerializationTrait?
I'm on Drupal 9. I'm trying to edit the `ProductVariationAccessControlHandler` class of Commerce.

The class extends `Drupal\Core\Entity\EntityAccessControlHandler` which in turn extends the abstract class `EntityHandlerBase`

This abstract class use the `DependencySerializationTrait` trait.

Now, I want to inject a new service inside `ProductVariationAccessControlHandler`. The parent class has a `__construct` method:

```
/**
 * Constructs an access control handler instance.
 *
 * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
 *   The entity type definition.
 */
public function __construct(EntityTypeInterface $entity_type) {
  $this->entityTypeId = $entity_type->id();
  $this->entityType = $entity_type;
}

```

I've searched, but found no documentation nor understood what is the way to use that "trait" in order to inject another service - e.g. *entity\_type.manager*.

# Answer
> 1 votes
`DependencySerializationTrait` is used to avoid that a service contained in a class property is fully serialized when that class instance is serialized. Instead, the service identifier is serialized within the class instance.

`DependencySerializationTrait` isn't used to add dependencies to a class that uses Dependency Injection. If you are editing an existing access control handler class (which isn't the correct thing to do when the class is implemented by Drupal core or a contributed module hosted on drupal.org) to add more dependencies, you should edit its `createInstance()` method, if it exists, or add it. For example, the `WorkflowAccessControlHandler` class uses the following code, to inject the dependencies it needs.

```
  /**
   * {@inheritdoc}
   */
  public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
    return new static($entity_type, $container
      ->get('plugin.manager.workflows.type'));
  }

  /**
   * Constructs the workflow access control handler instance.
   *
   * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
   *   The entity type definition.
   * @param \Drupal\Component\Plugin\PluginManagerInterface $workflow_type_manager
   *   The workflow type plugin manager.
   */
  public function __construct(EntityTypeInterface $entity_type, PluginManagerInterface $workflow_type_manager) {
    parent::__construct($entity_type);
    $this->workflowTypeManager = $workflow_type_manager;
  }

```

The correct way to alter an access control handler used by an entity is implementing `hook_entity_type_build()` and change the access control handler with `EntityTypeInterface::setAccessClass()`. For example, for the Node entity, I could use the following code.

```
function book_entity_type_build(array &$entity_types) {
  /** @var \Drupal\Core\Entity\EntityTypeInterface[] $entity_types */
  $entity_types['node']->setAccessClass('Drupal\\mymodule\\Access\\ExtendedNodeAccessControlHandler');
}

```

# Answer
> 1 votes
This trait has nothing to do with injecting another service, see When should I use DependencySerializationTrait?

The basic way to inject another service is overriding \__construct:

```
  public function __construct(EntityTypeInterface $entity_type, EntityTypeManagerInterface $entity_type_manager) {
    parent::__construct($entity_type);
    $this->entityTypeManager = $entity_type_manager;
  }

```

You need to be careful, though. Modules could consider the method to be internal and when they decide to inject another service themselve this will break others code. Best practice for modules is to provide a fallback with a deprecation message in such cases. See this change record NodeAccessControlHandler and MediaAccessControlHandler constructor adds a $entity\_type\_manager argument and the \__construct method:

```
  public function __construct(EntityTypeInterface $entity_type, EntityTypeManagerInterface $entity_type_manager = NULL) {
    parent::__construct($entity_type);
    if (!isset($entity_type_manager)) {
      @trigger_error('Calling ' . __METHOD__ . '() without the $entity_type_manager argument is deprecated in drupal:9.3.0 and will be required in drupal:10.0.0. See https://www.drupal.org/node/3214171', E_USER_DEPRECATED);
      $entity_type_manager = \Drupal::entityTypeManager();
    }
    $this->entityTypeManager = $entity_type_manager;
  }

```

---
Tags: entities, 9, dependency-injection
---


# Question
Title: How to programmatically append fields to node object when cloning with createDuplicate()
I am trying to setup a custom module which copies values from a node whose content type is *A* to a node whose content type is *B*. For the most part, the content types have the same fields, but *B* has a few additional fields.

### A

* Title (title)
* Body (body)
* Date (field\_date\_agenda)

### B

* Title (title)
* Body (body)
* Date (field\_date\_agenda)
* Number of items (field\_int\_how\_many)
* Reference to *A* (field\_noderef\_nta)

With `$cloned_node = $node->createDuplicate()` I am able to copy all the fields from *A*, as well as being able to change the content type to *B*.
Since *A* doesn't have the extra fields attached to it, `createDuplicate()` won't copy them.

Now, what I would like to do is to programmatically add the other fields (which I will populate with some custom values) to `$cloned_node`. When these actions are completed, `$cloned_node->save()` will be used to finalize the cloning process.

Simply adding the value via `$cloned_node->set("field_int_how_many", $value)` doesn't seem to do the trick: A PHP error is thrown.

> InvalidArgumentException: Field field\_int\_how\_many is unknown. in Drupal\Core\Entity\ContentEntityBase-\>getTranslatedField() (line 587 of /home/username/domains/domainname.com/public\_html/devsite/web/core/lib/Drupal/Core/Entity/ContentEntityBase.php).

Does anyone have an idea how to add those extra fields to the cloned node?

# Answer
If the content type of `$node` is *A*, the content type of the node returned by `$node->createDuplicate()` is still *A*. That's why `$node->createDuplicate()->set("field_int_how_many", $value)` returns an error saying that *field\_int\_how\_many* is an unknown field: Content type *A* doesn't have that field.

What you are trying to obtain isn't a clone of `$node`, but to copy the values from a node whose content type is *A* to a node whose content type is *B*.
For that, you need to create a new node, passing the values of the existing node field as values for the new node fields.

```
$new_node = Node::create(
  'type' => 'B',
  'title' => $node->title,
  'body' => $node->body,
  'field_date_agenda' => $node->field_data_agenda,
  'field_int_how_many' => /* the value to assign to the field */
);

```
> 3 votes

---
Tags: nodes, 9
---


# Question
Title: How update a webform submitted value clicking in a button?
How can I update a submitted data just clicking in a button? I have created a View table of webform subissions and I would like to add a collumn with a button "Aprroval". When user click on this button, the data value must be updated. My intention is optimize the "edit" and "save", avoiding the Form edit screen. Add a custom action in a "Webform submission operations bulk form" solves my problem too.

# Answer
You can use `hook_entity_operation` to add a custom entity operation for webform submissions. With the Webform Views Integration module you should already be able to add an "Operations" field to your view. It lists the default operations depending on access levels (Edit, Delete etc.). There your custom operation will appear.

## MYMODULE.module

```
<?php

/**
 * @file
 * Hooks implemented by the MYMODULE module.
 */

use Drupal\Core\Entity\EntityInterface;
use Drupal\webform\WebformSubmissionInterface;

/**
 * Implements hook_entity_operation().
 */
function MYMODULE_entity_operation(EntityInterface $submission) {
  $operations = [];
  if ($submission instanceof WebformSubmissionInterface) {
    if ($submission->getElementData('MY_HIDDEN_REVIEW_ELEMENT') !== 'approved') {
      $operations['approve'] = [
        'title' => t('Approve'),
        'weight' => 15,
        'url' => Url::fromRoute('MYMODULE.webform_submission_approve', [
          'submission' => $submission->id(),
        ], [
          'query' => \Drupal::destination()->getAsArray(),
        ]),
      ];
    }
  }
  return $operations;
}

```

## MYMODULE.routing.yml

```
MYMODULE.webform_submission_approve:
  path: '/admin/MYMODULE/submission/{submission}/approve'
  defaults:
    _controller: '\Drupal\MYMODULE\Controller\WebformSubmissionApproveController::approve'
  options:
    parameters:
      submission:
        type: 'entity:webform_submission'
  requirements:
    _custom_access: '\Drupal\MYMODULE\Controller\WebformSubmissionApproveController::access'

```

## src/Controller/WebformSubmissionApproveController.php

```
<?php

namespace Drupal\MYMODULE\Controller;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Controller\ControllerBase;
use Drupal\webform\Entity\WebformSubmission;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;

/**
 * Class WebformSubmissionApproveController.
 *
 * @package Drupal\MYMODULE\Controller
 */
class WebformSubmissionApproveController extends ControllerBase {

  /**
   * Approve method.
   *
   * @param \Drupal\webform\Entity\WebformSubmission $submission
   *   A webform submission.
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The current HTTP request.
   *
   * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
   *   The response.
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public function approve(WebformSubmission $submission, Request $request) {

    $submission->setElementData('MY_HIDDEN_REVIEW_ELEMENT', 'approved');
    $submission->save();

    $this->messenger()->addMessage($this->t('Submission @serial approved.', [
      '@serial' => $submission->serial(),
    ]));

    return $request->query->get('destination') ? new RedirectResponse($request->query->get('destination')) : [];
  }

  /**
   * Checks access for a specific request.
   *
   * @return \Drupal\Core\Access\AccessResult
   *   The access result.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public function access(WebformSubmission $submission) {
    return AccessResult::allowedIf(!$submission->isDraft() && in_array('administrator', $this->currentUser()->getRoles()));
  }

}

```
> 4 votes

---
Tags: 8, webforms
---


# Question
Title: How to redirect user page to front page for specific roles
I want to redirect every users page to front page? like if user page url is /user/97 then it redirect to front page if user is not administrator. I want user page inaccessible to other users but only administrators.

How can I achieve this?

I tried doing like this:

```
<?php

namespace Drupal\myisu_ubit\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
// use Drupal\user\Entity\User;

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

 /**
  * {@inheritdoc}
  */
 protected function alterRoutes(RouteCollection $collection) {
   // Change the route associated with the user profile page (/user, /user/{uid}).
   if ($route = $collection->get('user.page')) {
      $route->setPath('/');
   }
 }

}

```

module.services.yml:

```
services:
  user_profile.route_subscriber:
     class: Drupal\module\Routing\RouteSubscriber
     tags:
        - { name: event_subscriber }

```

What am I doing wrong here?

# Answer
Solved using EventSubscriber like this:

```
services:
  my_module.event_subscriber:
    class: Drupal\my_module\EventSubscriber\MyModuleSubscriber
    tags:
       - {name: event_subscriber}

```

And MyModuleSubscriber:

```
namespace Drupal\my_module\EventSubscriber;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\views\Views;
use Drupal\views\ViewExecutable;
use Drupal\user\Entity\User;
use Drupal\Core\Url;

class MyModuleSubscriber implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   */
  public function checkForRedirection(GetResponseEvent $event) {
    $request = \Drupal::request();
    $requestUrl = $request->server->get('REQUEST_URI', NULL);
    $userID = \Drupal::currentUser()->id();
    $user = User::load($userID);
    $uid = $user->get('uid')->value;
    $roles = $user->getRoles();
    $userPage = "/user/" . $userID;
    if (
      $userID !== '1' &&
      !in_array('administrator', $roles) &&
      $requestUrl == $userPage
    ) {
        $path =  \Drupal::service('path.alias_manager')->getAliasByPath('/');
      $event->setResponse(new RedirectResponse($path, 301));
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::REQUEST][] = array('checkForRedirection');
    return $events;
  }

}

```

I don't know if it is the correct way to do this but it solves my problem.
> 6 votes

# Answer
Here's an updated example for Drupal 9.

Notes

* This does not check for an administrator role; instead, it checks for the `administer content` permission, which all admins have on my site. Make sure the same is true for your site or modify the code.
* This does a redirect on ANY user profile page, not just the user's own profile page. This is different from @tasqyn's code.
* This uses route matching instead of hard-coding the user profile path. This is important because otherwise it will break if you change the user path with something like the Rename Admin Paths module.

**mymodule/mymodule.services.yml**

```
services:
  my_subscriber:
    class: Drupal\mymodule\EventSubscriber\MyEventSubscriber
    arguments: ['@request_stack', '@current_route_match', '@current_user']
    tags:
      - { name: 'event_subscriber' }

```

**mymodule/src/EventSubscriber/MyEventSubscriber.php**

```
<?php

namespace Drupal\mymodule\EventSubscriber;

use Drupal\Core\Routing\CurrentRouteMatch;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\Core\Url;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Event Subscriber MyEventSubscriber.
 */
class MyEventSubscriber implements EventSubscriberInterface {

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * The current route match.
   *
   * @var \Drupal\Core\Routing\CurrentRouteMatch
   */
  protected $currentRouteMatch;

  /**
   * The current user.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected AccountInterface $currentUser;

  /**
   * MyEventSubscriber constructor.
   *
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   * @param \Drupal\Core\Routing\CurrentRouteMatch $current_route_match
   *   The current route match.
   * @param \Drupal\Core\Session\AccountInterface $current_user
   *   The current user.
   */
  public function __construct(RequestStack $request_stack, CurrentRouteMatch $current_route_match, AccountInterface $current_user) {
    $this->requestStack = $request_stack;
    $this->currentRouteMatch = $current_route_match;
    $this->currentUser = $current_user;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events = [
      KernelEvents::REQUEST => 'redirectAuthUsersOnProfile',
    ];
    return $events;
  }

  /**
   * {@inheritdoc}
   */
  public function redirectAuthUsersOnProfile(RequestEvent $event) {
    $routeName = $this->currentRouteMatch->getRouteName();
    if (!$this->currentUser->hasPermission('administer content') &&
      $routeName === 'entity.user.canonical') {
      $response = new TrustedRedirectResponse('/webapp/index.html', 302);
      $event->setResponse($response);
    }
  }

}

```
> 2 votes

---
Tags: 8, redirection
---


# Question
Title: How can I inject dependencies based on conditions?
I am creating one custom form and in this form I need to use one service which are there in another module. I need to use that dependency injection based on condition which are there in configuration.

Conditions in Config Form:

1. Use Custom1 Form
2. Use Custom2 Form

If “Use Custom1 Form” enabled, then I need to use dependency injection.

```
namespace Drupal\test\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
use Symphony\Component\DependencyInjection\ContainerInterface;
use Drupal\custom_form1\Services\TestService;

/**
 * Test forms.
 */
class TestForm extends ConfigFormBase {

  /**
   * PinCodeRegistration Object.
   *
   * @var Drupal\custom_form1\Services\TestService;
   */
  protected $TestService;

  /**
   * Constructs a new pin code multistep form.
   *
   * @param Drupal\custom_form1\Services\TestService $test_service
   *   The service handler.
   */
  public function __construct(TestService $test_service) {
    $this->TestService = $test_service;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('custom_form1.form1_services')
    );
  }
}

```

How can I add `use Drupal\custom_form1\Services\TestService;` based on conditions?

If the *custom\_form1* module isn't installed, I get an error. Any Idea how we need to avoid error and added dependency based on conditions?

# Answer
> 1 votes
The question doesn't make it explicit, but since the question mentions getting an error when another module isn't installed, I take that *the condition* is *when the module is installed*. In that case, the module can simply use the following code.

```
public function __construct(TestService $test_service = NULL) {
  $this->testService = $test_service;
}

public static function create(ContainerInterface $container) {
  return new static(
    $container->has('custom_form1.form1_services') ? $container->get('custom_form1.form1_services') : NULL
  );
}

```

In this case, the class in your module should be ready not to get any class instance. Alternatively, your module could implement a simplified version of the service, which implement the same interface, and use code similar to the following one.

```
public function __construct(TestServiceInterface $test_service = NULL) {
  $this->testService = $test_service;
}

public static function create(ContainerInterface $container) {
  return new static(
    $container->has('custom_form1.form1_services') ? $container->get('custom_form1.form1_services') : $container->get('mymodule.form1_services')
  );
}

```

This assumes`TestService` implements an interface that can be implemented from the simplified service. (It also assumes it's possible to implement a simplified service.)

# Answer
> 3 votes
Dependencies cannot be added conditionally based on functionality within the class, as the injection happens during instantiation of the class, and is already complete before class methods can be called. Instead, you inject both services, and use whichever one you need when you need it. Or you can call the service you need statically using `\Drupal::service()` when you actually need it, though it is preferable to use dependency injection when in class context over calling services statically.

---
Tags: dependency-injection
---


# Question
Title: Updating core to a specific version with Composer
My site hasn't been updated for two months, a few new updates has been released. My site's core version is 8.5.6. Before running `composer update -with-dependencies` I read the release notes to the latest version of core (8.6.2), they say:

> Sites on 8.5.x should update immediately to Drupal 8.5.8 instead, and plan to update to the latest 8.6.x release before May 2019.

How do I update the old core to Drupal 8.5.8 instead? How do I specify that version in CLI, what command? Eventually I want to update it to the latest version.

# Answer
> 2 votes
I was in the same position. I used :

```
composer require drupal/core:^8.5.10

```

And it worked. Cheers.

# Answer
> 1 votes
If your project uses drupal/core-recommended you can execute this command to update your site to a specific release :

```
composer require drupal/core-recommended:9.2.16 drupal/core-composer-scaffold:9.2.16 drupal/core-project-message:9.2.16 --update-with-all-dependencies

```

---
Tags: 8, updating, composer
---


# Question
Title: "RuntimeException: You have requested a non-existent parameter 'app.root'"
After I clear the cache, I get this message.

> Symfony\Component\DependencyInjection\Exception\RuntimeException: You have requested a non-existent parameter "app.root". in Symfony\Component\DependencyInjection\Compiler\DefinitionErrorExceptionPass-\>processValue() (line 37 of /var/www/call/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php). Symfony\Component\DependencyInjection\Compiler\DefinitionErrorExceptionPass-\>processValue() (Line: 60) Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass-\>processValue() (Line: 30) Symfony\Component\DependencyInjection\Compiler\DefinitionErrorExceptionPass-\>processValue() (Line: 39) Symfony\Component\DependencyInjection\Compiler\AbstractRecursivePass-\>process() (Line: 140) Symfony\Component\DependencyInjection\Compiler\Compiler-\>compile() (Line: 789) Symfony\Component\DependencyInjection\ContainerBuilder-\>compile() (Line: 1335) Drupal\Core\DrupalKernel-\>compileContainer() (Line: 916) Drupal\Core\DrupalKernel-\>initializeContainer() (Line: 477) Drupal\Core\DrupalKernel-\>boot() (Line: 707) Drupal\Core\DrupalKernel-\>handle() (Line: 19)

Do you have any idea on how to solve this problem?

# Answer
> 3 votes
This error is caused by code using `%app.root%` as parameter in Drupal 8.

For example:

```
   cache.backend.apcu:
     class: Drupal\Core\Cache\ApcuBackendFactory
     arguments: ['%app.root%', '%site.path%', '@cache_tags.invalidator.checksum']

```

This is Drupal 9 code not working in Drupal 8.

The service argument `@app.root` on the other hand is not causing this error. You find it in Drupal Console or other Drupal 8 code. It was deprecated in Drupal 9, but is still working until you update to Drupal 10. Then it will be this error "Non-existent service" errors after clearing the cache

See the change record https://www.drupal.org/node/3080612.

# Answer
> 3 votes
The *app.root* parameter has been added in Drupal 9 to replace the *app.root* service. If you are using Drupal 8, that error could possibly be causes by:

* A module that says to be compatible with Drupal 8 and Drupal 9, whose code accesses the *app.root* container parameter when it runs on Drupal 8
* Other code that tries to access the *app.root* container parameter when it runs on Drupal 8

This could happen because:

* One of the arguments for a service is `'%app.root%'` (which requires the container parameter) instead of `'@app.root'` (which requires the service that exists in Drupal 8.x)
* There is code that uses `$container->getParameter('app.root')` instead of `$container->get('app.root')`
* There is code that checks whether to use the *app.root* container parameter or the *app.root* service, but it fails to use the available one

To understand which code causes the error, it should be sufficient to search for *%app.root%* or *-\>getParameter('app.root')*. Searching for *app.root* isn't sufficient, as it would return any line that correctly uses the *app.root* service.

\[Symfony 5\] Replace app.root and site.path string services with container parameters has been created has been created on August 13, 2019 and marked as fixed on December 23, 2020. (The patch was committed on Drupal 9.x on March 5, 2020.)
Drupal Console 1.9.4 (released on November 11, 2019) should not contain code that accesses the *app.root* container parameter, as Drupal core didn't even have that container parameter when Drupal Console 1.9.4 was released.

---
Tags: 8, dependency-injection
---


# Question
Title: How can I enable workflows for comments?
I would like to create workflows for comments and moderate them, but I can't find comments under *This workflow applies to:* on /admin/config/workflow/workflows/manage/comment\_workflow.

Does anyone know how I can enable workflows on comments?

# Answer
TLDR: Without a module that implements workflows for the Comment entity, you cannot.

The *Workflow* module doesn't implement any workflow: It's an API module other modules can use to implement their workflows.
An example of this is the *Content moderation* module, the only Drupal core module that implements workflows. Its workflows only apply to *Custom block types* and *Content types*, as shown in /admin/config/workflow/workflows/manage/editorial.

>

Even when you create a new *Content moderation* workflow, *Comment types* isn't an option listed under *This workflow applies to*.
> 1 votes

---
Tags: 9, comments, workflows
---


# Question
Title: Drupal Commerce Product Variation SQL Injection Vulnerability
A PCI scan on my site is saying that there is a SQL Injection vulnerability. But where it seems to be indicating it is on pretty basic Commerce functionality. When visiting a product variation page directly, it appends `v=nn` to the URL to show the selected variation.

This scan is suggesting that URLs like:

```
?v=54+or+5459%3D5459&page=1

?v=54+or+6721%3D8812&page=1

```

... return TRUE and FALSE, respectively (return where, I'm not really sure).

This is all pretty default behavior of Drupal Commerce if I'm not mistaken. Is it possible that this is a false positive from this PCI scan?

I know I haven't added any custom queries to this site. Other than theming, it's pretty out-of-the-box behavior. And I don't think I'm using the v= parameter directly in any of my theming.

I'm sorry this is vague and general, but looking for some more information on how to address this PCI result.

Thanks in advance!

# Answer
`?v=54+or+5459%3D5459&page=1` and `?v=54+or+6721%3D8812&page=1` would allow SQL injection if the code running the query would use the values passed in the URL without filtering them, as the following code, for example. (It's not the code the module is using. It's just code that would allow an SQL injection.)

```
$statement = "select * from product_variation pv WHERE pv.id = {$_GET['v']}";

```

The SQL queries would be essentially equivalent, respectively, to the following ones.

```
select * from product_variation pv where pv.id = 54 or 5459 = 5459

```

```
select * from product_variation pv where pv.id = 54 or 6721 = 8812

```

The first SQL query would return all the rows in the *product\_variation* database table, while the second query would return only the row for which the ID is equal to 54.

Drupal core and contributed modules don't concatenate values passed from the user (even through the URL) with literal strings to build the SQL string, but use proper argument substitution, making SQL injection not possible.
They don't also allow users to provide any operator to a query's condition, but set a list of allowed operators and only allow users to use those.

The PCI scan noticed it got two different results (`TRUE` and `FALSE`) using `?v=54+or+5459%3D5459&page=1` and `?v=54+or+6721%3D8812&page=1`, interpreted `TRUE` as *there are rows matching the query* and `FALSE` as *there aren't rows matching the query*, and thought the SQL injection was successful. (How the PCI scan can say that accessing URLs containing those query parameter would return `TRUE` and `FALSE` is not clear to me either.)

That is not what happened. What reported by the scan is a false positive.
> 3 votes

---
Tags: commerce, security
---


title: Entity is of bundle values in Rules

text:
# Question
Title: Entity is of bundle values in Rules
I've created a very basic "reaction rule" on "After updating a order".

I can't figure out what I need to fill in for: "Entity is of bundle" for the fields if I want to get Order fields:

1. Type
2. Bundle

I have tried all variants like "Type= Order" and "Bundle= default" etc, but it just doesn't work.

Anyone has it working with Entity is of bundle for Commerce Order?

# Answer
I've finally found it.

1. Type= commerce\_order
2. Bundle= default

I'll leave it here in case anyone searches for it. It is not documented anywhere.
> 0 votes

---
Tags: rules, 9
---


# Question
Title: Cannot get hook for custom twig template to work
I have a custom template with the following twig file:

views-view-unformatted--offices\_contact\_us\_page\_.html.twig

The view is added as part of extra fields module inside of a Drupal paragraph. I have tried everything but simply cannot get the hook to work, however, the .theme file is loaded correctly as I can add an exit to the preprocess\_page() function and that works.

I have tried:

1. \_preprocess\_views\_view\_unformatted()
2. \_preprocess\_views\_view\_unformatted\__offices\_contact\_us()
3. \_proprocess\_node()
4. \_preprocess\_views()

I am able to inject my variables through the \_preprocess\_page, but then the variable is not available inside the above view, so need to alter that hook. Any ideas as to what I am doing wrong or alternatively is there a way for me to "print" all hooks that are loaded (like their names) during the request so that I can better determine what I am doing wrong?

# Answer
you can try to debug a possible hook name. To do this, you should enable Twig templates debugging. You can enable it in a next way:

1. Open the sites/default/services.yml file. If you don't have it - copy sites/default/default.services.yml into sites/default/services.yml.
2. Find twig.config -\> debug parameter, set it as 'true', and save the file.
3. Clear caches and refresh the page.

Then, please open the browser inspector, and try to find the comment to your template file. You'll see something like this:  THEME HOOK from the comment is the correct one for debugging.
So your preprocess function name should consist of: theme name, "preprocess" word + theme hook from the comment:

```
THEME_NAME_preprocess_THEME_HOOK

```
> 0 votes

---
Tags: theming, hooks, 9
---


title: Search Api display search term in form

text:
# Question
Title: Search Api display search term in form
How do I display the search term after I have run the search.

Here is my form:

```
<input data-drupal-selector="edit-search-api-fulltext" id="edit-search-api-fulltext"  placeholder="Keyword" name="search_api_fulltext" value="{{ content.search_api_fulltext }}" class="regular-input" type="text">
<input data-drupal-selector="edit-submit-search" id="edit-submit-search" placeholder="Search" value="Search" class="btn secondary-btn js-form-submit form-submit" type="submit">

```

The value is not displaying anything, but I can't find an answer to what I should place here. Before installing Search Api I used {{ content.search\_query }} and that displayed the search term after the search was performed using the out-of-the-box Drupal search.

# Answer
> 0 votes
I'm using Drupal 9, and I had to create a variable in the theme and use it in my custom form template

In mytheme.theme

```
function hook_theme_preprocess(&$variables, $hook) {
  $variables['search_term'] = \Drupal::request()->query->get('search');
}

```

In my customtemplate.twig

```
<input value="{{ search_term }}" >

```

---
Tags: 8, search
---


# Question
Title: Is it possible to modify help text on a vocabulary page?
I am using a custom way of managing relations between terms in a particular vocabulary so I want to disable (or at least hide) the built-in functionality allowing terms to be placed in a hierarchy.

I have managed this to some extent with CSS (managed by the module that also does the custom relations). I have removed the "Relations" section from the taxonomy term edit form and I have removed the handles from the vocabulary list so that you cannot move the terms around and place them in a hierarchy that way. But I cannot see how to get rid of, or alter, the help text which says "You can reorganize the terms in Topic using their drag-and-drop handles, and group terms under a parent term by sliding them under and to the right of the parent.".

The problem is that there are no containers around this to identify which vocabulary is being adminstered, or indeed that it is on a taxonomy vocabulary list page at all. I have read the Drupal 8 docs on attaching libraries and they all say that targeting pages by URL is deprecated.

I suspect hook\_form\_alter would not work either as it is outside of the form tags.

Is there any way to do this?

# Answer
> 0 votes
I ended up achieving this in a rather round-about way but I could not see a more straightforward way to do it.

Following the second part of bleen's answer I looked at `hook_help` but I found that this appended my text to the default help text, rather than replacing it.

To hide the default help text and "replace" it with my own, I did this:

First, in the php for my module, I used `hook_module_implements_alter` in order to place my implementation, not last as bleen suggests, but first, so that the html it generates appears *before* the default help text:

```
function topic_relations_module_implements_alter(&$implementations, $hook) {
 if ($hook == 'help') {
    $implementations = array('topic_relations' => $implementations['topic_relations']) + $implementations;
  }
}

```

Then I specified the help text, with an id for ease of css selection:

```
function topic_relations_help($route_name, $route_match) {
  if  ($route_name == "entity.taxonomy_vocabulary.overview_form") {
    return "<p id='replacement_taxonomy_help'>The default functionality for arranging terms into a hierarchy has been overridden by the custom module 'Topic Relations'. </p>";
  }
}

```

Then in the css I used the sibling selector to hide the paragraph that comes *after* the one I inserted. (There is no previous-sibling selector, which is why I had to mess with the order of implementation).

```
#replacement_taxonomy_help ~ p {
  display: none;
}

```

# Answer
> 3 votes
When creating a vocabulary you have the option of turning on/off the ability to arrange terms in a hierarchy. If you choose "Single Hierarchy" for example then the help text will change to read: "VOCAB contains terms grouped under parent terms. You can reorganize the terms in VOCAB using their drag-and-drop handles."

See http://cgit.drupalcode.org/drupal/tree/core/modules/taxonomy/taxonomy.module#n78

... Otherwise you can create a custom module that implements hook\_help and check for $route\_name = entity.taxonomy\_vocabulary.overview\_form. As long as your module's hook\_help fires after taxonomy\_help() your's should win. See https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Extension%21module.api.php/function/hook\_module\_implements\_alter/8.4.x to control whose module wins when implementing a hook

# Answer
> 0 votes
My solution is similar to the one of naomi, but it removes the help text instead of hiding it, see following example code from MY\_MODULE.module.

Example: Removing help text of block\_content module for the route `entity.block_content.collection`:

```
/**
 * Implements hook_module_implements_alter()
 */
function MY_MODULE_module_implements_alter(&$implementations, $hook) {
  // Don't invoke block_content_hook(), to not show help texts from that module.
  if ($hook === 'help' && isset($implementations['block_content'])) {
    unset($implementations['block_content']);
  }
}

/**
 * Implements hook_help().
 */
function MY_MODULE_help($route_name, RouteMatchInterface $route_match) {
  // Re-add all help text from block_content_help() except for route
  // entity.block_content.collection.
  if ('entity.block_content.collection' !== $route_name) {
    return block_content_help($route_name, $route_match);
  }
}

```

There is a drupal.org issue for that, see Allow for altering help displayed by other modules. But as stated there:

> it seems that hook\_help() is likely to get deprecated, even if there is no definitive decision yet (see #3031642: Deprecate hook\_help() and combine with Topics).

---
Tags: theming
---


# Question
Title: Hide node created messages programmatically
I'm trying to the node created messages for a certain content type, but I can't use Disable Messages because it has a conflict the Commerce Add to Cart Confirmation module.

All the other methods (like the ones here) I've found either hide all status messages, or hide all status messages after a content type is created, which are inappropriate for me since I'm using rules to show a messages after a node is created, but I need to hide the default "\__________ has been created" message, and I appreciate any help you can offer me.

# Answer
> 7 votes
`drupal_set_message` is not hookable. But the message you want removed comes from `node_form_submit`, so you can get rid of it using `hook_form_FORM_ID_alter` on `node_form`. Either replace `node_form_submit` as form's submit handler with it's clone, sans messages, or set second handler that will remove what you want removed from `$_SESSION['messages'][$type]`.

# Answer
> 2 votes
While I was searching for solutions before I received the helpful reply from Mołot, I've found this module that fits my needs: Custom Submit Messages

It allows me to customise or remove any node creation, update, or deletion message in the content type-\>edit form.

(I had to disable messages displayed with Rules "*After a node is created*" to make it work as intended)

I appreciate your time and advice, but I've decided to go ahead with this because I plan to modify many more messages, the way this module allows and it will allow me to save a lot of time from doing it programatically.

# Answer
> 2 votes
Another way to accomplish this programmatically is to insert `drupal_get_messages('status');` after you call your save function.

```
$wrapper->save();
drupal_get_messages('status');
drupal_set_message('New Custom Message... or no message at all'));

```

Note that ANY status messages will be caught by this, not just the one generated by the save function, so use it cautiously as it may have unattended affects.

# Answer
> 2 votes
Molot's answer concerning unsetting certain elements of $\_SESSION\['messages'\] in an additional form submit handler was the best solution for me. One thing I struggled with was adding the custom handler appropriately -- not just to $form\['#submit'\]\[\]. The following code works great for me:

```
function MY_MODULE_form_FORM_ID_form_alter(&$form, &$form_state, $form_id) {
  $form['actions']['submit']['#submit'][] = 'MY_MODULE_NODE_TYPE_remove_message';
}

function MY_MODULE_NODE_TYPE_remove_message(&$form, &$form_state) {
  foreach ($_SESSION['messages']['status'] as $key => $value) {
    if (strpos($value, 'STRING UNWANTED MESSAGE BEGINS WITH') === 0) {
        unset($_SESSION['messages']['status'][$key]);
    }
  }
}

```

# Answer
> 0 votes
I came across this question while researching how to hide the status update message in Drupal 9. The answers here have been deprecated as of 8.5+ in favor of \Drupal::messenger().

Into your custom module:

```
function HOOK_form_alter (array &$form, &$form_state, $form_id) {
if($form_id == 'NODE_ID') {
$form['actions']['submit']['#submit'][] = 'MY_SUBMIT_FUNCTION';
}
}

function MY_SUBMIT_FUNCTION($form, FormStateInterface $form_state) {
$messenger = \Drupal::messenger();
$messenger->deleteByType($messenger::TYPE_STATUS);
}

```

# Answer
> -1 votes
You can do this in custom module:

```
/**
 * Implements hook_form_alter().
 */
function custommodule_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == "article_node_form") {
    //For article content type
    $form['actions']['submit']['#submit'][] = 'custommodule_custom_submit';
  }
}

function custommodule_custom_submit() {
  if (in_array("sellers", $user->roles)) {
    //sellers - For specific user role
    unset($_SESSION['messages']);
  }
}

```

# Answer
> -2 votes
http://xandeadx.ru/blog/drupal/729

Change

```
$_SESSION['messages']['status'][$old_message_key] = 'Текст нового сообщения';

```

to

```
unset($_SESSION['messages']['status'][$old_message_key]);

```

---
Tags: 7, status-messages
---


# Question
Title: security updates reported but not actually available (recommended==installed)
I installed Drupal 9.3.6.

At `/admin/reports/status`, I see the error:

> There are security updates available for one or more of your modules or themes

and at `/admin/modules/update`, two modules are listed: PHP 8.x-1.1 and Remote Stream Wrapper 8.x-1.5.

However, for both these modules the recommended version is the already-installed version.

* How do I see more details about the reason for the errors?
* Alternatively, can I make Drupal ignore these two modules?

# Answer
*There are security updates available for one or more of your modules or themes* isn't the more appropriate message that is correct in every case. It assumes that, once a release has been marked as insecure, a new release is created, but that doesn't always happen, for example because the project owner or one of the maintainers failed to fix the security issue.

In the specific case:

Implementing `hook_update_status_alter()` in a module, you can set those modules as ignored.

```
use Drupal\update\UpdateFetcherInterface;

function mymodule_update_status_alter(&$projects) {
  if (isset($projects['php'])) {
    $projects['php']['status'] = UpdateFetcherInterface::UNKNOWN;
    $projects['php']['reason'] = t('MyModule prevents Drupal from receiving information about module updates .');
  }
  if (isset($projects['remote_stream_wrapper'])) {
    $projects['remote_stream_wrapper']['status'] = UpdateFetcherInterface::UNKNOWN;
    $projects['php']['reason'] = t('MyModule prevents Drupal from receiving information about module updates .');
  }
}

```
> 1 votes

# Answer
Sometimes Drupal messages regarding module updates can be outdated and can be fixed by manual check for updates from the /admin/reports/updates page:

Also, some error messages can be shown because of the "Remote Stream Wrapper" module's status:

To avoid receiving such messages you can:

1. Uninstall the Update MAnager module.
2. Try to use the hook\_update\_projects\_alter
> 0 votes

---
Tags: updating, security
---


# Question
Title: How can I load the last nine created nodes?
I want to get the latest nine nodes in a preprocess hook. I am using the following code, but it returns all the *news* nodes.

```
$entities = \Drupal::entityTypeManager()->getStorage('node')->loadByProperties(['type' => 'news']);

```

Is it possible to load only the last nine created nodes using `loadByProperties()`?

# Answer
`loadByProperties()` just loads entities given the value of some of their properties. For more complex queries, which (for example) sort the returned nodes basing on some criteria, or return the last X entries, you need to use the object returned by `\Drupal::entityQuery()`.

```
$query = \Drupal::entityQuery('node');
$query->accessCheck(FALSE)
  ->condition('type', 'news')
  ->sort('changed', 'DESC')
  ->range(0, 9);

$nids = $query->execute();

```

`$nids` will contain an array of node IDs you can use to load the nodes, for example with `\Drupal::entityTypeManager()->getStorage('node')->loadMultiple($nids)`.

I used `accessCheck(FALSE)` to avoid Drupal would return only the nodes to which the currently logged-in user has access. To let Drupal return only the nodes to which the currently logged-in user has access, that line must be removed.
> 6 votes

---
Tags: nodes, 9
---


# Question
Title: How do I get the edited paragraph in hook_field_widget_WIDGET_TYPE_form_alter()
I use hook\_field\_widget\_WIDGET\_TYPE\_form\_alter() to alter the form for a single paragraph. What I do not understand is how I know which paragraph currently is edited when this hook is called. The problem: I want to change the default value for a field of the paragraph but only when no field value was set so far. So only when the paragraph gets created the default value should be changed as it is another default value when the paragraph is added within a node of a specific type.

I get the node with

```
$node = $build_info["callback_object"]->getEntity();

```

but then I do not know how to get the actually edited paragraph from here. It seems that nowhere in $form or $formState is the paragraph entity stored which is currenty edited?!

# Answer
Isn't there a context variable containing the field items? If not please share more code.

If yes, you can get the field data through the field properties. In case of a reference field the first referenced entity

```
$paragraph = $context['items']->entity;

```

In Drupal 9 the widget hooks were streamlined.

Get a specific delta of an entity reference field

```
function mymodule_field_widget_single_element_WIDGET_TYPE_form_alter(&$element, FormStateInterface $form_state, $context) {
  $items = $context['items'];
  $delta = $context['delta'];
  $entity = $items[$delta]->entity;
  ...
}

```
> 2 votes

---
Tags: 9, paragraphs
---


title: image.html.twig naming sugestions

text:
# Question
Title: image.html.twig naming sugestions
I need to customize the *image.html.twig* template. I have a new content type with an image field (*field\_tile\_image*). How can I overwrite the default image template only for one block?

I tried different naming but it's still using *image.html.twig*. There aren't other name suggestions.

# Answer
> 1 votes
The image.html.twig file does not have any names suggestions by default. Then you have to add it yourself. You can do it using hook\_theme\_suggestions\_alter.

Also, here's an example of this hook usage:

```
/**
 * Implements hook_theme_suggestions_alter().
 */
function MY_THEME_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
  if ($hook == 'taxonomy_term') {
    $term = $variables["elements"]["#taxonomy_term"];
    $vid = $term->get('vid')->target_id;
    $view_mode = $variables["elements"]["#view_mode"];

    $suggestions[] = $hook . '__' . $view_mode;
    $suggestions[] = $hook . '__' . $vid . '__' . $view_mode;
  }
}

```

You can read more about it here:
https://www.drupal.org/docs/theming-drupal/twig-in-drupal/working-with-twig-templates
and here:
https://www.drupal.org/docs/theming-drupal/twig-in-drupal/twig-template-naming-conventions

---
Tags: theming, media
---


title: Change product price title in form

text:
# Question
Title: Change product price title in form
How can I access the label of the product price field to change it for example to "amount" instead of "price"?

The html for the field is:

```
<div class="js-form-item form-item js-form-type-commerce-number form-item-variations-entity-price-0-number js-form-item-variations-entity-price-0-number">

<label for="edit-variations-entity-price-0-number" class="js-form-required form-required">Price</label>

<input data-drupal-selector="edit-variations-entity-price-0-number" type="text" id="edit-variations-entity-price-0-number" name="variations[entity][price][0][number]" value="" size="10" maxlength="128" class="form-text required" required="required">

```

I have tried various alternatives, but couldn't find a way to reach the title or the price field.

```
function THEME_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
    $form['variations']['entity']['price'][0]['number']= t('Amount');
    $form['variations']['entity']['price']['number']= t('Amount');
    $form['price']= t('Amount');
}

```

I also couldn't find any examples to use form\_alter on Drupal 8 Commerce product form while it was possible with Drupal 7.

# Answer
> 1 votes
```
$form['variations']['widget']['entity']['price']['widget'][0]['#title'] = t('Amount');

```

---
Tags: 8, commerce
---


title: Update Alias Programmatically

text:
# Question
Title: Update Alias Programmatically
I have a large website with 240 urls that need to be updated. I would like to do this programmatically to avoid making errors. I created the following function which seems to work. There seems to be a good bit of complexity here for what I am trying to accomplish. Is there a simplier way to update the url of a node?

```
function alias_replace($path, $lang, $new_alias) {

  $path_alias_manager = \Drupal::entityTypeManager()->getStorage('path_alias');

  $alias_objects = $path_alias_manager->loadByProperties([
    'path'     => $path,
    'langcode' => $lang
  ]);

  foreach($alias_objects as $alias_object) {
    $alias_object->delete();
  }

  $path_alias_manager->create([
    'path'     => $path,
    'alias'    => $new_alias,
    'langcode' => $lang
  ])->save();

}

```

# Answer
> 3 votes
A slightly simpler way I found is that you don't need to delete and create the alias object as you can just update its object properties in place with `->save()` like this:

```
function alias_replace($path, $lang, $new_alias) {

  $path_alias_manager = \Drupal::entityTypeManager()->getStorage('path_alias');

  $alias_objects = $path_alias_manager->loadByProperties([
    'path'     => $path,
    'langcode' => $lang
  ]);

  foreach($alias_objects as $alias_object) {
    $alias_object->alias = $new_alias;
    $alias_object->save();
  }
}

```

---
Tags: 8, path-aliases
---


# Question
Title: Generate static files of specific nodes with Tome
I'm looking for a way to generate a static version of specified nodes ( in my case they are book nodes pages).

I want to do it periodically in my custom Drupal cronjob,

most of the Drupal static modules are obsolete and there is no version for **Drupal 9.**

I found TOME module but looks like it's mostly for generating full website static generation through admin panel or `drush` command line.

I tried `drush tome:static-export-path /mybookpath --uri=localhost:8080` but it's blindly going through all the links on the pages and download all of them.

with digging more into the documentation I found this which is good to use tome services. in this case, there is no URI parameter option( it's only available for drush command) and it does not replace URLs ( image,link, style ( css) urls) and use the main version.

```
    <?php

/** @var \Drupal\tome_static\StaticGeneratorInterface $static */
$static = \Drupal::service('tome_static.generator');

/** @var \Drupal\tome_static\RequestPreparer $request_preparer */
$request_preparer = \Drupal::service('tome_static.request_preparer');

// Prepare for a new request. This is necessary so that static caches in Drupal
// can be reset between multiple requests in one bootstrap.
$request_preparer->prepareForRequest();

// Request an arbitrary path. "$invoke_paths" at this point is anything that
// needs to be copied (an existing file) or requested (an image derivative,
// other paths, etc.)
$invoke_paths = $static->requestPath('/foo');

// Export paths will try to copy or remove as many paths as possible without
// making a new internal request.
$invoke_paths = $static->exportPaths($invoke_paths);

// The remaining invoke paths need to be handled in new requests.
foreach ($invoke_paths as $path) {
  // Since we are only trying to export one path, restrict new requests to
  // paths with extensions, which are probably RSS feeds and image derivatives.
  if (pathinfo($path, PATHINFO_EXTENSION)) {
    $request_preparer->prepareForRequest();
    // This could return more paths, but we're ignoring that for simplicity.
    $static->requestPath($path);
  }
}

```

**My question:** What is the best solution to generate static HTML files will all assets of specific Drupal nodes?

# Answer
> 0 votes
I used Tome and with the following function I implement custom path fetching

```
public static function storeFileLocally($uri) {
$base_url = "http://localhost:8080";
$path = $uri;
/** @var \Drupal\tome_static\StaticGeneratorInterface $static */
$static = \Drupal::service('tome_static.generator');

/** @var \Drupal\tome_static\RequestPreparer $request_preparer */
$request_preparer = \Drupal::service('tome_static.request_preparer');

TomeStaticHelper::setBaseUrl(\Drupal::request(), $base_url);

$request_preparer->prepareForRequest();
$invoke_paths = $static->requestPath($path);

$invoke_paths = $static->exportPaths($invoke_paths);

foreach ($invoke_paths as $path) {
  if (pathinfo($path, PATHINFO_EXTENSION)) {
    $request_preparer->prepareForRequest();
    $static->requestPath($path);
  }
}

```

}

# Answer
> 0 votes
You can always recreate static pages with `wget`.

```
wget --mirror --convert-links --show-progress --content-disposition http://example.edu

```

This will create a copy of the entire site. I believe you can adjust the URL to be a specific node.

---
Tags: 9
---


# Question
Title: SymfonyTestsListener does not exist on PHP Unit Test
When I try to run a unit test I get an error that SymfonyTestsListener does not exist. Am I running this correctly?

```
../../vendor/bin/phpunit -c phpunit.xml ../modules/custom/my_module/

Class "Symfony\Bridge\PhpUnit\SymfonyTestsListener" does not exist

```

I am using PHPUnit 6.5.13.

# Answer
> 19 votes
Had a similar issue: Solved it by adding the "symfony/phpunit-bridge": "^3.4.3" library.

# Answer
> 5 votes
Removing the line below in `phpunit.xml` fixes my issue:

```
<!-- The Symfony deprecation listener has to come after the Drupal listener -->
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener">
</listener>

```

Not sure if this will cause any issues.

# Answer
> 4 votes
Although the approved answer here shows the exact package that is needed what users may be looking for is to require the "drupal/core-dev" package which contains the needed "symfony/phpunit-bridge" as a dependency.

# Answer
> 0 votes
Try using symfony/phpunit-bridge:

`composer require --dev symfony/phpunit-bridge`

This will install the phpunit-bridge that is used with phpunit, it fixed the issue for me.

---
Tags: testing
---


# Question
Title: Cannot get any output when passing array through preprocessor
In my preprocessor I assign the following:

```
$variables['myVar'] = "value";

```

And in my twig file I can do the following and I get the value printed:

```
{{ myVar }}

```

If I however assign an array like this in my preprocessor:

```
$variables['myVar'] = ['name' => 'John','surname' => 'Doe'];

```

I am not able to get any output either through the outputting the variable, doing a dump or even trying to run it through a for loop:

```
{{ dump('myVar') }}
{% for items in myVar %}

```

I have cleared cache as well. Any ideas would be welcome :)

# Answer
> 0 votes
in THEME.theme

```
function THEME_preprocess_page(&$variables)
{
  $variables['myVar'] = ['name' => 'John','surname' => 'Doe'];
}

```

in page.html.twig

```
name: {{ myVar.name }}
surname: {{ myVar.surname }}

```

or array iteration

```
{% for key,var in myVar %}
{{ key }}: {{ var }}
{% endfor %}

```

---
Tags: 9
---


# Question
Title: Is there a way to avoid CkEditor is used for some form elements, for example the body form element used for nodes?
I enabled the CkEditor module, which is now affecting all the form elements with a summary and a input format fields.

Is there a way to avoid CkEditor is used for some form elements, for example the body form element used for nodes?

# Answer
> 5 votes
The problem you experienced with configuring the field is that in core there is no option to select the allowed text formats. When this module is installed

https://www.drupal.org/project/allowed\_formats

you can select the text format that is available for a specific field and then you can choose in the settings of the text format whether to use ckeditor or not.

There is work going on to put this in core: https://www.drupal.org/node/784672

# Answer
> 0 votes
For body you can use next code:

```
function YOURMODULE_form_node_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'YOUR_FORM_ID'){
    $form['body']['widget']['#after_build'][] = '_remove_body_wysiwyg';
  }
}

function _remove_body_wysiwyg($form_element, \Drupal\Core\Form\FormStateInterface $form_state) {
  if (isset($form_element[0]['#pre_render'])) {
    unset($form_element[0]['#pre_render']);
  }
  return $form_element;
}

```

---
Tags: 8, forms, wysiwyg
---


title: Using Twig template to generate a PDF

text:
# Question
Title: Using Twig template to generate a PDF
I am trying to generate a Twig template for the Attachment PDF item in a webform. I am able to automatically generate a label and field data using : `{{ webform_token('[webform:element:to]', webform) }} : {{ data.to }}`

I am trying to figure out how I can get access to the rest of the webform settings such as the labels of the different fields: `{{ webform_token('[webform_submission:created]', webform_submission) }}`

What if I want to display the title of the form only using label:value? I know I can use : `{{ webform_token('[webform_submission:label]', webform_submission) }}` but this gives The form name with Submission No attached to the end. I need the form name only.

Is there a command or a setting I can use to get a list of all available settings and fields in the webform?

Sorry if this is not clear enough. Thanks

# Answer
> 0 votes
I figured how to accomplish what I wanted. It is simply a matter of selecting the proper token :) in this case `{{ webform_token('[webform_submission:webform:title]', webform_submission) }}`

---
Tags: webforms
---


# Question
Title: How do I get the type of a "Custom block" entity?
I created two custom block types.

>

How do I retrieve the type of custom block in `hook_theme_suggestions_block_alter()`?

```
function mytheme_theme_suggestions_block_alter(array &$suggestions, array $variables) {
  if (isset($variables['elements']['content']['#block_content'])) {
    // $variables['elements']['content']['#block_content']->getEntityTypeId() returns 'block_content'.
  }
}

```

# Answer
```
  if (isset($variables['elements']['content']['#block_content'])) {
    array_splice($suggestions, 1, 0, 'block__bundle__' . $variables['elements']['content']['#block_content']->bundle());
  }

```
> 2 votes

# Answer
Use the `bundle()` function

EntityInterface::bundle

This applies to every entity, no matter if node, user or custom content block
> 2 votes

---
Tags: blocks, 9
---


# Question
Title: HTML not rendered in text field content type
In my content type, I have a text field that will display a string (max 200 characters) in a Bootstrap card. Due to the design, we have to allow the user to add a \< br /\> or \ n to add "invisible lines" to ensure content is wrapped correctly in the card.

By adding "\< br /\> to the field however, in twig, the \< br /\> is printed to screen and not HTML rendered. I have tried:

```
<p>{{content.field_copy}}</p>
<p>{{content.field_copy|raw}}</p>
<p>{{content.field_copy|render}}</p>

```

With no affect. What other options do I have? Can this be done using a text field?

# Answer
> 0 votes
it's bad practice, but still

```
{{ content.field_copy.0['#context'].value|raw }}

```

---
Tags: 9
---