# Question
Title: How do I invalidate the cache of an entity?
Is there any easy way to clear the cache for a custom entity? I know there is an entry in the cache\_entity-Table. If i manually delete it, everything is fine. I tried doing the same as in `\Drupal\Core\Entity->invalidateTagsOnSave()` or `\Drupal\Core\Entity->invalidateTagsOnDelete()`. This does not seem to change anything.

Unfortunately I can't just load the entity and resave it in this situation.

# Answer
> 16 votes
But you know the entity ID that you want to have invalidated?

Then use `\Drupal::entityTypeManager()->getStorage($entity_type_id)->resetCache([$id]);`

# Answer
> 6 votes
To invalidate a cache you should use the Drupal cache invalidator service : `cache_tags.invalidator`.

## Static call

```
// Invalide a Node cache.
\Drupal::service('cache_tags.invalidator')->invalidateTags(['node:5']);
// Invalidate a custom entity cache.
\Drupal::service('cache_tags.invalidator')->invalidateTags(['custom_entity:5']);
// Invalidate a custom cache tag.
\Drupal::service('cache_tags.invalidator')->invalidateTags(['thing:identifier']);

```

## Dependency injection call

my\_module.services.yml

```
services:
  hello.service:
    class: \Drupal\my_module\Service\Hello
    arguments:
      - '@cache.default'
      - '@cache_tags.invalidator'

```

Hello.php

```

use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheTagsInvalidator;

class Hello {

 /**
   * Cache backend.
   *
   * @var Drupal\Core\Cache\CacheBackendInterface
   */
  protected $cacheBackend;

 /**
   * Cache tags invalidator.
   *
   * @var Drupal\Core\Cache\CacheTagsInvalidator
   */
  protected $cacheInvalidator;

  /**
   * {@inheritdoc}
   */
  public function __construct(
    CacheBackendInterface $cacheBackend,
    CacheTagsInvalidator $cacheInvalidator
  ) {
    $this->cacheBackend = $cacheBackend;
    $this->cacheInvalidator = $cacheInvalidator;
  }

  /**
   * Function getting something from cache.
   */
  public function getSomething() {
    $cid = 'thing:identifier';
    $data = NULL;
    $cache = $this->cacheBackend->get($cid);

    if ($cache) {
      $data = $cache->data;
    }
    else {
      $data = my_module_complicated_calculation();
      $this->cacheBackend->set(
        $cid,               // Cache tag identifier.
        $data,              // Data to store in cache.
        Cache::PERMANENT,   // Save permanently.
        ['node:5', 'user:7']// Automatically invalidated if these entities are modified.
      );
    }

    return $data;
  }

  /**
   * Function invalidating a cache tag.
   */
  public function invalidateSomething() {
    $cid = 'thing:identifier';
    $this->cacheInvalidator->invalidateTags([$cid]);

    return;
  }
}

```

## Links

# Answer
> 3 votes
In your custom entity you should override the function

```
public function getCacheTagsToInvalidate();

```

of the EntityInterface.

Then, to clear that entity's cache you simply call

```
\Drupal\Core\Cache\Cache::invalidateTags($entity->getCacheTagsToInvalidate());

```

If you do not override getCacheTagsToInvalidate() the default implementation in entity.php should also work:

```
public function getCacheTagsToInvalidate() {
    if ($this->isNew()) {
      return [];
    }
    return [$this->entityTypeId . ':' . $this->id()];
  }

```

The tags\[\] is just the name plus the id.

---
Tags: 8, caching
---


# Question
Title: Is there a way to retain core search logging instead of having it get deleted with the watchdog logs?
We're using the core search module on a D9 site and use the "Top Search Phrases" report for search tracking but the results get stored in the watchdog table so they get cleared out when the logs do.

I see there are some D7 modules to improve the core search logs but nothing that I could find for D8.

The client needs to retain the search word logging so how could we do this on our D9 site?

# Answer
I don't know if there exists a module (off-topic anyway on this site), but you could try to implement your own cron hook. First disable the built-in clean up process by setting "Database log messages to keep" to "All" in the UI.

Then implement your own hook\_cron(), similar to the core hook

*/core/modules/dblog/dblog.module*

```
/**
 * Implements hook_cron().
 *
 * Controls the size of the log table, paring it to 'dblog_row_limit' messages.
 */
function dblog_cron() {
  // Cleanup the watchdog table.
  $row_limit = \Drupal::config('dblog.settings')->get('row_limit');

  // For row limit n, get the wid of the nth row in descending wid order.
  // Counting the most recent n rows avoids issues with wid number sequences,
  // e.g. auto_increment value > 1 or rows deleted directly from the table.
  if ($row_limit > 0) {
    $connection = \Drupal::database();
    $min_row = $connection->select('watchdog', 'w')
      ->fields('w', ['wid'])
      ->orderBy('wid', 'DESC')
      ->range($row_limit - 1, 1)
      ->execute()->fetchField();

    // Delete all table entries older than the nth row, if nth row was found.
    if ($min_row) {
      $connection->delete('watchdog')
        ->condition('wid', $min_row, '<')
        ->execute();
    }
  }
}

```

only that your hook keeps the search entries or moves them to a different table.
> 1 votes

---
Tags: search
---


# Question
Title: How to get the node from the url referer?
I have a custom entity named **Application** that has an **Entity Reference** field named **Product**.

When I am on an Apllication page and click on a **Product** to see it, I would like to know that I come from the **Application** page and know its **ID**.

This would allow me to display information from the **Application** page on the **Product** page.

But how to do it ?

# Answer
This method works for me:

```
use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\Url;
// Getting the referer.
$request = \Drupal::request();
$referer = $request->headers->get('referer');
// Getting the base url.
$base_url = Request::createFromGlobals()->getSchemeAndHttpHost();
// Getting the alias or the relative path.
$alias = substr($referer, strlen($base_url));
// Getting the node.
$params = Url::fromUri("internal:" . $alias)->getRouteParameters();
$entity_type = key($params);
$node = \Drupal::entityTypeManager()->getStorage($entity_type)->load($params[$entity_type]);

// To use dpm you need the devel module.
dpm($node->id());
dpm($node->title->value);

```
> 10 votes

# Answer
```
$previousUrl = \Drupal::request()->server->get('HTTP_REFERER');
$fake_request = Request::create($previousUrl);
$url_object = \Drupal::service('path.validator')->getUrlIfValid($fake_request->getRequestUri());
$route_name = $url_object->getRouteName();
$url = Url::fromRoute($route_name, $url_object->getRouteParameters());
$previousPath = $url->getInternalPath();

```
> 0 votes

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


# Question
Title: Do views filter plugins not apply to base field definitions?
I created a custom entity type that has a base field definition like this:

```
$fields['start_date'] = BaseFieldDefinition::create('datetime')
  ->setLabel(t('Start Date'))
  ->setDescription(t('The date and time to start.'))
  ->setDisplayOptions('view', array(
    'type' => 'datetime_default',
    'weight' => 3,
  ))
  ->setDisplayOptions('form', [
    'type' => 'datetime_default',
    'weight' => 3,
  ])
  ->setRequired(TRUE);

```

When I create a view that displays entities of this type, and try to create a filter on this base field, I get the generic filter provided by views, instead of the one defined in `Drupal\datetime\Plugin\views\filter\Date`.

Why is that?

# Answer
> 3 votes
Looks like this is a known major issue. Here's the main "parent" issue where most of the work is going down: https://www.drupal.org/node/2337515

I think, by default, there is some basic views integration for all entities, but it's not that robust.

As a workaround, I was able to implement hook\_views\_data\_alter to tell views to use the 'datetime' filter plugin instead of the default 'string' plugin it had.

```
function MY_MODULE_views_data_alter(array &$data) {
  $data['my_entity_type']['start_date']['filter']['id'] = 'datetime';
}

```

# Answer
> 0 votes
An entity type can be revisionable and translatable and in these cases, the table name will not be `entity_type`. Check the `@ContentEntityType` annotation on the entity class for `data_table` and `revision_data_table` keys.

Also, the `ListField` Views filter class needs `field_name` set.

Here's a working example for a base field set on `media`:

```
function sd8_media_views_data_alter(array &$data) {
  $data['media_field_data']['embed_status']['filter']['id'] = 'list_field';
  $data['media_field_data']['embed_status']['filter']['field_name'] = 'embed_status';
}

```

My field is not revisionable and so I didn't need to set the same on `$data['media_field_revision']` but if your field is, then you need that too. xdebug is very much your friend, put a breakpoint inside the `hook_views_data_alter` function and look at `$data`.

---
Tags: views, 8, entities
---


# Question
Title: Possible to fallback to a simple text format
We have to Textformats for the WYSIWYG editor:

* full html (intended for admins with html knowledge)
* simple html (for the non-tech editors)

Both can edit the node

However, if the admin save a field with full html, it is automatically blocked for the normal editors, as they have no permission for the "full html":

Is there a way, that the field is simply using "simple html" as fallback? It would be no problem if the markup got sanitised more then it would be with full html...

I found this old post from 10 years ago - maybe something has changed in the meantime?

# Answer
Alright, so I found the well maintained module allowed\_formats.

This actually solves my problem, as I can limit the format to simple html for those few fields, that the normal editors have access too.
> 2 votes

---
Tags: 9, wysiwyg
---


# Question
Title: How to hide text format options when using WYSIWIG module?
Using this tip I was previously hiding the text format options with

```
$form['und'][0]['format']['#access'] = FALSE;

```

When I enabled WYSIWYG it wouldn't show the editor and I had to use

```
$form['und'][0]['format']['format']['#access'] = FALSE;
$form['und'][0]['format']['guidelines']['#access'] = FALSE;
$form['und'][0]['format']['help']['#access'] = FALSE;

```

What's left now is this bottom box (below Path: p...)

This is the HTML that's generating it:

```
<fieldset class="filter-wrapper form-wrapper" id="edit-comment-body-und-0-format">
    <div class="fieldset-wrapper"><input id="edit-comment-body-und-0-format--2" class="wysiwyg wysiwyg-processed" type="hidden" name="comment_body[und][0][format]" value="filtered_html"></div>
</fieldset>

```

I could hide it with CSS. How would I hide it with code similar to above? Btw, I'm aware of Better Formats module but don't want to use it just for that.

# Answer
Try unsetting the field elements. According to the blog post this kills TinyMCE

```
<?php
  function [theme_name]_form_comment_form_alter(&$form, &$form_state, $form_id)
  {
    $form['comment_body']['#after_build'][] = 'remove_tips';
  }

  function remove_tips(&$form)
  {
    unset($form['und'][0]['format']['guidelines']);
    unset($form['und'][0]['format']['help']);
    return $form;
  }
?>

```

source: technonaturalist
> 3 votes

# Answer
There is also https://www.drupal.org/project/allowed\_formats, which allows to limit the formats per field.
> 0 votes

---
Tags: 7, wysiwyg
---


# Question
Title: Saving node with a text format another user doesn't have permission for renders it inaccessible
I have an editor role which has access to an editor Text format. I have an admin role which uses the Full HTML format.

When the admin edits a node and saves the body (or any other full text field) with their default text format, Full HTML, then the editor gets:

"This field has been disabled because you do not have sufficient permissions to edit it."

How can I allow the editors to simply have permission to edit this locked field with their own editor text format?

# Answer
> 4 votes
You can't I'm afraid.

Think about it like this: When rendering the text to screen, Drupal has to decide which text format to use to filter it. This means that per field, there must only be one text format, regardless of which users have edited it.

If this wasn't the case, Drupal would have no idea which format to use to render the text. It would have to guess, which is something you don't want a computer doing!

If you want users to be able to edit textarea fields, your admins will simply have to save them in a format that those users have permissions to use. Otherwise the whole point of having different filters available for different roles is kind of lost.

But the main point is that conceptually, if different users edit the same field, with different text formats, then Drupal has no idea which one to use when outputting the field value. This is why you cannot do it.

# Answer
> 0 votes
Now 10 years later, there is also https://www.drupal.org/project/allowed\_formats, which allows to limit text formats for a field to those, that everybody can use.

---
Tags: users, wysiwyg, input-formats
---


# Question
Title: Why don't I see Asset Injector code directly in the HTML?
I’m having trouble getting the Asset\_Injector module to work, and would like to find out why it's not working. As a simple test, I want to insert some CSS using the module’s CSS injector:

```
#container {
    max-width: 1000px;
    margin: 1em auto;
}

```

Asset\_Injector is configured with no restrictions on injection: content types, pages, etc. But when I create a page, then look at the source code, the CSS is not injected.

I’ve cleared the Drupal caches and the browser cache. I’m running a Drupal 9.4 site on Pantheon with Asset\_Injector 8.x-2.13.

To re-create the problem:

> Inline JavaScript is highly discouraged. It's recommended to put the JS you want to use inline in a file instead, because that allows JavaScript to be cached on the client side. It also allows JavaScript code to be reviewed and listed.

# Answer
> 3 votes
Asset Injector adds the custom CSS and JavaScript as libraries, which means these appear as attached assets. Asset Injector does not insert the CSS or JavaScript directly into the page HTML. That is the reason you do not see these items directly in the HTML.

---
Tags: javascript
---


# Question
Title: How to programmatically capture a payment?
Payment is in Authorized state. How do I programmatically capture it? I am using Authorize.net payment gateway.

# Answer
Figured it out on my own:

```
function capture_payment($order_id) {
  $order = Order::load($order_id);
  $payment_method_id = $order->payment_method->target_id;
  $payment = getPayment($payment_method_id);
  $amount = new Price($order->total_price[0]->number, $order->total_price[0]->currency_code);

  $gateway = \Drupal::entityTypeManager()
    ->getStorage('commerce_payment_gateway')->loadByProperties([
      'plugin' => 'authorizenet_acceptjs',
    ]);
  $plugin = $gateway['authorize_net_accept_js'];
  $payment_gateway_plugin = $plugin->getPlugin();

  $payment_gateway_plugin->capturePayment($payment, $amount);
}

function getPayment($method_id) {
  $payments = \Drupal::entityTypeManager()
    ->getStorage('commerce_payment')
    ->loadByProperties(['payment_method' => $method_id]);
  $payment = current($payments);
  return $payment;
}

```
> 1 votes

# Answer
To programmatically capture a payment using the Authorize.Net payment gateway, you will need to follow these steps:

1. Integrate your application with the Authorize.Net payment gateway. This will typically involve setting up an account with Authorize.Net, and installing their SDK or library in your application.
2. Create a payment form in your application that allows users to enter their payment details. This form will typically include fields for the user's credit card number, expiration date, and security code.
3. When the user submits the payment form, send a request to the Authorize.Net payment gateway to initiate the payment. This request will include the user's payment details, as well as any other relevant information such as the amount of the payment and the currency.
4. The payment gateway will process the payment, and send a response back to your application indicating whether the payment was successful or not. If the payment was successful, you can then capture the payment by sending a capture request to the payment gateway.

To send a capture request to the Authorize.Net payment gateway, you will need to use the `CaptureOnly` API method. This method requires the following parameters:

`x_trans_id`: The transaction ID of the authorization you want to capture. `x_amount`: The amount you want to capture. `x_invoice_num`: An optional invoice number for the capture. You can find more information on the `CaptureOnly` API method in the Authorize.Net documentation.

Keep in mind that these steps are just a general outline, and the specific details will vary depending on your specific implementation. It's important to consult the documentation and support resources provided by Authorize.Net to get more detailed information on how to use their APIs and functionality.
> -1 votes

---
Tags: commerce, 9
---


# Question
Title: "Mismatched entity and/or field definitions" after enabling contributed module
I installed the Rabbit Hole module in Drupal 9. I was immediately greeted with this message on the status page:

```
Mismatched entity and/or field definitions

The following changes were detected in the entity type and field definitions.
User
The Rabbit Hole action field needs to be installed.
The Rabbit Hole redirect path. field needs to be installed.
The Rabbit Hole redirect response code field needs to be installed.
The Rabbit Hole redirect fallback action field needs to be installed.

```

Everyone seems to say run devel entity-updates, but that module page itself says:

> The goal of this module is to have a quick way to apply schema updates while developing new entity types and ending up incrementally adding/removing/changing entity type/field definitions.
>
> When these changes are part of an official release (and not in the scope of a code development session), they should absolutely rely on DB update functions, as explained in the CR above, because that's the only way the entity schema update process can be predictable and reliable.
>
> For this reason, this module depends on Devel and is not meant to be enabled in production environments or relied upon in deployment workflows, see #3082442: Why not meant to be enabled in production environments? for more details.

So, it should not be used or ran in production? Running it locally produces no visible change to configuration exports. So how would you get this done on a production database?

Instead, people say these updates should occur in an update hook. What does that mean? Is this burden on the developer or the user to do? I have seen this from time to time with contributed modules, and do not understand if devel entity-updates will "fix" (**correctly** fix) this issue, or if there is a concrete way to do this change.

# Answer
> 1 votes
You don't get "Mismatched entity and/or field definitions" after installing/uninstalling a contrib module adding base fields to existing entities.

Steps to reproduce:

* composer require 'drupal/rabbit\_hole:^1.0@beta'
* enable Rabbit Hole main module and Rabbit Hole users submodule
* the table users\_field\_data contains the 4 new fields
* Status page is clear
* edit a user with individual rabbit hole settings to fill the fields with data
* check the database, data is stored
* uninstall the module
* fields are moved from users\_field\_data to separate field\_deleted\_data\_\* tables
* run cron
* field\_deleted\_data\_\* are purged from the database

If the module doesn't install/uninstall correctly like this, rollback and test it first on a local copy of the site until it works. Don't use a dev tool like devel entity-updates on production data. Even more so for a module still in beta changing core entity tables.

# Answer
> 0 votes
I was able to resolve this issue by doing the following:

1. Note the name(s) of the field(s) in the error message on the status page
2. Go to /admin/reports/fields and search for the field(s) in question
3. Click on the link in the "Used In" column for each field in question. That will take you to the "Manage fields" page for the content type where the field is used.
4. Click "Edit" next to the name of the field in question.
5. Click "Save" to update the field.

I didn't need to do anything other than click "Save". That resolved the error.

---
Tags: entities, 9
---


# Question
Title: What is the appropriate way to get items from an entityqueue?
I was having trouble finding API examples for entityqueue in Drupal 8.

I ended up writing a query to get the items.

```
$query = $this->database->select('entity_subqueue__items', 'esi')
  ->fields('esi', array('items_target_id'))
  ->condition('esi.bundle', $name_of_queue)
  ->orderBy('delta', 'ASC');

$nids = $query->execute()->fetchCol();

```

But I'd like to use a built in function if possible. Where's the function for retrieving items from an entity queue?

# Answer
Given $sid is your subqueue id:

```
$entity_subqueue = \Drupal::entityManager()->getStorage('entity_subqueue')->load($sid);

```

Loads the subqueue object. You can manipulate this to retrieve or update your entityqueue.

To get the items:

```
$items = $entity_subqueue->get('items')->getValue();

```

To update the items, add another item to the $items array and then save the entity object:

```
$items[] = ['target_id' => 69];

$entity_subqueue->set('items', $items);

$entity_subqueue->save();

```

Voila!

You can check in the database that your entity queue is updated:

```
select * from entity_subqueue__items where bundle = :sid;

```

I would like to also add that there is a great alternative to using entityqueue in Drupal 8: the Config Pages module. It allows you to create entity bundles that have only one entity. You can then add any field type you like, including entity reference fields. I recently replaced an entity queue on a project with a config page with an entity reference field, and I preferred the user experience.
> 15 votes

# Answer
There is also a shortcut to load the subqueue: `\Drupal\entityqueue\Entity\EntitySubqueue::load($sid);`
> 0 votes

# Answer
Based on what oknate says, you can also load the entities referenced directly:

```
$entity_subqueue = \Drupal::entityManager()->getStorage('entity_subqueue')->load($sid);
$items = $entity_subqueue->get('items')->referencedEntities();

```
> 0 votes

---
Tags: 8
---


# Question
Title: Does CKEditor5 have an embed button like CKEditor4?
With CKEditor4 I was able to configure the editor to have embed buttons for entities (Webform, Taxonomy, or Node) like this using through *Configurations \>\> Content Authoring \>\> Text editor embed buttons*.

>

With CKEditor5, I am lost as it has only Drupal media embed.

>

*Note: Merely changing CKEditor4 to CKEditor5 is not breaking existing functionality as of now.*

How can I get Entity Embed buttons back in CKEditor5?
Is there any update regarding entity embed button that would be ported to Drupal core?

# Answer
This is because the entity embed module does not support CKEditor5 yet - mainly because the way plugins are written in CKEditor5 is different than CKEditor4.

The status looks good. I think you can get it to work with

1. The latest dev release of the 'entity\_embed' module.
2. A patch for the 'embed' module from https://www.drupal.org/project/embed/issues/3309747
> 5 votes

---
Tags: wysiwyg, 10
---


title: hierarchical select based in taxonomy

text:
# Question
Title: hierarchical select based in taxonomy
I have used the Simple hierarchical select and hierarchical select module long time ago, but now I need that functionality for a webform, I have a list of taxonomy terms with all the states and cities of my country organized

I know that with webform conditionals I can create each condition separately but that would be very tedius, is there a way of create the hierarchical select functionality based on my taxonomy terms for my webforms?

# Answer
You can use contrib module https://www.drupal.org/project/webform\_shs to make terms in hierarchical select.
> 1 votes

---
Tags: 7, webforms, taxonomy-terms
---


# Question
Title: How do I create a paragraph using a bundle class defined in another module?
I have a controller in one module that generates paragraphs that are using unique bundle classes that I want to be able to use in other modules.

In my controller I have this

```
$bundle_class = \Drupal::service('class_resolver')->getInstanceFromDefinition('Drupal\other_module\Entity\Paragraph\StandardHero');
$paragraph = $bundle_class::create([
  'type' => 'standard_hero',
  'field_title' => [
    'value' => 'Test'
  ]
]);

```

It does recognize the class because if I change the class sting to gibberish it complains that that class is not found. But I get this error

> ArgumentCountError: Too few arguments to function Drupal\Core\Entity\ContentEntityBase::\__construct(), 0 passed in /core/lib/Drupal/Core/DependencyInjection/ClassResolver.php on line 31 and at least 2 expected in Drupal\Core\Entity\ContentEntityBase-\>\__construct() (line 189 of core/lib/Drupal/Core/Entity/ContentEntityBase.php).

How can I create a paragraph of a specified bundle class that appears in a different module?

# Answer
4uk4 was correct. Defining the class was unnecessary. I was able to generate the paragraph with the proper bundle class applied automatically by just defining 'type' in the create method of the paragraphstorage class, like so

```
  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    // Injected.
    $this->entityTypeManager = $entity_type_manager;
    $this->paragraphStorage = $this->entityTypeManager->getStorage('paragraph');
    $this->paragraphViewBuilder = $this->entityTypeManager->getViewBuilder('paragraph');
  }

  public function show($type) {
    $query_params = \Drupal::request()->query->all();
    $paragraph_values = [
      'type' => $type
    ];

    $paragraph_values += $query_params;
    $paragraph = $this->paragraphStorage->create($paragraph_values);
    $build = $this->paragraphViewBuilder->view($paragraph);
    return $build;
  }

```
> 0 votes

---
Tags: 9, paragraphs
---


# Question
Title: How to detect if form-building function is called for the first time?
In my form building function I need to render some things basing on user's actions. But if the form building function is called for the very first time I want to put a form deliberately in slightly inconsistent state (I have my reasons, long story).

How can I reliably detect if the form building function was called for the first time, or if the form was already presented to the user and now it's built due to AJAX call or to allow user to fix input errors?

Currently I'm using `empty($form_state['input'])` but I have this feeling there is a better, more reliable way and I forgot it.

# Answer
You can add our own value to $form\_state in a hook\_form\_alter(). If it doesn't already exist (eg., `!isset($form_state['my_var'])`), then you know it is the first build.
> 5 votes

# Answer
At least in Drupal 9, your form\_alter function() will run at least twice without the value you add to form\_state being defined. Now that it is an object and not an array, the only mechanism I know of to set an arbitrary value is get() and set(), and the values live in the storage property of form\_state. According to this issue:

> form\_state\['storage'\] is ought to be changed in submit handler not in builder.

That comment is 15 years old, so maybe it isn't so definitive nowadays. When I try it, I find that my values need to be initialized at least twice.

The only reliable indication I have found for "the beginning of this form process" (ie if you are editing a node, and you reload the URL, that starts a new form process, even though it's the same entity) is that both form\_state values and input are empty. I hope to eventually find something better.
> 0 votes

---
Tags: forms
---


# Question
Title: Were sub-menu lists of admin panel deleted?
I installed Drupal 9.3. In its administration panel, I don't see drop-down sub-menu lists I saw in a Drupal 8.9 site, where I could hover the cursor at any of the first level menu items (for example, *Content* or *Structure*).

Has sub-menu lists of the administration panel been removed in Drupal 9.x?

# Answer
Drop-down menus on hover are a feature of the Admin Toolbar module. Check if it is enabled, or install if missing.
> 0 votes

---
Tags: 9
---


# Question
Title: Change default value when triggering form #states
By default, my `field_taxo` has the value 'castle'.

1. \_none
2. castle (by default)
3. mansion

The `field_taxo` is only showing when the role 'marketing' is checked, and becomes required.

```
/**
 * Implements hook_form_alter().
 */
function mymodule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
{
  $forms = ['user_register_form', 'user_form'];
  if (in_array($form_id, $forms)) {
    $form['field_taxo']['#states'] = [
      'visible' => [
        ':input[name="roles[marketing]"]' => ['checked' => TRUE],
      ],
    ];
    $form['field_taxo']['widget']['#states'] = [
      'required' => [
        [':input[name="roles[marketing]"]' => ['checked' => TRUE]],
      ],
    ];
  }
}

```

Is it possible to set the value to '\_none' when the role marketing is not checked ? Because I need the value to be empty for the non-marketing role

# Answer
Found a workaround by adding this :

```
$form['#validate'][] = '_mymodule_user_validate';

```

and reseting the value in the validate function

```
function _mymodule_user_validate(&$form, \Drupal\Core\Form\FormStateInterface &$form_state) {
  if(!in_array('marketing', $form_state->getValue('roles'))) {
    $form_state->setValue('field_taxo', []);
  } else {
    if($form_state->isValueEmpty('field_taxo')) {
      $form_state->setErrorByName('field_taxo', "error");
    }
  }
}

```
> 1 votes

# Answer
It is not possible to do this with #states.
Take a look a https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Form%21FormHelper.php/function/FormHelper%3A%3AprocessStates/9.3.x
Only states like enabled, visible, checked, ... are available. You need to add a custom javascript or use ajax to do this.
If you only use this value on server side, you can check if the role marketing is not checked and unset the other value.
> 0 votes

---
Tags: forms, 9
---


# Question
Title: How to put select option value into particular category in webform module?
I am using webform module and added a select field.

My option values are

> One|Sample 1
> Two|Sample 2
> Three|Sample 3
> Four|Sample 4
> Five|Sample 5
> Six|Sample 6

But I want these three fields in a particular category named Sample list 1

> One|Sample 1
> Two|Sample 2
> Three|Sample 3

Sample List 2:

> Four|Sample 4
> Five|Sample 5
> Six|Sample 6

Note: I don't want to show it in groups \<\>.

**I want a select list which consists of Sample List 1 and Sample List 2 In a single select field I want to store both of option values into their respective select lists.**

# Answer
I think you want to store this a 2 separate fields however present it to the user as 1 field.

One solution would be to use `hook_form_alter()` to combine the 2 selects into 1, and then put the values back where it should be after the form is submitted.

For this example lets call the first select field A, and the second field B, and the new field that combines both A and B, C.

So - first combine the fields and add an additional submit handler:

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

  if($form_id == 'webform_client_form_<ADD WEBFORM ID HERE>') {

    // Make a new field which will have both options. Base in on the existing
    // field A.
    $form['submitted']['field_c'] = $form['submitted']['field_a'];

    // Combine the options of field A and B for the new field.
    $form['submitted']['field_c']['#options'] = array_merge($form['submitted']['field_a']['#options'], $form['submitted']['field_b']['#options']);

    // Hide field A and field B.
    $form['submitted']['field_a']['#access'] = $form['submitted']['field_b']['#access'] = FALSE;

    // Add an additional submit handler to put the values back where they
    // should be. Add this before the existing submit handler so we can make
    // our changes before anything is saved.
    array_unshift($form['#submit'], 'split_combined_select_values_out');

    // Add a validate function to make sure only 1 option is selected from each category
    $form['#validate'][] = 'combined_select_validate';

  }

}

```

In the new validation function make sure that only 1 option is selected from each category:

```
function combined_select_validate($form, &$form_state) {

  $count_a = $count_b = 0;

  foreach($form_state['values']['submitted']['field_c'] as $val) {
    if(array_key_exists($val, $form['submitted']['field_a']['#options'])) {
      $count_a++;
    } elseif(array_key_exists($val, $form['submitted']['field_b']['#options'])) {
      $count_b++;
    }
  }

  if($count_a > 1 || $count_b > 1) {
    form_set_error('submitted][field_c', 'Can only select 1 option from each category');
  }

}

```

And then in the new submit handler put the values back where they should be:

```
function split_combined_select_values_out($form, &$form_state) {

  foreach($form_state['values']['submitted']['field_c'] as $val) {
    // Check if the value  selected is from field A or field B
    if(array_key_exists($val, $form['submitted']['field_a']['#options'])) {
      $form_state['values']['submitted']['field_a'][$val] = $val;
    } elseif(array_key_exists($val, $form['submitted']['field_b']['#options'])) {
      $form_state['values']['submitted']['field_b'][$val] = $val;
    }
  }

  // Unset the value from field C.
  unset($form_state['values']['submitted']['field_c']);

}

```
> 0 votes

# Answer
Create a taxonomy of these options & create hierarchy of them & enable hierarchy select webform module & add Hierarchy term select element in your webform.
> 0 votes

---
Tags: forms, webforms
---


# Question
Title: Commerce Order Total Tax line via EntityMetadataWrapper
I need the final tax amount for an order found on the commerce order total. when using dpm and entity metadata wrapper i can't seem to break it out in order to grab the value.

```
$order = entity_metadata_wrapper('commerce_order', 3);
dpm($order->commerce_order_total->getPropertyInfo());

```

# Answer
> 1 votes
the most thorough insight on getting access to the tax line and individual subtotals. found via: https://gist.github.com/BBGuy/3e1f624eaee2088d8eee

```
// order total object
$order_total_obj = $order_wrapper->commerce_order_total->value();
// Order total (cents).
$order_total = $order_total_obj['amount'];
// order currency code
$currency_code = $order_wrapper->commerce_order_total->currency_code->value();
// subtotal without vat
$total_ex_vat = commerce_price_component_total($order_total , 'base_price');
// total tax (in this case vat 20%)
$total_vat = commerce_price_component_total($order_total , 'tax|vat_20');
// subtotal with vat
$sub_total = $total_ex_vat['amount'] + $total_vat['amount'];
// formatted price string with currency sign
$sub_total = commerce_currency_format($sub_total, $currency_code);

```

# Answer
> 0 votes
To get the final tax amount for an order from the commerce\_order\_total field, you can use the following code:

```
$order = entity_metadata_wrapper('commerce_order', 3);
$order_total = $order->commerce_order_total->value();
$tax_amount = $order_total['tax_amount'];

```

The commerce\_order\_total field is an entity\_reference\_revisions field, which means that it stores a reference to a revision of a tax total entity. The tax total entity stores the total tax amount in the tax\_amount field.

You can also use the commerce\_price Twig filter to format the tax amount as a price:

```
{# Format the tax amount as a price #}
{{ tax_amount|commerce_price }}

```

---
Tags: commerce
---


# Question
Title: How do I enable all error messages altering directly a database table?
When I try to log in on a site, I get a generic error, which doesn't help in understanding what exactly is going wrong.

I would like to enable the *All messages, with backtrace information* option shown for *Error messages to display*, to be able to understand what the error cause is.

Is it possible to change it by directly altering a database table? If the answer is *yes*, which table and which row should I change?

# Answer
> 1 votes
This question as written, "directly in MySQL", is unanswerable. The value to change is found with this query:

```
SELECT data FROM `config` where name = 'system.logging';

```

But the content of the `data` column is a blob type containing serialized PHP data, and that data contains a configuration hash that is particular to your site.

You will have to write a PHP program that selects the value, unserializes it, changes the `error_level` key to `verbose`, serializes the new data then re-inserts it. I know of now way to do that directly in MySQL alone.

---
Tags: database, 9
---


title: How do I get the current node ID?

text:
# Question
Title: How do I get the current node ID?
In Drupal 7, if I wanted to get the node id of the currently displayed node (e.g. `node/145`) I could get it with the `arg()` function. In this case, `arg(1)` would return 145.

How can I achieve the same in Drupal 8?

# Answer
> 145 votes
The parameter will have been upcasted from nid to full node object by the time you get access to it, so:

```
$node = \Drupal::routeMatch()->getParameter('node');
if ($node instanceof \Drupal\node\NodeInterface) {
  // You can get nid and anything else you need from the node object.
  $nid = $node->id();
}

```

See the change record for more information.

# Answer
> 24 votes
It is correct to use `\Drupal::routeMatch()->getParameter('node')`. If you just need the node ID, you can use `\Drupal::routeMatch()->getRawParameter('node')`.

# Answer
> 8 votes
Note on the node preview page, the following doesn't work:

```
$node = \Drupal::routeMatch()->getParameter('node');
$nid = $node->id();

```

For the node preview page, you have to load the node this way:

```
$node = \Drupal::routeMatch()->getParameter('node_preview');
$nid = $node->id();

```

How to load node object in node preview page?

# Answer
> 6 votes
if you are using or creating custom block then you have to follow this code to get current url node id.

```
// add libraries
use Drupal\Core\Cache\Cache;

// code to get nid

$node = \Drupal::routeMatch()->getParameter('node');
  $node->id()  // get current node id (current url node id)

// for cache

public function getCacheTags() {
  //With this when your node change your block will rebuild
  if ($node = \Drupal::routeMatch()->getParameter('node')) {
  //if there is node add its cachetag
    return Cache::mergeTags(parent::getCacheTags(), array('node:' . $node->id()));
  } else {
    //Return default tags instead.
    return parent::getCacheTags();
  }
}

public function getCacheContexts() {
  //if you depends on \Drupal::routeMatch()
  //you must set context of this block with 'route' context tag.
  //Every new route this block will rebuild
  return Cache::mergeContexts(parent::getCacheContexts(), array('route'));
}

```

# Answer
> 1 votes
By using Service,

```
    use Drupal\Core\Routing\RouteMatchInterface;

/**
 * Provides a 'UtilitiesDataService' service.
 */
class MyClass {

  /**
   * The route match.
   *
   * @var \Drupal\Core\Routing\RouteMatchInterface
   */
  protected $routeMatch;

  /**
   * Constructs a new service.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
   *   The route match.
   */
  public function __construct(RouteMatchInterface $route_match) {

    $this->routeMatch = $route_match;
  }

  public function getNodeId(){
    $nid = $this->routeMatch->getParameter('node')->id();
  }
}

```

In services.yml file,

```
services:
   my_module.get_data_service:
    class: Drupal\my_module\MyClass
    arguments: ['@current_route_match']

```

# Answer
> 1 votes
Blocks are *context aware* and you should be using them. This will allow using the blocks in places where the route itself doesn't have a node but some subsystem provides the context anyways.

Example from core:

```
/**
 * Provides a 'Node Context Test' block.
 *
 * @Block(
 *   id = "node_block_test_context",
 *   label = @Translation("Node Context Test"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node", label = @Translation("Node"))
 *   }
 * )
 */
class NodeContextTestBlock extends BlockBase {

  public function build() {
    /** @var \Drupal\node\NodeInterface $node */
    $node = $this->getContextValue('node');

```

You can also see how easy it is to get the node. The test this block is used for is instructional: it tests whether the block appears on the preview page. This is not doable with the route match approach as the `/node/preview/{node_preview}/{view_mode_id}` route doesn't contain a node at all.

This will also make the node context required so there's no need to check whether there is a node at all. It's possible to make the node optional, of course:

```
 *     "node" = @ContextDefinition("entity:node", label = @Translation("Node"), required = FALSE)

```

the order of options after the first argument does not matter.

---
Tags: nodes, 8
---


title: How to export data using POST?

text:
# Question
Title: How to export data using POST?
I am using Drupal as a backend to deliver data, collected using sensors, and stored in the Drupal database to a mobile app that present the data to the end user.

Drupal records the value from a temperature sensor. When some event happens that changes the temperature, the value is stored in a temperature field in a standard node. I then need to wrap the temperature and use a POST endpoint (defined by an external app) to notify the app about the temperature recorded (i.e. a push notification or export of data by means of POST).

I know how to do this with GET (which requires the app to poll the endpoint periodically to check if a new data point is available), but I need to do this by means of POST from the the Drupal back end *whenever* a new data point is created.

I believe I shall be able to implement `hook_ENTITY_TYPE_insert()`to intercept the node when it is being created to save the new data. What I am struggling with is how to use POST to push the data to the app.

# Answer
Drupal core includes the Guzzle HTTP Client library under the hood. Guzzle can be used to make post requests. Whenever your event fires, you can send off a POST request as follows:

```
$post_data = [
  'field_1' => $node->get('field_one')->value,
  'field_2' => $node->get('field_two')->value,
];
$options['body'] = http_build_query($post_data);
// Instantiate the Guzzle HTTP client.
$client = \Drupal::httpClient();
$client->request('POST', $url, $options);

```

See the guzzle documentation for how to set `$options` for your request. Guzzle is extremely dynamic, can be used for any type of HTTP request, and allows for all sorts of options to be set. Note that depending on the endpoint, `http_build_query()` is not necessary (for example a JSON endpoint), and you may need to a different key than `body` in the options.
> 1 votes

---
Tags: 9
---


# Question
Title: How can I change the default branch of a contributed module?
If you're more used to GitLab than Drupal.org, you might spend a while hunting through settings there to figure out how to change the default branch - or concluding that you simply can't.

# Answer
> 2 votes
Turns out it's a setting on your Drupal.org version of the module page. Visit `edit > default branch` on the page-specific menu of your module.

At the time of creating this question, the documentation page from 2012 (last updated 2015) is still close enough to be helpful.

# Answer
> 2 votes
Drupal.org removed the possibility to delete a branch from the project page. Project owners who edit a project they created will see the following tabs.

>

The tab to change the default branch isn't anymore shown.

Instead, Project owners need to visit the Gitlab repository from the browser. The *Repository \> Branches* page lists all the branches, with a button to delete them. As long as a branch isn't the default one, it can be delete.

>

To change the default branch, is sufficient to visit the *Settings \> Repository* page. The *Branch defaults* section, once expanded, allows to change the default branch, which is necessary to delete a branch that is set as default.

>

---
Tags: version-control, community-official-site
---


# Question
Title: "Your requirements could not be resolved to an installable set of packages."
cPanel PHP Version: 7.3

Drupal 8.8

I am trying to install *upgrade\_status* module via composer for the first time in a shared hosting server but I am unable to do that. Below shows the error that I get.

```
lz@lz [~/public_html]$ composer require 'drupal/upgrade_status:^3.18'

```

Error

```
The "composer/installers" plugin was skipped because it requires a Plugin API version ("^1.0") that does not match your Composer installation ("2.2.0"). You may need to run composer update with the "--no-plugins" option.
The "drupal/core-composer-scaffold" plugin was skipped because it requires a Plugin API version ("^1.0.0") that does not match your Composer installation ("2.2.0"). You may need to run composer update with the "--no-plugins" option.
The "drupal/core-project-message" plugin was skipped because it requires a Plugin API version ("^1.1") that does not match your Composer installation ("2.2.0"). You may need to run composer update with the "--no-plugins" option.
The "drupal/core-vendor-hardening" plugin was skipped because it requires a Plugin API version ("^1.1") that does not match your Composer installation ("2.2.0"). You may need to run composer update with the "--no-plugins" option.
./composer.json has been updated
The "composer/installers" plugin was skipped because it requires a Plugin API version ("^1.0") that does not match your Composer installation ("2.2.0"). You may need to run composer update with the "--no-plugins" option.
The "drupal/core-composer-scaffold" plugin was skipped because it requires a Plugin API version ("^1.0.0") that does not match your Composer installation ("2.2.0"). You may need to run composer update with the "--no-plugins" option.
The "drupal/core-project-message" plugin was skipped because it requires a Plugin API version ("^1.1") that does not match your Composer installation ("2.2.0"). You may need to run composer update with the "--no-plugins" option.
The "drupal/core-vendor-hardening" plugin was skipped because it requires a Plugin API version ("^1.1") that does not match your Composer installation ("2.2.0"). You may need to run composer update with the "--no-plugins" option.
Running composer update drupal/upgrade_status
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - mglaman/phpstan-drupal[1.0.0, ..., 1.1.4] require php ^7.1 || ^8.0 -> your php version (7.0.8; overridden via config.platform, actual: 7.3.33) does not satisfy that requirement.
    - mglaman/phpstan-drupal[1.1.5, ..., 1.1.26] require php ^7.4 || ^8.0 -> your php version (7.0.8; overridden via config.platform, actual: 7.3.33) does not satisfy that requirement.
    - drupal/upgrade_status 3.18.0 requires mglaman/phpstan-drupal ^1.0.0 -> satisfiable by mglaman/phpstan-drupal[1.0.0, ..., 1.1.26].
    - Root composer.json requires drupal/upgrade_status ^3.18 -> satisfiable by drupal/upgrade_status[3.18.0].

Installation failed, reverting ./composer.json and ./composer.lock to their original content.

```

How can I install the module via the composer?

# Answer
> 1 votes
The version of Composer is too *new* for the old plugins specified and the config.platform configured PHP version in composer.json is older than the actual 7.3 version. This is what the output says.

---
Tags: composer
---


# Question
Title: sort api solr search using custom view field using hook_views_query_alter()
Drupal 9.4.8. Search api solr 4.2.9

I have created a search api solr search in views

One of the fields included in this view is a custom view field: **node\_date\_raw\_field**

From module hook\_views\_data():

```
  $data['views']['node_date_raw_field'] = [
    'title' => t('Node Date (raw)'),
    'help' => t('Node Date raw field plugin.'),
    'field' => [
      'id' => 'node_date_raw_field',
    ],
    'sort' => [
      'field' => 'node_date_raw_field',
      'id' => 'standard',
    ],
  ];

```

This field simply brings back the node created date field associated with the current row content datasource or file datasource. What I want to do is sort the search results of the view by this custom field using hook\_views\_query\_alter().

None of the examples I have found so far seem to work. This below is what I have tried:

```
function sbn_views_query_alter(Drupal\views\ViewExecutable $view, Drupal\views\Plugin\views\query\QueryPluginBase $query) {
  if ($view->id() == 'solr_search') {

       # https://drupalize.me/tutorial/alter-query-used-view?p=3463
       # $query->sort('node_date_raw_field', 'DESC'); // Unlike the other options, nothing shows up in sort results
       # Error message: *Sorting by "node_date_raw_field" has no valid solr field*.

       // Override existing Order rules.
        #$query->orderby = [];
        # $query->addOrderBy(NULL, NULL, 'DESC', 'node_date_raw_field');
        # Simply doesn't sort.

        # https://www.zyxware.com/articles/3885/drupal-how-to-use-drupal-hookview…
        #$query->orderby[0] = array(
        #    'field' => 'node_date_raw_field',
        #    'direction' => 'desc',
        #);
        # Notice: Undefined property: Drupal\search_api\Plugin\views\query\SearchApiQuery::$orderby in sbn_views_query_alter()

       # $query->addOrderBy(NULL, NULL, 'desc', 'node_date_raw_field');
  }
}

```

Everything above brings back unsorted results except for **$query-\>sort** which errors out.

I checked the **$query** field and the field **node\_date\_raw\_field** is there:

```
 [field] => Array
                                        (
                                            [label] => Drupal\search_api\Plugin\views\field\SearchApiEntityField
                                            [title] => Drupal\search_api\Plugin\views\field\SearchApiEntityField
                                            [search_api_excerpt] => Drupal\search_api\Plugin\views\field\SearchApiStandard
                                            [uri] => Drupal\search_api\Plugin\views\field\SearchApiEntityField
                                            [node_label_field] => Drupal\sbn\Plugin\views\field\NodeLabelField
                                            [node_id_field] => Drupal\sbn\Plugin\views\field\NodeIDField
                                            [group_label_field] => Drupal\sbn\Plugin\views\field\GroupLabelField
                                            [node_date_field] => Drupal\sbn\Plugin\views\field\NodeDateField
                                            [node_date_raw_field] => Drupal\sbn\Plugin\views\field\NodeDateRawField
                                        )

```

Also checked the class: echo get\_class($query); Class used: **Drupal\search\_api\Plugin\views\query\SearchApiQuery**

Is it simply not possible to sort a search api solr view by a views custom field, or am I missing something above?

# Answer
From this link, Programmatically change order, I found this comment:

> Solr queries don't use the database (it would defeat the purpose of using Solr if they did). You'll need to use hook\_search\_api\_solr\_query\_alter and alter the query provided by the Solarium library. Keep in mind it's not a database query, so you'll probably have to consult the Solr docs to find out the correct syntax to use to reproduce the sorting you need. If you're on an older version of Solr (4.x and below), the options for complex sorting are somewhat limited, so be sure that you're consulting the right version of the documentation to avoid frustration

Given that this view is a search api solr indexed view, hook\_views\_query\_alter will never give me the results I am looking for. So, I had to rethink my approach.

The soltion was an Aggregated Field.

In Configuration -\> Search and metadata -\> Search API -\> Solr index -\> Fields

I created a new, aggregated field of the timestamp field from each of the solr datasources in my view:

This creates a field that contains the timestamp from whichever one of the datasources (file, group\_content, node, comment) happens to be in the row that is being returned. If there is more than one datasource in the row, this field will be the datasource timestamp with the highest value (i.e., most recent date).

Got the machine name of this field after it was created, and made sure it was Integer:

Next, I went and edited the view. I added the aggregated field to the field list, and also made it the sort criteria for the view results:

Saved the view, re-indexed the site, and voila! Search results for the search api solr indexed view are sorted by the aggregated field.
> 0 votes

---
Tags: views, search
---


# Question
Title: How will I highlight active item in glossary view?
I have created a glossary view which shows alphabetical navigation to filter the list.

But I can't find a way to highlight the active link - would like for "G" to be highlighted if I am clicking the "G".

I have this tutorial for this but it works only when ajax is disabled. But I am using ajax for this glossary view.

Below is the code which isn't working

```
$(".view-display-id-attachment_1 span a").each(function(){
     if($(this).attr("href") == location.pathname) {
       $(this).addClass('my-class');
     }
});

```

I want something like this

When **C** will be clicked it will be highlighted this way

How will I achieve this in view glossary when **ajax is enabled**?

Thanks in advance.

Please check the issue I am facing currently. Click Here

# Answer
After so many research I understood that unfortunately glossary view doesn't add `is-active` class if AJAX enabled in the view.

So I had to use a contrib module for that. It provides a simple A-Z filter as radio button/checkbox.

https://www.drupal.org/project/custom\_view\_filters
> 0 votes

---
Tags: views, 9
---


# Question
Title: How do I lock down a child theme to use jQuery 3.6.0?
My older site uses bootstrap 3 and has been working great when accessed from a mobile phone and the hamburger menu kicks in, but something has happened in jQuery 3.6.2 (In Drupal 9.5.0) that causes the menu click to fire and then immediately close the menu. I can see this when setting breakpoints in the Drupal behaviors script. Looks like some kind of race condition. How would I lock down the child theme to use only jQuery 3.6.0? Most of what is on Drupal site about using different libraries is old or the code does not work at all. I've tried the suggestion below and jQuery never loads in the theme. I could see it core/assets/vendor folder when not overridden.

```
name: Visitor Permits
type: theme
core_version_requirement: ^8 || ^9
description: Child theme for Visitor Permits.
base theme: bootstrap
screenshot: profile-vpermits.jpg

# Libraries
libraries:
  - vpermits/vpermits

libraries-override:
  core/jquery: vpermits/jquery

# Regions
regions:
  mobile: "Mobile"
  header_left: "Header Left"
  header_right: "Header Right"
  navigation: "Navigation"
  sidebar_left: "Sidebar Left"
  content: "Content"
  sidebar_right: "Sidebar Right"
  footer: "Footer"
  disabled: "Disabled"

```

And the .libraries.yml

```
vpermits:
  version: VERSION
  js:
    dist/vpermits.js: {}
  css:
    theme:
      dist/style.css: {}
  dependencies:
    - core/drupal
    - core/modernizr
    - vpermits/babel-polyfill
    - core/drupal.dialog.ajax
    - core/jquery.form

permit-form-app:
  version: 1.x
  js:
    dist/permit-form-app.js: {}
  css:
    theme:
      dist/app-style.css: {}
  dependencies:
    - vpermits/babel-polyfill

babel-polyfill:
  version: 1.x
  js:
    dist/polyfill.js: {}

jquery:
  remote: https://github.com/jquery/jquery
  version: "3.6.0"
  license:
    name: MIT
    url: https://raw.githubusercontent.com/jquery/jquery/3.6.0/LICENSE.txt
    gpl-compatible: true
  js:
    assets/vendor/jquery/jquery.min.js: { minified: true, weight: -20 }

```

# Answer
Override the core/jquery library in the theme. Its primary definition in Drupal 9.5.0 is:

```
jquery:
  remote: https://github.com/jquery/jquery
  version: "3.6.2"
  license:
    name: MIT
    url: https://raw.githubusercontent.com/jquery/jquery/3.6.2/LICENSE.txt
    gpl-compatible: true
  js:
    assets/vendor/jquery/jquery.min.js: { minified: true, weight: -20 }

```
> 0 votes

---
Tags: javascript, bootstrap-theme
---


title: Adding autocomplete for text-field

text:
# Question
Title: Adding autocomplete for text-field
I tried to implement an autocomplete in text-field for drupal 8 in my custom module

all I wanted was to fetch and display the likely title I typed via autocomplete so declared a public function autocomplete within a class in DefaultController.php in folder directory --\>mymodule/src/Controller/DefaultController.php

```
<?php

namespace Drupal\mymodule\Controller;

use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\JsonResponse;

class DefaultController extends ControllerBase
{
    public function autocomplete($string)
    {
        $matches = array();
        $db = \Drupal::database();
        $result = $db->select('node_field_data', 'n')
        ->fields('n', array('title', 'nid'))
        ->condition('title', '%'.db_like($string).'%', 'LIKE')
        ->addTag('node_access')
        ->execute();

        foreach ($result as $row) {
            $matches[$row->nid] = check_plain($row->title);
        }

        return new JsonResponse($matches);
    }
}

```

then created an EditForm.php in folder directory --\>mymodule/src/Form/EditForm.php

```
<?php

namespace Drupal\mymodule\Form;

use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;

class EditForm extends FormBase
{
    public function getFormId()
    {
        return 'mymodule_edit_form';
    }

    public function buildForm(array $form, FormStateInterface $form_state)
    {
        $form = array();

  $form['input_fields']['nid'] = array(
    '#type' => 'textfield',
    '#title' => t('Name of the referenced node'),
    '#autocomplete_route_name' => 'mymodule.autocomplete',
    '#description' => t('Node Add/Edit type block'),
    '#default' => ($form_state->isValueEmpty('nid')) ? null : ($form_state->getValue('nid')),
    '#required' => true,
  );

        $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Create'),
  );

        return $form;
    }
}

```

also created mymodule.routing.yml

```
  mymodule.autocomplete:
  path: '/mymodule/autocomplete'
  defaults:
    _controller: '\Drupal\mymodule\Controller\DefaultController::autocomplete'
  requirements:
    _permission: 'access content'

```

still autocomplete functionality not getting implemented ? Can anybody point me what am i missing ??

# Answer
Your class need some modification you need to check request and put it into $string.

```
<?php

namespace Drupal\mymodule\Controller;

use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Component\Utility\Unicode;

class DefaultController extends ControllerBase
{

  /**
   * Returns response for the autocompletion.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The current request object containing the search string.
   *
   * @return \Symfony\Component\HttpFoundation\JsonResponse
   *   A JSON response containing the autocomplete suggestions.
   */

  public function autocomplete(request $request) {
    $matches = array();
    $string = $request->query->get('q');
    if ($string) {
      $matches = array();
      $query = \Drupal::entityQuery('node')
      ->condition('status', 1)
      ->condition('title', '%'.db_like($string).'%', 'LIKE');
      //->condition('field_tags.entity.name', 'node_access');
      $nids = $query->execute();
      $result = entity_load_multiple('node', $nids);
      foreach ($result as $row) {
        //$matches[$row->nid->value] = $row->title->value;
        $matches[] = ['value' => $row->nid->value, 'label' => $row->title->value];
      }
    }
    return new JsonResponse($matches);
  }
}

```
> 11 votes

# Answer
If you want to select an entity, then there is a way easier way to do that. Drupal 8 has a standard entity\_autocomplete field type, just specify your form element like this:

```
$form['node'] = [
  '#type' => 'entity_autocomplete',
  '#target_type' => 'node',
];

```

See Custom autocomplete field for more information.

Also, never do database queries against node/entity tables. Use \Drupal::entityQuery() for that.
> 12 votes

# Answer
1. Create a routing.yml file and add the below code : admin\_example.autocomplete:

:

```
  path: '/admin_example/autocomplete'
  defaults:
    _controller: '\Drupal\admin_example\Controller\AdminNotesController::autocomplete'
  requirements:
    _permission: 'access content'

```
2. The form which you have build in mymodule/src/Form/EditForm.php is correct

You need to change the code in controller .The code is below :

```
public function autocomplete(Request $request)
{
 $string = $request->query->get('q');
    $matches = array();
      $query = db_select('node_field_data', 'n')
          ->fields('n', array('title', 'nid'))
          ->condition('title', $string . '%', 'LIKE')
          ->execute()
          ->fetchAll();
    foreach ($query as $row) {
        $matches[] = array('value' => $row->nid, 'label' => $row->title);
    }

    return new JsonResponse($matches);
}

```
> 5 votes

# Answer
Use @vgoradiya code then on the foreach loop try it this way:

```
    foreach ($result as $row)
    {
        $matches[] = ['value' => $row->nid, 'label' => check_plain($row->title)];
    }

```
> 2 votes

# Answer
FWIW I had the same need and was greatly helped by the excellent write-up over at https://antistatique.net/en/blog/how-to-create-a-custom-autocomplete-entity-field-widget-using-the-drupal-8-form-api
> 0 votes

---
Tags: 8, forms
---


# Question
Title: RuntimeException Could not delete /path/web/sites/default/default.services.yml:
I have installed Drupal 9 with Composer.

I didn't install any modules, themes or customize anything. It's a plain Drupal installation.

After a few months I did `composer update` in that website's directory and the process seems to went well besides:

```
[RuntimeException] Could not delete /path/web/sites/default/default.services.yml:

```

The website itself is working after this procedure (tested from a browser with cleared cache).

Should I ignore this warning/error? I mean, shouldn't this file stay the same anyway?

# Answer
> 0 votes
The file `default.services.yml` is part of the Drupal scaffold and can change on a composer update. You shouldn't edit the file, remove it or change the file permissions. If you need to change the defaults, copy the file content to `services.yml` and change it there.

---
Tags: 9
---


# Question
Title: RuntimeException when updating from command line
I went to my website's directory and ran:

```
composer update

```

> \[RuntimeException\] Could not delete /home/example/public\_html/example.com/web/sites/default/default.services.yml:

`ls -la` output:

> `-rw-rw-r-- 1 example example 7732 Aug 28 03:52 default.services.yml`

Should I take any action, if so, what?

# Answer
> 1 votes
In the core 9.4.7 update, the `default.services.yml` file was updated. However, if your permissions are set correctly on the `/default` directory and the `default.services.yml` file, then composer update will fail with the "could not delete" permissions warning.

You can solve this as follows on most versions of linux and macOS.

First, delete `default.services.yml`. (You may need to use `sudo` (`sudo rm default.services.yml`).

Next, try running `composer install` (since you have already run the update, running `install` will cause the scaffolding to be reset). If the file is created properly, check the permissions against this answer and if they are ok, you are done.

If the file cannot be created, carefully change the permissions of the `default` directory (but not any child/subdirectories) to `777` (`chmod default 777`), run `composer install` again to create the file, and then change the permissions for the `default` directory back to 755 (`chmod default 755`).

## Why does this happen?

Drupal needs file permissions for services files to be set securely so that they cannot be changed by just anyone. Unfortunately, this makes updating these files a bit of a pain because the update requires manual intervention (since the files can't be easily overwritten automatically, unlike most Drupal files in updates).

# Answer
> 0 votes
I just ran into this issue when upgrading Drupal 9.4.8 to 9.5.0 and this link helped me, I believe it will help you too :)

https://drupal.stackexchange.com/a/290297/35202

---
Tags: 9, composer
---


# Question
Title: Is there a way to add / remove items from an unlimited cardinality field in form alter / after build?
In a node edit form, I am trying to add items to a multivalue field with unlimited cardinality in a form builder hook, like form\_alter or after\_build. I can't figure out how to do it, though, at least not very well. For instance, if I fill in the default blank item in form\_alter and then add a new blank item, when you click the "Add another item" button, the form resets the items\_count for the field to the original entity item count. It doesn't "see" the new blank item I added to the field, so visibly it ends up doing nothing. There's also strange results on Submit if there's a validation error.

Is there a way to do this? Not in response to clicking on a button, so not in a submit function. I think that may be the problem. That items count is in the form state storage, and from what I've seen searching around, trying to change form state in a form builder function doesn't work. I may be misunderstanding that, though.

For context, the task I'm trying to accomplish is that I have two related fields. One is an entity reference, one is an unlimited text field. A value from the referenced entity needs to always be one of the values in the unlimited text field. So when I build the form, I need to add that value to the list if it isn't there, and still end up with a blank item at the bottom of the list.

# Answer
You can add or remove items in hook\_ENTITY\_TYPE\_prepare\_form() before the form is built:

```
/**
 * Implements hook_ENTITY_TYPE_prepare_form() for nodes.
 */
function mymodule_node_prepare_form(\Drupal\node\NodeInterface $node, $operation, \Drupal\Core\Form\FormStateInterface $form_state) {
  if ($node->getType() != 'my_content_type') {
    return;
  }
  if ($operation == 'edit') {
    // remove item
    $node->field_foo->removeItem($delta);
    // add items
    $node->field_foo[] = ['value' => $value];
    $node->field_reference[] = ['target_id' => $tid];
  }
}

```
> 3 votes

---
Tags: forms, hooks
---


# Question
Title: After any Composer command, does Composer or core set (or harden) the file permissions?
After any Composer command (for example, `composer create-project`, `composer require`, and `composer update`), does Composer or Drupal set (or harden) the file permissions?

# Answer
> 3 votes
No. The system\_requirements function of Drupal hardens the permissions of files *and the directories containing the files*. It is nothing to do with Composer commands.

---
Tags: security
---


title: How can you cache a form render array?

text:
# Question
Title: How can you cache a form render array?
I have a custom module which builds a set of complicated forms, and these forms are built dynamically (the option lists for certain SELECT items, for example, are fetched via an API call). Some of these forms take 14 seconds to load, whereas a simple "static" form takes 2 seconds.

The data behind the dynamic forms does not change often and so I want to cache the render array of the form, so that a complicated form could also load in 2 seconds. A cache life of an hour would be fine, for example.

I have not yet found how do this, or at least what I have tried has not helped the speed.

All forms in question are only available to logged in users, as they are for staff use only.

On /admin/config/development/performance I have "Browser and proxy cache maximum age" set to 1 hour.

# Answer
You can store the data in a cache.

```
$cid = 'mymodule_example';
$data = NULL;
if ($cache = \Drupal::cache()
  ->get($cid)) {
  $data = $cache->data;
}
else {
  $data = my_module_complicated_calculation();
  \Drupal::cache()
    ->set($cid, $data);
}

foreach ($data as $something) {
  // build render array
}

```

You'll build the required data in `my_complicated_calculation()`.
> 2 votes

---
Tags: forms, 9, caching
---


title: Can't add a custom filter criteria

text:
# Question
Title: Can't add a custom filter criteria
I try to add a new filter criteria to my views with a custom module.

I manage to display my new filter on the filter criteria list but when I select it and go to "Add and configure filter criteria" I have an error saying:

> The handler for this item is broken or missing. The following details are available:
>
> Enabling the appropriate module may solve this issue. Otherwise, check to see if there is a module update available.

Here is my `content_search.module` :

```
function content_search_views_data_alter(&$data)
{
    $data['node']['content_search_filter'] = [
        'title' => t('Content search filter'),
        'filter' => [
            'title' => t('Content search filter'),
            'help' => 'Filters nodes on its content',
            'field' => 'nid',
            'id' => 'content_search_filter',
        ]
    ];
}

```

And here is my `ContentSearchFilterPlugin`, placed in `content_search/src/Plugin/Filter/ContentSearchFilterPlugin.php`

```
namespace Drupal\content_search\Plugin\Filter;

use Drupal\views\ViewExecutable;
use Drupal\views\Plugin\views\display\DisplayPluginBase;
use Drupal\views\Plugin\views\filter\FilterPluginBase;

/**
 * Filters nodes on on their content
 *
 * @ingroup views_filter_handlers
 *
 * @ViewsFilter("content_search_filter")
 */
class ContentSearchFilterPlugin extends FilterPluginBase {
  /**
   * {@inheritdoc}
   */
  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
    parent::init($view, $display, $options);
    $this->valueTitle = t('Content search filter');
  }

  public function query() {
    parent::query();
    // TODO: custom query here
  }

}

```

What am I missing ?

# Answer
I think you have a problem with plugin file organization. It should be :

```
content_search/src/Plugin/views/filter/ContentSearchFilterPlugin.php

```

...instead of

```
content_search/src/Plugin/Filter/ContentSearchFilterPlugin.php

```

And the namespace for this file should be

```
namespace Drupal\content_search\Plugin\views\filter;

```
> 1 votes

# Answer
This works for me in Drupal8:

Name of custom module: `custom_modulename`

Name of table in SQL: `name_of_sql_table`

Selecting the ID for filtering

```
function custom_modulename_views_data_alter(array &$data) {
  $data['name_of_sql_table']['custom_modulename'] = [
    'title' => t('Title shown'),
    'group' => t('abc'),
    'filter' => [
      'title' => t('Filter'),
      'help' => t('Self made'),
      'field' => 'id',
      'id' => 'string'
    ],
  ];
}

```

*Hint: If you want to use options etc. then it is much more complicated. Use a Class for that.*
> 0 votes

---
Tags: 8, views
---


# Question
Title: Unable to add custom css from asset injector module to content type
I have a content type called Advertisement on my Drupal site. I want to add some custom css functionality to this content type (as in, when I create an advertisement from the "Add Content" button, it should have the css I want).

I am using the Asset injector module to insert the css. Here is what it looks like:

These are the conditions I have specified in the injector:

However, if I try to create an advertisement, my css changes do not get reflected.

Would anyone happen to know why the asset injector module isn't injecting my css? I've tried clearing the cache but that did not do the trick.

# Answer
> 0 votes
Usually, there are **2 themes** being used on a Drupal site, one for the "public" side (default theme), and the other for "backend" content (admin theme). You have to figure out which theme you want your custom CSS to be added to.

In your question, the screenshot is showing a page through which new content is being added, and it seems by its design that the theme being used is one of the admin themes.

You are probably using the option `Use the administration theme when editing or creating content`. You can find that option on the Administration \> Appearance page `/admin/appearance`.

Asset Injector is most likely adding the CSS to the default theme, not the admin theme.

In your case you can turn off the mentioned option. This way you will see the default theme when creating new content, and get the custom CSS, but you may not be happy with the look of other elements on the page, depending on the form styles in your default theme.

Or you can check if Asset Injector has the option which theme to add the CSS to. If you can make it add to the admin theme you can continue to use the admin theme for creating/editing content.

---
Tags: nodes
---


# Question
Title: Grouped Exposed filters radio buttons : one in two no value ticked. How to programatically force default button be ticked?
Some exposed filters (radio buttons) aren't systematically ticked when a view is displayed, causing an "*An illegal choice has been detected. Please contact admin...*" error message and *No result found*.

Moreover, refreshing the same view, or surfing between similar views with another contextual filter value (taxonomy term ID) : **one in two the button is ticked**, the other not !

Ticking any radio button once the view is loaded gives correct results.

Errors reported :

* `Warning : Illegal offset type in isset or empty dans convert_exposed_input() (line 1165 of views/handlers/views_handler_filter.inc).`
* `Illegal choice 0 in field_statut_depart_value element.`

**EDIT :** I did put below as many details as I could find to illustrate the problem, but after searching and searching, basically **the question is** : since I can't find why such behaviour, nor why this is always the same value which is loaded by default, whichever setup I try : **How can I alter the form and ensure the default button is ticked on page loading.**

This filter filters a field which values can be "Open, Almost confirmed, Confirmed, Full, Closed", and I need to group the filter values :

* 1=\> Any value excepting Closed, **selected by default**
* 2=\> Almost confirmed or Confirmed

I played around with **Grouped filters** and **BEF**, and achieved the correct radio buttons display with at least 2 different setups. This is the last setup I tried.

I tried then to alter the form :

```
function MODULE_form_alter(&$form, &$form_state, $form_id) {
  if($form['#id']=='views-exposed-form-my-form'){
    $form['field_status_depart_value']['#default_value'] = 1;
    $form['field_status_depart_value']['#required'] = TRUE;
    //dpm($form);
  }
}

```

I could hide the error message with `$form['field_status_depart_value']['#validated'] = TRUE;` . It seems to be solving also the view returning empty result one in two... *but* now the result are filtered with one or another filter value, while the customer does not know it !

I tried without success to change the UI setup in many manners : with or without ajax, with or without BEF overwriting, optional or not, remember or not.. Same if I set to default select list, the exposed filter value **toggles from one to the other** at each page refresh.

After night & day fighting with that, I would feel really better to get some help, my most wished Christmas present ! Thanks a lot !

**EDIT : this is the relevant parts of code export.**

```
$handler->display->display_options['exposed_form']['options']['bef'] = array(

'field_status_depart_value' => array(
    'bef_format' => 'bef',
    'more_options' => array(
      'bef_select_all_none' => 0,
      'bef_collapsible' => 0,
      'is_secondary' => 0,
      'any_label' => '',
      'bef_filter_description' => '',
      'tokens' => array(
        'available' => array(
          0 => 'global_types',
        ),
      ),
      'rewrite' => array(
        'filter_rewrite_values' => '',
      ),
    ),
  ),
//...

/* Critère de filtrage: Commerce Product : Statut (field_status_depart) */
//RELEVANT LINES
$handler->display->display_options['filters']['field_status_depart_value']['value'] = array(
  1 => '1',
  2 => '2',
);
$handler->display->display_options['filters']['field_status_depart_value']['expose']['multiple'] = TRUE;
$handler->display->display_options['filters']['field_status_depart_value']['is_grouped'] = TRUE;
$handler->display->display_options['filters']['field_status_depart_value']['group_info']['remember'] = 1;
$handler->display->display_options['filters']['field_status_depart_value']['group_info']['default_group'] = '1';
$handler->display->display_options['filters']['field_status_depart_value']['group_info']['group_items'] = array(
  1 => array(
    'title' => 'Opened',
    'operator' => 'or',
    'value' => array(
      0 => '0',
      1 => '1',
      2 => '2',
      3 => '3',
    ),
  ),
  2 => array(
    'title' => Confirmed or almost confirmed',
    'operator' => 'or',
    'value' => array(
      1 => '1',
      2 => '2',
    ),
  ),
);

```

# Answer
> 0 votes
Should add select="selected" for the radio widget to solve this issue.

# Answer
> 0 votes
You have checked the option `Optional` `This exposed filter is optional and will have added options to allow it not to be set.`

If a filter is optional nothing will be automatically checked on page load.

If you want an option in a group of radios/checkboxes to be automatically checked you need to turn off the Drupal setting in that filter that makes it optional. This way your filter will get the `required` HTML attribute and the form won't be able to be submitted without it.

The option you set as Default will be the one checked, if you don't have the "Optional" checked as explained above.

BEF doesn't affect this, BEF affects the look and how user interacts, but not the core functionality of how form item is set up.

---
Tags: views
---


# Question
Title: How does the Geolocation content of a page filter is a Views block?
I have a website with Drupal 9 and the Geolocation module :

https://www.drupal.org/project/geolocation

I created a content type with a Geolocation field that contains coordinates.

My website uses the Olivero theme. I want to create a Views page with the summary my nodes and create a Views block with my nodes on a map.

The block must be on the same page, but it must be in the "Hero (full width)" region of the Olivero theme.

I have added a filter exposed in "Filtering criteria" of the Geolocation module to my page to filter the nodes in proximity.

I want this filter to be applied to the page, but also to the block. How to filter the page and the block ?

Here is the configuration of my Views :

The page.

The exposed filter "Proximity" for the Geolocation field, with its identifier.

The block.

I added a context filter, but the block is not filtered, if I filter the page with Proximity in "Filter criteria".

# Answer
To be able to inherit the exposed filter you need to use the "Attachment" Views Display type, not the "Block" Views Display type.

But you won't be able to control the theme Region positioning, you can only choose "Above" or "Below" the results. It may still look the way you want, or you may use CSS to adjust the layout.

Add the Attachment type to your Views, and copy all the settings to it that you have on Block and set the Attachment to `Inherit exposed filters:` to `Yes`.

You will find that option in the "central" column in Attachment options:

Then you can delete the "Block" Views Display.

This will apply the same exposed filter to the list of nodes and the map attachment.

You can also try the `Exposed form in block: Yes` option, add the block with the filter to a Region of your theme. This will control the placement of the Exposed filter, not the block with the map.

---

Alternatively also check out the Views Global Filter module and its Issues, maybe there's a version for newer Drupal.
> 0 votes

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


# Question
Title: Alter the exposed filters of a view, based on the view result
I have a view that displays matching nodes, based on contextual arguments.

I'd like to create an exposed filter that filters by node title, displaying a drop down (select) menu with options for every node in the result set.

I can modify / set the contents of the exposed filter using hook\_form\_alter, but the views query hasn't executed when this hook is called, so I don't have access to the result set. If I use hook\_views\_post\_execute then I have access to the result set, but the exposed filters form has already been rendered.

I know that I could write an EntityFieldQuery to select the nodes and set them within hook\_form\_alter, but that isn't very DRY as I would effectively be re-writing (and executing) the same query that Views will be executing anyway.

What's the best practice way to achieve what I'm looking for?

# Answer
Since this has gone unanswered, I decided to get creative and it's very easy with Entity Reference, Views Reference Filter and optional Rules.

1. Add an entity reference field to the content type that will reference its own node. So node/5's field will reference node/5. This can be done with Rules automatically. Old nodes can be updated with VBO if needed.
2. In your view, **Add** \> Entity Reference with the exact same filters etc. That should be automatic. Remove unwanted fields. Save the view.
3. Go back to your regular view, add an exposed filter (only for that pane) for the entity reference field we just created with **(reference filter)** written beside it.
4. In the exposed filter's settings, choose the Entity Reference view we just created. If it's just using contextual filters, don't worry about sending arguments.

The logic: The view will process the entity reference view first and provide its results to the first view as an exposed filter. I just tested it and it works perfectly. Takes about five minutes.
> 0 votes

# Answer
The closest solution to this with core Views is to use the Summary option of a Contextual filter, but use it in a separate Views Display of type Attachment.

In your case to show title it may be the Title contextual filter, or node ID contextual filter set to display the title instead of the ID (use Relationship if necessary, I haven't tested this).

The Attachment will display along with the results, but because of the Contextual filter set to Summary it will work like an Exposed filter, showing all the options from the results set.

You may need to tweak the appearance of the Summary to make it look more like a drop-down or something you had in mind, by default it will be a list of links.
> 0 votes

---
Tags: views
---


# Question
Title: How can I add a start and end date range in views exposed filter for Drupal 9 webform submission data?
I have created a view which displays all the webform submission data, but when it comes to views exposed filter for the dates I'm unable to find a way to add a webform submitted date as a range, I did add the dates separately giving an offset value but this isn't working as a range. is there a way to get a single date as range?

# Answer
Date data filters come with some options about how to filter them. You don't need to use two Date filters for the range, you do it on the one Date filter.

You need to choose the `Is between` Operator:
> 0 votes

---
Tags: views, webforms
---


# Question
Title: How can I show child categories in the parent category page?
I have created a new vocabulary with some extra fields and these taxonomy terms.

* Parent 1

+ Child 1.1
    + Child 1.2
    + Child 1.3
* Parent 2

+ Child 2.1
    + Child 2.2
    + Child 2.3
* Parent 3
* Parent 4
* Parent 5

In the parent category page, how can I show child categories with images or other custom fields?

# Answer
> 0 votes
The way terms are related is from child towards parent, not parent towards child.

So you need to start with taxonomy term views (Block Views Display) showing all the terms, filter them according to Parent term to only show children terms, this will show all of them, no matter what parent, but will not show parents (because they don't have parents of their own).

You can directly add any custom fields you have on the terms because this is a term type Views.

Then add a contextual filter for the Parent term, (Provide Default Value, from URL context).

When you place the Block on the page of the Parent term (don't forget to set the Block filter option) it will automatically filter it to show only the children terms of that parent.

This may need a bit different solution if Block is to be placed on a node Views type. Node type will already have a contextual filter for terms and the additional contextual filter for child terms will have to work together with it.

---
Tags: views, taxonomy-terms, 9
---


# Question
Title: When does system_requirements function runs?
When does Drupal call `system_requirements()`, which hardens permissions for files and for directories containing them?
Does Drupal call it in each cron run?

# Answer
> 3 votes
`system_requirements()` is a `hook_requirements()` implementation by the System module, which is one of the required Drupal core modules. (It means it's installed on every Drupal site.)

`hook_requirements()` implementations are invoked when:

* Modules are installed from the UI
* The site status report is shown
* A database update page is shown

For what I can see, Drupal core doesn't invoke `hook_requirements()` implementations during cron tasks, but a contributed or a custom module could invoke them when cron tasks are executed. They are invoked when /update.php is accessed, though.

---
Tags: cron
---


# Question
Title: How to determine the cause of sudden "content encoding error"s for logged-in Drupal users?
One day last week or so, seemingly out of the blue, logged in sessions started to throw content encoding errors. The site still works fine for anonymous users.

There's nothing in `error_log`, clearing caches and sessions didn't change anything and throttling the page loading speed shows it actually manages to draw the admin (and CiviCRM) toolbar and part of the page before giving up. The running PHP of course supports zlib and compression has been enabled for years. The dbs are acting normally.

The dev tools network tab appears to be useless when trying to determine which request response was bad. I've downloaded a few database snapshots and diffed them, but nothing stands out (though they're huge, so it's possible I missed something). I've made a minor version bump to Drupal to ensure the code is ok (8.9.20); no change. This thread had some helpful suggestions, but nothing brought me closer to finding the cause. One thing I haven't tried yet is to reimport older db backups to see if they work, to rule out a data issue. It's a heavy hammer, so I'm interested in:

How would you approach debugging this, pinpointing the source?

Edit: some more information: it's not a browser issue, since it didn't change and both firefox and chromium hit the same wall. It's hit on all pages, whether admin or on the frontend. When I say that the network tab is useless in identifying the failing request it's because not all are listed or if it's the main html one, the request headers are not set (even with persistent logs enabled). And compression clearly works, since some css files get through successfully before everything breaks.

I tried logging in via curl and comparing good and bad pages, but there was nothing obviously wrong in the requests upon diffing them. Just for posterity, the commands were:

```
curl -v -L $(drush uli --uid 99) --cookie-jar cookie.txt
curl --cookie cookie.txt -v --trace-ascii - good-url > good
curl --cookie cookie.txt -v --trace-ascii - bad-url > bad

```

# Answer
> 0 votes
Because the question is "how would you approach debugging this?", then this is a valid answer:

For a given request that reproduces the error, I would copy the cURL command syntax of the request using the browser tools, and execute the cURL command in a terminal so as to get a better idea of what is going on.

I would pass the `-I` option to `curl` to examine the response headers separately too.

---
Tags: debugging, http-request
---


# Question
Title: How can I add term's vocabulary name as body class?
I already had following codes added, which adds term ID as body class. However, how can I change the ID to term's vocabulary name?

For example:

> \<body class="term-type-cameras"\>

```
/**
 * Implements template_preprocess_html().
 */
function MYTHEME_preprocess_html(&$variables) {
  if (\Drupal::routeMatch()->getRouteName() == 'entity.taxonomy_term.canonical') {
    // Load the term entity and get the data from there.
    $term = \Drupal::routeMatch()->getParameter('taxonomy_term');
    $variables['term_id'] = $term->id();
    $variables['vocabulary_id'] = $term->bundle();
    $variables['attributes']['class'][] = 'term-' . $term->id();
  }
}

```

# Answer
You can use `$term->bundle()` method to get term vocabulary and then use it as part of the class.

```
$variables['attributes']['class'][] = 'term-type-' . $term->bundle();

```
> 2 votes

---
Tags: theming, taxonomy-terms
---


# Question
Title: checking route access for authenticated role
I'm outputting a link, made using `Url::fromRoute()`. If the current user is anonymous, and the route is not accessible to them, I'd like to show a 'Log in to use this link' text instead, simular to what comment module does.

But I want to show that link *only* if logging in *would* actually allow that. So I want to check `$url->access()` for an authenticated user.

I've tried making a temporary user entity with the authenticate role like this:

```
$dummy_authenticated_user = User::create([
  'roles' => [
    AccountInterface::AUTHENTICATED_ROLE,
  ],
]);

if ($url->access($dummy_authenticated_user)) {
  // ...
}

```

but that doesn't work because in the User entity class, the check for authenticated uses the uid:

```
public function isAuthenticated() {
  return $this->id() > 0;
}

```

Is there a way to do this?

# Answer
It's not necessary to create a user entity, you only need a user session object. Minimum requirement is that it implements AccountInterface:

```
$account = new UserSession([
  'uid' => 42,
  'roles' => ['authenticated'],
]);

$access = $url->access($account);

```
> 2 votes

---
Tags: users, routes
---


# Question
Title: How to translate a link defined in javascript with Drupal.t()
I have a template string that contains a link, which I want to translate afterwards throught the Drupal UI:

```
var html = `<p>${Drupal.t('<a href="/node/16">Check this out</a>')}</p>`

```

Two questions about that:

1. What is the correct way to build links in JS that could be translatable, (both the `anchor text` and the `href`)?
2. What should I do with these double quotes? Should I escape them? I've noticed in the UI that if I'd escape them with backslashs, each backslash '\\' is converted to a triple baskslash '\\\\', which makes no sense for me.

Any help will be very appreciated!

# Answer
> 2 votes
I would do this:

```
// Create a <p> tag, append an <a> tag, and make the
// link text translatable:
let html = $("<p/>").append(
  $("</a>", {href:"/node/16"}).text(Drupal.t("Check this out"))
);

```

After that you should clear the cache once, and go to the translate page (/admin/config/regional/translate)

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


# Question
Title: How to get "user pictures in posts" to not be greyed out/ disabled?
**Setup:** Drupal 9 with Claro admin theme and Olivero default theme.

**Scenario:** When I navigate to admin\>appearance\>settings\>global settings, under the first section "page element display", the first two options ("user pictures in posts" and "user pictures in comments") are both selected but greyed out and unable to change. The second two options below are both selected as well but aren't greyed out, and I'm able to freely switch between enabled and disabled. When I switch from global settings to Claro's settings, "page element display" is identical. However, when I switch to Olivero's settings, only "user pictures in comments" is enabled out of the four options. And again, the first two user picture settings are greyed out and unable to change, but the second two options are able to freely.

**Question:** How can I get "user pictures in posts" to not be grey/ disabled, so that I can enable this? I need my site to have profile/account pictures, which should display by the user's posts/ user's content (and their account if possible).

**What I've tried:**

* I've searched for modules (I did find a couple that might work but they were both unsecure, not maintained, and didn't even have the "composer require (...)" link with additional info typically found at the bottom of modules)
* Searched on Drupal answers (and google, reddit, quora) for a solution but no one else seems to be having this problem?
* Testing that "user pictures in comments" would work at least, and they do which tells me that being able to select "user pictures in posts" should work for me as well if I were able to select it
* "routine" troubleshooting- checked logs (nothing), cleared caches, updated composer, ran cron, updated db, as well as installing completely new and standard Drupal 9 with no added themes or modules (with same problem), so if this can't be reproduced or if no one else has the same issue, I have no idea what I'm doing differently or is unique about my installation. (Am running Drupal on Cloudways hosting, and did a regular installation as a test on there with same server and setup, as well as a test installation on my local environment using docker/ ddev. All 3 have this issue)

(I would really like to keep using the Olivero theme and not have to switch themes in order to get user account pictures. All help is greatly appreciated)

# Answer
> 0 votes
A look through of the code shows that these will be disabled if there is not a field on user entities named `user_picture`.

---
Tags: users, 9
---


# Question
Title: Looping through child elements in Twig 2.10 without using if
Currently I need to loop through child elements in my Twig to render dynamic grids properly. I have achieved this by using code similar to this

```
{% for key, child in element if key|first != '#' %}
  <div>{{ child }}</div>
{% endfor %}

```

This works exactly how I am needing it to work. However in Twig 2.10 using an `if` inside of a `for` is now deprecated and it is now recommended to use either a `filter` filter or an `if` inside the body of the `for`.

> Using an "if" condition on "for" tag in "main.twig" at line 1 is deprecated since Twig 2.10.0, use a "filter" filter or an "if" condition inside the "for" body instead (if your condition depends on a variable updated inside the loop).

I have been unable to figure out how to achieve the same effect using the `filter` filter in this case and could use some help with the change. I'm sure I'm making some basic error but my brain isn't solving this one quickly.

# Answer
You can install the Twig Tweak module and use the `children` filter it provides.

For example:

```
{% for child in element|children %}
  <div>{{ child }}</div>
{% endfor %}

```
> 6 votes

---
Tags: theming
---


# Question
Title: How can I make this JavaScript code get executed when the BigPipe module is enabled?
I keep struggling with getting JavaScript executed when I need to target a DOM element that is added via the BigPipe module when I'm logged in on my Drupal site.

The following code runs when I'm not logged in, but it's never executed when I am logged in.

```
(function ($) {
  'use strict';

  Drupal.behavior.bpBlockTest = {
    attach: function(context, settings) {
      $('.my-block', context).once('bp-block-testing').each(function () {
        var $myBlock = $(this);
        var $addOn = $('<span>addOn</span>');
        $addOn.appendTo($myBlock);
      });
    }
  }

}(jQuery));

```

# Answer
> 2 votes
For the current Drupal version this is the correct way to run Javascript (including jQuery, Drupal and the new Drupal once library):

```
(function ($, Drupal, once) {
  Drupal.behaviors.myModuleBehavior = {
    attach: function (context, settings) {
      once('myCustomBehavior', 'input.myCustomBehavior', context).forEach(function (element) {
        // Apply the myCustomBehaviour effect to the elements only once.
      });
    }
  };
})(jQuery, Drupal, once);

```

MODULE.libraries.yml or THEME.libraries.yml:

```
foobar:
  js:
    js/foobar.js: {}
  dependencies:
    - core/drupal
    - core/jquery
    - core/once

```

From https://www.drupal.org/docs/drupal-apis/javascript-api/javascript-api-overview

See also https://www.drupal.org/node/3158256

# Answer
> 1 votes
Until #3272693 is fixed, the fix for this is to remove `context` from your once function or use `$.filter()`

```
(function ($, Drupal, once) {
  Drupal.behaviors.myBehavior = {
    attach: function (context, settings) {
      // don't use context with once
      once('myBehavior', '.myBehavior').forEach(function (element) {});
      // or use filter
      $(context).filter('.myBehavior').once('myBehavior').forEach(function (element) {});
    }
  };
})(jQuery, Drupal, once);

```

---
Tags: javascript
---