title: Mink unable to connect to chromedriver

text:
# Question
Title: Mink unable to connect to chromedriver
I need help from someone who knows about testing web pages with Javascript in Docker containers. I have browser-based testing working and now I have scenarios which don't work without Javascript, so I'm trying to follow the Drupal documentation for running PHPUnit Javascript tests. The problem is that I'm getting

```
An unexpected error occurred while starting Mink: unknown error: net::ERR_CONNECTION_REFUSED

```

I can see that the `chrome` container is listening on port 9515:

```
# ss -a | grep 9515
tcp   LISTEN    0      5        *:9515              *:*

```

And I have confirmed that the `web` container can in fact connect to it on that port:

```
# curl --head http://chrome:9515
HTTP/1.1 404 Not Found
Content-Length:545
Content-Type:application/json; charset=utf-8
cache-control:no-cache

```

The `MINK_DRIVER_ARGS_WEBDRIVER` variable is set in `phpunit.xml` as instructed by the documentation linked above:

```
<env name="MINK_DRIVER_ARGS_WEBDRIVER" value='["chrome", {"browserName":"chrome","chromeOptions":{"args":["--disable-gpu","--headless", "--no-sandbox", "--disable-dev-shm-usage"]}}, "http://chrome:9515"]'/>

```

I can't run `chromedriver` directly in the web container, because it's running Ubuntu, which says you have to install the chromium `snap`, and Docker containers don't support `snap`. So I used the *Other ways to install and run chromedriver: Docker compose based chromedriver* instructions from the documentation linked above to put it in a separate container.

I'm out of my depth here. Help, please!

# Answer
The "easiest" (depending on your setup, it may not be all that easy) is to use the selenium-standalone-chrome docker image.

This image contains chrome as well as VNC for watching your tests.

Ddev has this image available as a plugin. Ddev is probably the simplest way to get set up, although you may need to remove the --headless flag from the plugin configuration to get core tests working.
> 1 votes

---
Tags: testing
---


# Question
Title: How do I display the title of the entities to which the user has no access?
I created a new content type with entity references to standard pages. I am using the Taxonomy Access Control module to control the access to these pages.

When users view a node of that content type, they unfortunately do not see page titles for which they do not have access (the title is a teaser). I want all entities to be listed (with the links to the pages), even if the users do not have access to actual page. Is that possible?

# Answer
It doesn't make sense to list links because if users follow it they will only see the Access denied page.

But you can create a Views list with the titles and disable the node access check for those Views. You have to be really careful not to reveal something unintentionally!

In d8 you can disable the node access check under **Query options** \> **Disable SQL rewriting**, it may be called differently in D7 but it will be in approximately the same location.
> 0 votes

---
Tags: 7, entities, display-suite
---


# Question
Title: How do you display the 'Title' field on display/page for custom content type?
I created a content type called 'News' and when creating a 'News' entity, I am able to enter a value for the 'Title' field.

However, when I go to 'Manage display' for the content type, the 'Title' field is not listed as one of the fields that can be managed.

Looking at the page/node for a 'News' entity, the 'Title' field only appears in the breadcrumb. However, I would like to display the 'Title' field elsewhere on the page (not only in the breadcrumb).

Is there a way to achieve this?

# Answer
In D8 the title is not handled as a normal field. As example for nodes the title is displayed in two ways:

1. Block: There is a block "Page Title". You can place this block in any region, it' possible to place it multiple times and the visibility can be configured so that it does not appear on every page.
2. Template: If the node is not displayed as page, then the title is displayed inside the node template.

You can use the same methods for your custom entity.

The first method should work with any custom entity. If you have a route to the entity and you place the block "Page Title" on your site, then the block should be able to resolve the title of the entity.

For the second method you have to put the title in a variable in preprocess and place it in the twig file.

Edit: You have no custom entity, it is a custom content type. So the title is there already as variable "label" and can be used right away:

**node--custom-content-type.html.twig**

```
  <h2{{ title_attributes }}>
      <a href="{{ url }}" rel="bookmark">{{ label }}</a>
    </h2>

```

This example is the linked title, but you can simply use `{{ label }}` if you don't need this.
> 8 votes

# Answer
I don't like the idea of falling back to another block (as I wanted a title **field**) or to needing to set the title in templates (too much logic in templates can get difficult to maintain on the long run). At least there seems to be some ongoing discussion on DO how to \[META\] Expose Title and other base fields in Manage Display after the loved Title module seems to be abandoned.

I also wouldn't recommend to install the pretty massive Display Suite for such a small thing. The new experimental core module Layouts Builder (video) might cover that, but still seems quite fiddly to configure.

So for now I live with the following little gem (source 1, source 2) that adds a new **pseudo field** to the display settings of each content type to render the page title as simple markup at the corresponding position inside the node's `$content`.

```
use Drupal\node\Entity\NodeType;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;

/**
 * Implements hook_entity_extra_field_info().
 */
function MYMODULE_entity_extra_field_info() {

  $extra = [];

  foreach (NodeType::loadMultiple() as $bundle) {

    $extra['node'][$bundle->id()]['display']['title_field'] = [
      'label'       => t('Title'),
      'description' => t('Title field'),
      'weight'      => 100,
      'visible'     => TRUE,
    ];
  }

  return $extra;
}

/**
 * Implements hook_ENTITY_TYPE_view().
 */
function MYMODULE_node_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {

  // You could get the node ID or anything else
  // you want from the node object here.
  $title = $entity->getTitle();

  if ($display->getComponent('title_field')) {

    $build['title_field'] = [
      '#type'     => 'inline_template',
      '#template' => '<h1>{{ title }}</h1>',
      '#context'  => [
        'title' => $title,
      ],
    ];
  }
}

```

---

Just found out there already is a little module which does exactly that: Pseudo Title.

> Pseudo Title creates a pseudo field that can be used to move up and down the content of the title in the same administration page where the display of other fields are managed.

And there also is the Manage display module.

> This project makes base fields such as 'title' available in "Manage Display".
>
> This very simple module uses the framework that is already in Core rather than inventing anything new. The goal is that most or all of this module will be absorbed into core #2353867: \[META\] Expose Title and other base fields in Manage Display.
> 5 votes

# Answer
If you inspect the entity from the scope of your TWIG templates the title should be available there. Also Node::getTitle()
> 2 votes

# Answer
There is a third way: If you have the modules Token and Token filter installed, you can use the token \[current-page:title\] in every place of your node and you get the rendered title. You can also put it in the content type as a default value in some field and hide the field from the user who provides the content. Then it is automatically displayed in this field.
> 2 votes

# Answer
For anyone looking for an updated answer, there's a 'Manage Display' contrib module which could soon be added into Drupal 10's core. You can find it here.
> 0 votes

---
Tags: 8, entities
---


title: Get MenuLinkContent object values

text:
# Question
Title: Get MenuLinkContent object values
get title and link of a menu link object in. I am trying to get title and link of a MenuLinkContent object and below is my code. I want to get title and link value. How I can get the title and Link url without foreach. something like- menu\_content\[\]-\>title and menu\_content\[\]-\>link

Defined name spaces

```
use Drupal\menu_link_content\Plugin\Menu;
use Drupal\menu_link_content\Entity\MenuLinkContent;

```

Code in

```
 function build(){

       $menu_content = current(\Drupal::entityManager()->getStorage('menu_link_content')->loadByProperties(array('id' => 123)));
  $menu_content_title =  $menu_content->values;
  \Drupal::logger('module_name')->notice('<pre><code>' . print_r($menu_content, TRUE) . '</code></pre>' );
    }

```

output:

```
Drupal\menu_link_content\Entity\MenuLinkContent Object
(
[insidePlugin:protected] =>
[values:protected] => Array
    (
        [id] => Array
            (
                [x-default] => 123
            )

        [revision_id] => Array
            (
                [x-default] => 124
            )

        [bundle] => Array
            (
                [x-default] => menu_link_content
            )

        [uuid] => Array
            (
                [x-default] => 8930a948-921e-4fasddb-be34-c98bcd6ae4c3
            )

        [langcode] => Array
            (
                [x-default] => en
            )

        [revision_user] => Array
            (
                [x-default] =>
            )

        [revision_created] => Array
            (
                [x-default] => 1626345445
            )

        [revision_log_message] => Array
            (
                [x-default] =>
            )

        [revision_default] => Array
            (
                [x-default] => 1
            )

        [isDefaultRevision] => Array
            (
                [x-default] => 1
            )

        [enabled] => Array
            (
                [x-default] => 1
            )

        [title] => Array
            (
                [x-default] => Example title
            )

        [description] => Array
            (
                [x-default] =>
            )

        [link] => Array
            (
                [x-default] => Array
                    (
                        [uri] => https://www.example.com
                        [title] =>
                        [options] => Array
                            (
                                [fa_icon] =>
                                [fa_icon_prefix] => fa
                                [fa_icon_tag] => i
                                [fa_icon_appearance] => before
                                [attributes] => Array
                                    (
                                        [class] => Array
                                            (
                                            )

                                        [target] => _blank
                                    )

                            )

                    )

            )

```

Got Title `$title = $menu_content->getTitle();` but Url not getting After apply code: `$url = $menu_content->get('link')->first()->getUrl();`

```
Drupal\Core\Url Object
(
[urlGenerator:protected] =>
[urlAssembler:protected] =>
[accessManager:protected] =>
[routeName:protected] =>
[routeParameters:protected] => Array
    (
    )

[options:protected] => Array
    (
        [fa_icon] =>
        [fa_icon_prefix] => fa
        [fa_icon_tag] => i
        [fa_icon_appearance] => before
        [attributes] => Array
            (
                [class] => Array
                    (
                    )

                [target] => _blank
            )

        [external] => 1
    )

[external:protected] => 1
[unrouted:protected] => 1
[uri:protected] => https://www.example.com
[internalPath:protected] =>
[_serviceIds:protected] => Array
    (
    )

[_entityStorages:protected] => Array
    (
    )

```

# Answer
> 0 votes
You didn't tell us why you've loaded the entity. You usually can get this information directly from the menu link plugin via `getUrlObject()`, without knowing whether there is an underlying entity or the menu link is defined differently, for example in a YAML file.

The entity has a Link field with the name `link`:

```
$url = $menu_content->get('link')->first()->getUrl();

```

See How to get the valid URL of a Link field from within a Twig template?.

The title is available for both, plugin or entity, by the same method:

```
$title = $menu_content->getTitle();

```

---
Tags: 8, theming
---


# Question
Title: Inline Template with Render Array in #context
I'm using the https://api.drupal.org/InlineTemplate to render a string with a variable, and that variable is itself another theme function.

My reading of the documentation is that this is supported; based on the fact that the `#context` variable can be a string **or render array**.

> **#context:** (array) The variables to substitute into the Twig template. Each variable may be a string or a render array.

However, my implementation is not working:

```
    $my_subtemplate = [
      '#type' => 'inline_template',
      '#template' => '{% trans %}my {{ foo }} here{% endtrans %}',
      '#context' => ['foo' => 'bar'],
    ];

    $my_string_with_embedded_themable = [
      '#type' => 'inline_template',
      '#template' => '{% trans %}Print this string and this subtemplate: {{ my_subtemplate }}.{% endtrans %}',
      '#context' => [
        'my_subtemplate' => $my_subtemplate,
      ],
    ];

```

The generated output is:

> Print this string and this subtemplate: .

I've confirmed that my\_subtemplate generates the correct output on its own:

> my bar here

But when its placed into a variable of another inline template, it does not render.

# Answer
> 3 votes
The issue not in the `inline_template` but the issue comes from `{% trans %}` if you place a render array variable into `{% trans %}{% endtrans %}` you will get the following error and it will not rendered:

> Warning: htmlspecialchars() expects parameter 1 to be string, array given in Drupal\Component\Utility\Html::escape()

So you have two options:

1) get the variable out of `{% trans %}{% endtrans %}` like the following:

```
    $my_subtemplate = [
      '#type'     => 'inline_template',
      '#template' => '{% trans %} my {{ foo }} here {% endtrans %}',
      '#context'  => [
        'foo' => 'bar'
      ],
    ];
    $my_string_with_embedded_themable = [
      '#type'     => 'inline_template',
      '#template' => '{% trans %} Print this string and this subtemplate: {% endtrans %} {{ my_subtemplate }} .',
      '#context'  => [
        'my_subtemplate' => $my_subtemplate,
      ],
    ];

```

2) Pre-render the renderable array variable to a string first.

```
    $my_subtemplate = [
      '#type'     => 'inline_template',
      '#template' => '{% trans %} my {{ foo }} here {% endtrans %}',
      '#context'  => [
        'foo' => 'bar'
      ],
    ];

    $renderer = \Drupal::service('renderer');
    $my_subtemplate = $renderer->renderRoot($my_subtemplate); // this fixes it

    $my_string_with_embedded_themable = [
      '#type'     => 'inline_template',
      '#template' => '{% trans %} Print this string and this subtemplate: {{ my_subtemplate }}.{% endtrans %}',
      '#context'  => [
        'my_subtemplate' => $my_subtemplate,
      ],
    ];

```

# Answer
> 0 votes
I like to also use `inline_template`, as a way to escape from the limitations of the drupal render arrays.

I would solve it with a single include to have templates as proper twig templates and not mixed with the logic (MVC approach + better syntax highlighting):

```
$my_string_with_embedded_themable = [
  '#type' => 'inline_template',
  '#template' => "{% include '@myTheme/path/my-template-file.html.twig' %}",
  '#context' => [
     'foo' => 'bar',
     'my_subtemplate' = 'my_subtemplate'
  ]
]

```

And then 'web/themes/myTheme/templates/path/my-template-file.html.twig':

```
<p>
{% trans %}Print this string and this subtemplate:{% endtrans %}
{% include '@myTheme/' ~ my_subtemplate %}.
</p>

```

The above example does not really require the include in the include, but the real approach is probably more complex anyway.

so `'web/themes/myTheme/templates/' + my_subtemplate`:

```
{% trans %} my {{ foo }} here {% endtrans %}

```

---
Tags: 8, theming
---


# Question
Title: Using Ultimate cron to set a specific time to run a function of module, but it is not working as expected
I have set ultimate cron job time **once a day** but it works at **every hour** because another default **site cron** is running every hour.

This code is working on production but not according to crontab time i.e once in a day. It is working every hour, i checked cron job list on acquia server there is one cron job set named "site cron" which is running every hour.

Code:

```
/**
 * Implements hook_cronapi().
 */
function demo_cronapi($op, $job = NULL) {

  $items['monitor_run'] = [
    'description' => 'Post Solution',
    'scheduler' => [
      'name' => 'simple',
      'simple' => [
        'rules' => ['0' => '0 7 * * *'],
      ],
    ],
  ];

  return $items;
}

/**
 * Trigger event to generate report.
 */
function monitor_run($job) {
  // logic code.
}

```

# Answer
> 0 votes
For D8/9 version of Ultimate cron. You can go to the listing of all cron jobs/queues (admin/config/system/cron/jobs). Then edit the perticular cron job you would want to setup time and select crontab from the dropdown and then add the time you want, you can check the rules there or from crontab guru.

# Answer
> -2 votes
Set your crontab to wget/curl cron.php once per minute `(* * * * *)`.

---
Tags: cron
---


# Question
Title: Avoid adding custom CSS to a node editing form?
Situation

* custom module adding styles
* don't add styles to node editing form

How to avoid adding the style to the editing forms?

```
function crossfade_page_attachments(array &$page) {
  $page['#attached']['library'][] = 'crossfade/crossfade';
}

```

# Answer
> 0 votes
Currently discovered answer derived from the metatag module)

```
function crossfade_page_attachments(array &$page) {
  if (\Drupal::service('router.admin_context')->isAdminRoute()) {
    return FALSE;
  }
  $page['#attached']['library'][] = 'crossfade/crossfade';
}

```

---
Tags: theming
---


# Question
Title: Serialization of 'Closure' is not allowed
I am getting the following error on *.../checkout/ID/order\_information* page after submitting payment details for *Review*.

> Exception: Serialization of 'Closure' is not allowed in serialize() (line 14 of core/lib/Drupal/Component/Serialization/PhpSerialize.php).

I have tried to catch the exception with a `try/catch` block, but it always gives that fatal error, if I unchecked *My billing information is the same as my shipping information* checkbox in the *Payment information* form.

I am using my custom payment method module for payment. Where should I look in the code to find what is causing the fatal error?

\__construct() method :-

```
public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, PaymentTypeManager $payment_type_manager, PaymentMethodTypeManager $payment_method_type_manager, TimeInterface $time) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $entity_type_manager, $payment_type_manager, $payment_method_type_manager, $time);

  if ($this->getMode() === 'test') {
    $url = "url given here";
  }
  else {
    $url = "url given here";
  }

  try {
    $this->soapClient = new SoapClient($url);
  }
  catch (SoapFault $e) {
    throw new PaymentGatewayException($e->getMessage());
  }
}

```

# Answer
I believe this comes from loading a connection in the SOAP client, and storing it in memory with `$this->soapClient`. The problem is that the soap client cannot be serialized. Serialization is the process of turning something into a string, generally so it can be stored in a databse or a file or something, to be retrieved later. The SOAP connection is not something that can be stored, which is why you are facing the issue.

You could potentially store the SOAP client in the construct method, then make the connection using the client when you actually need it. I'm guessing that the client, without a connection, can probably be serialized. I may be wrong though, and you may need to call the soap client dynamically every time you need it.
> 1 votes

# Answer
You might try adding `use DependencySerializationTrait;` to the class.

You could also try disabling caching if you can do without: `$form_state->disableCache();`
> 0 votes

---
Tags: 8
---


# Question
Title: "A fatal error occurred: Serialization of 'Closure' is not allowed"
I'm implementing a form using the Drupal form and AJAX. I've done this many times before, but now I stumble upon a problem I never seen before.

My AJAX event is called when the value of a textfield is changed.

```
'#ajax' => array(
   'callback' => array($this, 'ajaxRenderSheets'),
   'event' => 'change',
),

```

In my callback I refresh the form:

```
  public function ajaxRenderSheets(array &$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();
    $response->addCommand(new ReplaceCommand('#wrapper', $form['sheets-wrapper']));

    return $response;
  }

```

Then in my form, I check if the value of a field is filled out; if so, I execute a request to google sheets API (this form state value is filled out after the ajax request. So when the texfield above is filled out, this code gets executed).

```
  if ($spreadsheet_id = $form_state->getValue('spreadsheet')) {
    $spreadsheet_info = $this->googleManager->getSpreadsheet($spreadsheet_id);
  }

```

When that request is executed I get the error:

> A fatal error occurred: Serialization of 'Closure' is not allowed

Is this a Drupal core issue, or is this related to my code?

# Answer
> -1 votes
You might try adding `use DependencySerializationTrait;` to the class.

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


# Question
Title: How do I display a block after changing its ID?
I have a custom block. I want to change its ID, but after I changed it from *main\_menu\_block* to *header\_block*, the block is not displayed anymore.

I tried to:

1. Remove the block with the old ID
2. Change the block ID and clear the cache
3. Add the custom block on the admin side

The following is the block definition.

```
/**
 * Provides a 'Header Block' block.
 *
 * @Block(
 *   id = "header_block",
 *   admin_label = @Translation("Header Block"),
 *   category = @Translation("Custom"),
 * )
 */
class HeaderBlock extends BlockBase implements ContainerFactoryPluginInterface {
 //...
}

```

What steps should I take do to display the block after its ID has been changed?

# Answer
> 0 votes
Block placement is *usually* configuration (e.g. Block Layout, Layout Builder, etc.). That placement configuration will typically reference the block ID. You'll have to rename it *everywhere it's been referenced*.

You can do it in two ways:

* On Drupal admin, simply remove and re-add that block.
    + In most cases, the layout page may crash because of a non-existent block. So I'd
        1. Rename the block back to `main_menu_block` and clear the cache.
        2. *Remove the block* from Block Layout/Layout Builder.
        3. Rename it back to its `header_block` and clear cache again.
        4. Re-add the block.
* If you have a local dev environment
    1. Export your configuration (`drush cex`)
    2. Find all references to `main_menu_block` and rename it to `header_block`.
    3. Import back your configuration (`drush cim`)

In the odd case where the block is referenced in the content (e.g. node-specific layout, block field, etc.), you will have to update/remove it from the content in some way. If you're still in development, just replace it in the database using a client. But if it's already in production, you can use `hook_update_N()` to update that content programmatically.

---
Tags: blocks, 9
---


# Question
Title: Insert Media button in Ckeditor 5 not load with non admin user
I use Drupal 9.5.5, CKeditor 5 and BootstrapBarrio theme, but I have also used Claro theme.

I have disabled "Aggregate JavaScript files" and "Aggregate CSS files" option in Performance, Insert Media with Media Library does not load when a user (non admin) edits node.

I get that errors:

```
Ocurrió un error durante la ejecución de la respuesta Ajax: TypeError: $element.dialog is not a function ajax.js:411:22
    success ...com/core/misc/ajax.js?v=9.5.5:411
    (Asíncrono: promise callback)
    success ...com/core/misc/ajax.js?v=9.5.5:410
    success ...com/core/misc/ajax.js?v=9.5.5:207
    jQuery 6
    execute ...com/core/misc/ajax.js?v=9.5.5:266
    openDialog ...com/core/modules/ckeditor5/js/ckeditor5.js?rrrmc2:280
    init ...com/core/modules/ckeditor5/js/build/drupalMedia.js?rrrmc2:1
    fire ...com/core/assets/vendor/ckeditor5/ckeditor5-dll/ckeditor5-dll.js?v=35.4.0:5
    click ...com/core/assets/vendor/ckeditor5/ckeditor5-dll/ckeditor5-dll.js?v=35.4.0:5
    s ...com/core/assets/vendor/ckeditor5/ckeditor5-dll/ckeditor5-dll.js?v=35.4.0:5
    fire ...com/core/assets/vendor/ckeditor5/ckeditor5-dll/ckeditor5-dll.js?v=35.4.0:5
    t ...com/core/assets/vendor/ckeditor5/ckeditor5-dll/ckeditor5-dll.js?v=35.4.0:5

```

Format filter and CKeditor 5 appear when I edit a node, but when I click "Insert media" button, media library does not load.

Any idea?

Thanks.

# Answer
> 1 votes
I had the same issue with the regular Media Library field. The latest patch here helped me solving that: https://www.drupal.org/project/drupal/issues/3222107 Looks like theres an issue with the set weight of the JS file which results in that error.

Hope, that helps! :)

---
Tags: media
---


# Question
Title: How can i subscribe/unsubscribe to a simplenews newsletter programmatically?
I have the following code to set subscriptions to a simplenews newsletter on or off:

```
    $user_load = User::load($userID_current);
    $newsletter_subscriptions = [
        'newsletter1' => 'on',
        'newsletter2' => 'off',
        'newsletter3' => 'off',
        'newsletter4' => 'off',
    ];

    foreach ($newsletter_subscriptions as $system_name => $value) {

        $subscription_manager = \Drupal::service('simplenews.subscription_manager');

        $newsletter = \Drupal::entityTypeManager()
            ->getStorage('simplenews_newsletter')
            ->loadByProperties(['system_name' => $system_name]);

        if ($value == 'on') {
            $subscription_manager->subscribe($user_load, $newsletter);
        } else {
            $subscription_manager->unsubscribe($user_load, $newsletter);
        }
    }

```

in the `$newsletter` i got back NULL even though the properties exists (checked by this:

```
$newsletter_storage = \Drupal::entityTypeManager()->getStorage('simplenews_newsletter');
$system_names = $newsletter_storage->getQuery()
    ->execute();
foreach ($system_names as $system_name) {
    \Drupal::logger('simplenews')->info('Simplenews system name: @system_name', ['@system_name' => $system_name]);
}

```

whats wrong with my `$newsletter`? Does someone have experiences with simplenews 3?

# Answer
It seems that chatGPT and Drupal are not best friends, so i had to find the solution the oldschool (long & painful) way. The solution was to provide the right subscribe() arguments, so i didn't need the $newsletter.

```
$user_load = User::load($userID_current);
$newsletter_subscriptions = [
    'newsletter1' => 'on',
    'newsletter2' => 'off',
    'newsletter3' => 'off',
    'newsletter4' => 'off',
];

foreach ($newsletter_subscriptions as $system_name => $value) {

    $subscription_manager = \Drupal::service('simplenews.subscription_manager');

    if ($value == 'on') {
        $subscription_manager->subscribe($user_load->getEmail(), $system_name);
    } else {
        $subscription_manager->unsubscribe($user_load->getEmail(), $system_name);
    }
}

```
> -2 votes

---
Tags: entities, database, hooks
---


# Question
Title: CKeditor 5 does not load with Aggregate JavaScript files option
I use Drupal 9.5.5, CKeditor 5 and BootstrapBarrio theme.

When I enable "Aggregate JavaScript files" option in Performance, CKeditor does not load when a user (non admin) edits node.

I uninstalled Advanced CSS/JS Aggregation module also.

Any idea?

Thanks.

# Answer
It seems to be an error with JQuery UI library order

https://www.drupal.org/project/drupal/issues/3222107
> 1 votes

---
Tags: performance, css-js-aggregation
---


# Question
Title: How do I programatically change a webform's element type?
I am using a webform element 'select\_other' in the webform. We got a requirement that the *Other* field should only appear if certain conditions are satisfied. I already have a Webform Handler In place, and using the alterForm(), I tried to change the `#type` value, which removed the *Other* option, but duplicates the field wrapper property.

Is there any way to change the `#type` of a webform element programmatically from `webform_select_other` to `select`?

I was able to get around this by creating a dummy element for `select` and then in the alterForm, substituting the form element with the new one, using this code.

```
$type_of_request = $webform_submission->getElementData('type_of_request');

if ($type_of_request == "Process") {
  $webform = $webform_submission->getWebform();
  $dummy_element = $webform->getElement('dummy_element');
  $elements['original_element'] = $dummy_element;
  unset($elements['original_element']['#access']);
}

```

This is a workaround I am using.

# Answer
You should change it to always use a `select` element, and then make a separate `textfield` (or whatever type) field for "Other". Then you can use the Webform module's built-in conditionals to control when it shows, without using a webform handler for that.

1. Add a select element
2. Add a separate textfield "Other" element
3. Add a "visible" conditional on the Other element, with the condition being that the `type_of_request` is set to `Process`

**Example YAML**

```
  type_of_request:
    '#type': select
    '#title': 'Type of Request'
    '#options':
       review: Review
       process: Process
    '#required': true
  select:
    '#type': select
    '#title': 'Select'
    '#options':
       - 'Option 1'
       - 'Option 2'
    '#required': true
  other:
    '#type': textfield
    '#title': 'Other'
    '#required': true
    '#states':
      visible:
        - ':input[name="type_of_request"]':
            value: process

```
> 0 votes

---
Tags: 8, theming, webforms
---


# Question
Title: How to disable the option time_restriction that honeypot add to the forms
In the README file for the Honeypot module, it says:

> If you want to add honeypot to your own forms, or to any form through your own
>
> module's hook\_form\_alter's, you can simply place the following function call
>
> inside your form builder function (or inside a hook\_form\_alter):

```
> \Drupal::service('honeypot')->addFormProtection(   $form,
> $form_state,   ['honeypot', 'time_restriction'] );

```

> Note that you can enable or disable either the honeypot field, or the time
>
> restriction on the form by including or not including the option in the array.

I added this code to the `buildForm` function in the form I want to change, and also tried it with a `hook_form_FORM_ID_alter()`.

```
  \Drupal::service('honeypot')->addFormProtection(
    $form,
    $form_state,
    ['honeypot']
  );

```

However, the `$form['honeypot_time']` element still appears in the form. I only managed to remove it by adding `unset($form['honeypot_time'])` in my `hook_form_FORM_ID_alter`. I would like to use the way that Honeypot describes in its README file.

# Answer
> 1 votes
The problem with the module honeypot is that they don't explain in the README file that this code only works when you don't enable for all the forms in the site.

```
honeypot_add_form_protection(
  $form,
  $form_state,
  ['honeypot', 'time_restriction']
);

```

To disable time\_restriction you must use a `hook_fomr_FORM_ID_alter()` and unset the element inise the hook:

```
  if( (\Drupal::service('module_handler')->moduleExists('honeypot')) &&
      (isset($form['honeypot_time']))
     ) {
    unset($form['honeypot_time']);
  }

```

---
Tags: forms, services, 9
---


title: Stick comments on top

text:
# Question
Title: Stick comments on top
I need to stick specific comment on top of others which will remain from oldest to newest. When it's stick on top it's replies must be with that comment.

So

1. I made links in .module file which will take method from controller

```
    use Drupal\comment\CommentInterface;
    use Drupal\Core\Url;

    function hook_comment_links_alter(array &$links, CommentInterface $entity, array &$context) {

      $links['comment_on_top'] = [
    '#links' => [
      'comment-report' => [
        'title' => t('Stick on top'),
        'url' => Url::fromRoute('comment_on_top.add',
          ['comment' => $entity->id(),
        ]),
      ],
    ],
      ];

      $links['comment_on_top_remove'] = [
    '#links' => [
      'comment-report' => [
        'title' => t('Remove from top'),
        'url' => Url::fromRoute('comment_on_top.remove',
          ['comment' => $entity->id(),
        ]),
      ],
    ],
      ];
    }

```
2. This is my route file

```
    comment_on_top.add:
      path: '/my_module/stick/{comment}'
      defaults:
        _controller: '\Drupal\my_module\Controller\MyModuleController::stickOnTop'
      requirements:
        _permission: 'access content'

    comment_on_top.remove:
      path: '/my_module/remove/{comment}'
      defaults:
        _controller: '\Drupal\my_module\Controller\MyModuleController::removeFromTop'
      requirements:
        _permission: 'access content'

```
3. I created "sticked" field of the boolean type via drush gen field and added to comment type.
4. I put this two methods in my controller

```
public function stickOnTop($comment_id)
  {
    $comment = \Drupal::entityTypeManager()->getStorage("comment")->load($comment_id);
    $comment->field_sticked_to_top->value_1 = '1';
    $comment->save();
  }

  public function removeFromTop($comment_id)
  {
    $comment = \Drupal::entityTypeManager()->getStorage("comment")->load($comment_id);
    $comment->field_sticked_to_top->value_1 = '0';
    $comment->save();
  }

```

And it works!

But now I'm stuck in hook\_preprocess\_HOOK() to stick that comment at top also in my .module file

```
function my_module_preprocess_comment(&$variables)
{
// what to put where
}

```

When I use kint($variables); I'm getting all comments in separated objects.

Is solution to change weight $variables\['elements'\]\['#weight'\] ?

What now?

I saw this question How to place a specific comment on top of list and Best reply module and it helped but not for all problem.

# Answer
> 0 votes
I would do the following:

1. Add a new field to the comment with a field name of `field_sticky`.
2. Create a view, showing comments, with a page display.
3. Set the path of the display to whatever you want the path to be.
4. Set the view style to be unformatted list, set to display the rendered entity in the full view mode.
5. Add a sort on `field_sticky`, descending
6. Add another sort on `created`, either ascending or descending depending on what you want
7. Ensure the sort on `created` comes AFTER the sort on `field_sticky`, reorder if necessary.

Now you have a page, listing your comments, with sticky comments first, other comments after. If necessary, you can add a filter on a specific comment type to limit the results to that comment type.

---
Tags: 9, comments
---


# Question
Title: How can I set view permissions for content type to make it visible to autenticated users only?
I want a content type to be only visible to authenticated users.

Now the edit permission dialog only offers permissions for modification, not for displaying the published content.

Until Drupal 9, I've used the *Permissions by Term* module to limit public access for certain page areas and content types. Since *Permissions by Term* is not yet Drupal 10 compatible I had to remove it.

Is there an elegant, ideally Drupal 10 native way, to limit certain content types from public access?

>

# Answer
> 2 votes
Drupal core doesn't come with the separate "View content" permission.

To get that functionality you need to search for a module that adds it.

I think all the contributed modules that provide additional permissions, at least the ones I've tried, can be described as "Drupal native" because they tie into Drupal permissions system, they don't bypass it.

Permissions by Term is a great module, although it is an overkill if you have clean permission separation based on Content Type, and you don't need fine-grained control of individual nodes within a Content Type. You can use a content-type-based permissions module instead:

I've tried Content Access in the past and I was happy with it. You should search the modules list to investigate all that are available and pick according to your needs.

---
Tags: nodes, authentication-authorization, 10
---


title: Two visible states

text:
# Question
Title: Two visible states
I'm struggling with two visible states. WIth thE UI this is not possible.

I have an extended text/html field, which shall be visible if the following conditions match:

Scenario 1:

`System` checked AND `System` everything except `Google Kalender` and `Miscellaneous` selected AND branch is NOT `Gesundheit...` ist.

Scenario 2:

`Website` checked AND `System 2` everything except `Google Kalender` and `Miscellaneous` selected AND branch is NOT `Gesundheit...` ist.

That's what I've tried, but it doesn't work:

```
  - ':input[name="requirements__[System]"]':
      checked: true
    ':input[name="branch"]':
      '!value': 'Gesundheit, Fitness, Ärzte, Kliniken, Labore & Sozialwesen'
    ':input[name="system_"]':
      value: null
      pattern: ^(Gastronovi|OpenTable|Petleo|Resmio|Seatris)$
  - or
  - ':input[name="requirements__[Website]"]':
      checked: true
    ':input[name="branch"]':
      '!value': 'Gesundheit, Fitness, Ärzte, Kliniken, Labore & Sozialwesen'
    ':input[name="system_2"]':
      value: null
      pattern: '^(Aleno|Best Western Hotels Resort|Calendly|Dirs 21|HotelNetSolutions|OpenTable|Quandoo|Tablebooker|Terminland|Vioma)$'

```

# Answer
> 0 votes
I have an old project of mine with complex conditions. There the YAML is written just a little bit different. In your case it would look like this (you see the extra line-break?):

```
-
  ':input[name="requirements__[System]"]':
    checked: true
  ':input[name="branch"]':
    '!value': 'Gesundheit, Fitness, Ärzte, Kliniken, Labore & Sozialwesen'
  ':input[name="system_"]':
    value: null
    pattern: ^(Gastronovi|OpenTable|Petleo|Resmio|Seatris)$
- or
-
  ':input[name="requirements__[Website]"]':
    checked: true
  ':input[name="branch"]':
    '!value': 'Gesundheit, Fitness, Ärzte, Kliniken, Labore & Sozialwesen'
  ':input[name="system_2"]':
    value: null
    pattern: '^(Aleno|Best Western Hotels Resort|Calendly|Dirs 21|HotelNetSolutions|OpenTable|Quandoo|Tablebooker|Terminland|Vioma)$'

```

---
Tags: webforms
---


# Question
Title: Error when trying to retrieve a term with ajax
We are creating a custom form to edit a certain node. We do this above because there are some things that cannot be accomplished with the default form.

I want to use AJAX to populate the fields of the custom form with the values entered in the existing node, as shown below.

```
$form['client_company'] = [
  '#type' => 'entity_autocomplete',
  '#target_type' => 'taxonomy_term',
  '#tags' => TRUE,
  '#selection_settings' => array(
    'target_bundles' => array('vid', 'client'),
  ),
  '#weight' => '0',
];

```

```
$term = $this->taxonomyStroage->load($node->field_project_refercompany->target_id);
$form['client_company']['#value'] = $term;
$response->addCommand(new ReplaceCommand(".form-item-client-company", $form['client_company'])); // Line 208

return $response;

```

However, I get the following error.

> Error: Drupal\Core\Template\Attribute-\>\__toString() in Call to undefined method Drupal\taxonomy\Entity\Term::render() (/app/web/core/lib/Drupal/Core/Template/Attribute.php line.324)
> /app/web/modules/custom/projectmanager/src/Form/ProjectManagerForm.php (208): Drupal\Core\Ajax\AjaxResponse-\>addCommand(Object(Drupal\Core\Ajax\ReplaceCommand))

I do not know how to fix this.

# Answer
> 0 votes
In your code `$term` will be a term entity object.
Try setting the value of the form to the term id.
`$form['client_company']['#value'] = $term->id();`

EDIT:
Actually, it seems you already have the term ID, so you should not need to load the term entity. Maybe just do:
`$form['client_company']['#value'] = $node->field_project_refercompany->target_id`

---
Tags: forms, taxonomy-terms, ajax, 9
---


# Question
Title: How to modify the timezone options list?
I have a date range field in a paragraph which is set to allow setting the timezone. Can someone suggest how I can alter the list of options used to select the TZ?

For the user profile form a simple form\_alter exposes the timezone field options but when trying to alter the paragraph form I only see the timezone value already set as #date\_timezone.

Possibly I can override the class used to build this list?

I could do this with JS without too much effort; but not the correct approach.

# Answer
You can do that by using HOOK\_form\_alter and altering the widget of the field:

```
HOOK_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  // Check for your target entity form.
  // Replace 'your_entity_type' and 'your_entity_bundle' with your entity type and bundle.
  if (strpos($form_id, 'your_entity_type_your_entity_bundle') !== FALSE) {

    // Define the custom timezone options.
    $customTimezones = [
      'America/New_York' => 'America/New_York',
      'America/Los_Angeles' => 'America/Los_Angeles',
      'Europe/London' => 'Europe/London',
    ];

    foreach (array_keys($form['your_paragraph_field']['widget']) as $index) {

      // Check if the index is numeric, which indicates a paragraph item.
      if (is_numeric($index)) {

        // Alter the timezone options of the date range field.
        $form['PARAGRAPH_FIELD']['widget'][$index]['subform']['DATE_RANGE_FIELD']['timezone']['#options'] = $custom_timezones;
      }
    }
  }
}

```
> -1 votes

---
Tags: forms, 9, datetime
---


# Question
Title: Custom webform element saves value as array
I have created a custom webform element based on the webform example element. https://github.com/drupalprojects/webform/tree/8.x-5.x/modules/webform\_example\_element

It is still a simple text field, like the example but does some calculations form the current formid submissions.
Somhow every value entered in my text field shows up as "Array" (basically as the word "Array" in the submissions. I did a dpm($element\['#value'\]) in the validation handler of the element:

This does not happen with the example. It seems like I messed something up - maybe somone could shed a light on where to look for? Where is controlled in which format an input value is saved?

I have added some custom twig code - could this be the reason?

```
    <div class="custom-element">
  <label for="{{ element['#webform_id'] }}-{{ element['#key'] }}">{{ element['#title'] }}</label>
  <div class="custom-element-textfield">{{ dd(element) }}
    <input type="text" name="{{ element['#name'] }}[value]" value="{{ element['#value'] }}" class="form-control">
    <p>Available Seats: {{ element['#maxseats'] }}</p>
  </div>
</div>

```

Here is the yaml of the form:\`

```
uuid: 7349e6bd-4112-4b4b-8b8c-bf904e3a32c6
langcode: de
status: open
dependencies: {  }
weight: 0
open: null
close: null
uid: 1
template: false
archive: false
id: platzreservierung
title: Platzreservierung
description: ''
category: ''
elements: |-
  book_seats:
    '#type': my_webform_seatbooking_element
    '#title': 'Plätze buchen (Element)'
    '#multiple': false
    '#placeholder': '[webform:element:book_seats:maxseats]'
    '#maxseats': '100'
  test:
    '#type': webform_example_element
    '#title': test
    '#multiple': false
css: ''
javascript: ''
settings:
  ajax: false
  ajax_scroll_top: form
  ajax_progress_type: ''
  ajax_effect: ''
  ajax_speed: null
  page: true
  page_submit_path: ''
  page_confirm_path: ''
  page_theme_name: ''
  form_title: both
  form_submit_once: false
  form_open_message: ''
  form_close_message: ''
  form_exception_message: ''
  form_previous_submissions: true
  form_confidential: false
  form_confidential_message: ''
  form_disable_remote_addr: false
  form_convert_anonymous: false
  form_prepopulate: false
  form_prepopulate_source_entity: false
  form_prepopulate_source_entity_required: false
  form_prepopulate_source_entity_type: ''
  form_unsaved: false
  form_disable_back: false
  form_submit_back: false
  form_disable_autocomplete: false
  form_novalidate: false
  form_disable_inline_errors: false
  form_required: false
  form_autofocus: false
  form_details_toggle: false
  form_reset: false
  form_access_denied: default
  form_access_denied_title: ''
  form_access_denied_message: ''
  form_access_denied_attributes: {  }
  form_file_limit: ''
  form_attributes: {  }
  form_method: ''
  form_action: ''
  share: false
  share_node: false
  share_theme_name: ''
  share_title: true
  share_page_body_attributes: {  }
  submission_label: ''
  submission_exception_message: ''
  submission_locked_message: ''
  submission_log: false
  submission_excluded_elements: {  }
  submission_exclude_empty: false
  submission_exclude_empty_checkbox: false
  submission_views: {  }
  submission_views_replace: {  }
  submission_user_columns: {  }
  submission_user_duplicate: false
  submission_access_denied: default
  submission_access_denied_title: ''
  submission_access_denied_message: ''
  submission_access_denied_attributes: {  }
  previous_submission_message: ''
  previous_submissions_message: ''
  autofill: false
  autofill_message: ''
  autofill_excluded_elements: {  }
  wizard_progress_bar: true
  wizard_progress_pages: false
  wizard_progress_percentage: false
  wizard_progress_link: false
  wizard_progress_states: false
  wizard_start_label: ''
  wizard_preview_link: false
  wizard_confirmation: true
  wizard_confirmation_label: ''
  wizard_auto_forward: true
  wizard_auto_forward_hide_next_button: false
  wizard_keyboard: true
  wizard_track: ''
  wizard_prev_button_label: ''
  wizard_next_button_label: ''
  wizard_toggle: false
  wizard_toggle_show_label: ''
  wizard_toggle_hide_label: ''
  wizard_page_type: container
  wizard_page_title_tag: h2
  preview: 0
  preview_label: ''
  preview_title: ''
  preview_message: ''
  preview_attributes: {  }
  preview_excluded_elements: {  }
  preview_exclude_empty: true
  preview_exclude_empty_checkbox: false
  draft: none
  draft_multiple: false
  draft_auto_save: false
  draft_saved_message: ''
  draft_loaded_message: ''
  draft_pending_single_message: ''
  draft_pending_multiple_message: ''
  confirmation_type: page
  confirmation_url: ''
  confirmation_title: ''
  confirmation_message: ''
  confirmation_attributes: {  }
  confirmation_back: true
  confirmation_back_label: ''
  confirmation_back_attributes: {  }
  confirmation_exclude_query: false
  confirmation_exclude_token: false
  confirmation_update: false
  limit_total: null
  limit_total_interval: null
  limit_total_message: ''
  limit_total_unique: false
  limit_user: null
  limit_user_interval: null
  limit_user_message: ''
  limit_user_unique: false
  entity_limit_total: null
  entity_limit_total_interval: null
  entity_limit_user: null
  entity_limit_user_interval: null
  purge: none
  purge_days: null
  results_disabled: false
  results_disabled_ignore: false
  results_customize: false
  token_view: false
  token_update: false
  token_delete: false
  serial_disabled: false
access:
  create:
    roles:
      - anonymous
      - authenticated
    users: {  }
    permissions: {  }
  view_any:
    roles: {  }
    users: {  }
    permissions: {  }
  update_any:
    roles: {  }
    users: {  }
    permissions: {  }
  delete_any:
    roles: {  }
    users: {  }
    permissions: {  }
  purge_any:
    roles: {  }
    users: {  }
    permissions: {  }
  view_own:
    roles: {  }
    users: {  }
    permissions: {  }
  update_own:
    roles: {  }
    users: {  }
    permissions: {  }
  delete_own:
    roles: {  }
    users: {  }
    permissions: {  }
  administer:
    roles: {  }
    users: {  }
    permissions: {  }
  test:
    roles: {  }
    users: {  }
    permissions: {  }
  configuration:
    roles: {  }
    users: {  }
    permissions: {  }
handlers: {  }
variants: {  }

```

the /src/plugin/WebformElement/MyWebformSeatbookingElement.php

```
<?php

namespace Drupal\my_webform_seatbooking_element\Plugin\WebformElement;

use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Plugin\WebformElementBase;
use Drupal\webform\WebformSubmissionInterface;

/**
 * Provides a 'my_webform_seatbooking_element' element.
 *
 * @WebformElement(
 *   id = "my_webform_seatbooking_element",
 *   label = @Translation("Webform seat booking element"),
 *   description = @Translation("Provides a webform element for booking seats."),
 *   category = @Translation("Custom elements"),
 * )
 *
 * @see \Drupal\my_webform_seatbooking_element\Element\HwWebformSeatbookingElement
 * @see \Drupal\webform\Plugin\WebformElementBase
 * @see \Drupal\webform\Plugin\WebformElementInterface
 * @see \Drupal\webform\Annotation\WebformElement
 */
class HwWebformSeatbookingElement extends WebformElementBase {

  /**
   * {@inheritdoc}
   */
  protected function defineDefaultProperties() {
    // Here you define your webform element's default properties,
    // which can be inherited.
    //
    // @see \Drupal\webform\Plugin\WebformElementBase::defaultProperties
    // @see \Drupal\webform\Plugin\WebformElementBase::defaultBaseProperties
    return [
      'multiple' => '',
      'size' => '',
      'minlength' => '',
      'maxlength' => '',
      'placeholder' => '',
        'maxseats' => '',
    ] + parent::defineDefaultProperties();
  }

  /* ************************************************************************ */

  /**
   * {@inheritdoc}
   */
  public function prepare(array &$element, WebformSubmissionInterface $webform_submission = NULL) {
    parent::prepare($element, $webform_submission);

    //dpm('be-prepared');
    //dpm($element);

    // Get the current webform ID.
    $webform_id = $element['#webform_id'];

    // Get the current element's machine name.
    $machine_name = $element['#webform_key'];

    // Get all submissions for the current webform.
    $webform_storage = \Drupal::entityTypeManager()->getStorage('webform_submission');
    $submissions = $webform_storage->loadByProperties(['webform_id' => $webform_id]);

    // Sum up the values of all submissions for the current element.
    $total = 0;

    if (!empty($submissions)) {
      foreach ($submissions as $submission) {
        $data = $submission->getData();
        if (isset($data[$machine_name])) {
          $total += $data[$machine_name];
        }
      }
    }

    //dpm($total);

    // Add the total to the element's attributes.
    //$element['data-total'] = $total;
    // Here you can customize the webform element's properties.
    // You can also customize the form/render element's properties via the
    // FormElement.
    //
    // @see \Drupal\my_webform_seatbooking_element\Element\WebformExampleElement::processWebformElementExample
  }

  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state) {
    $form = parent::form($form, $form_state);
    // Here you can define and alter a webform element's properties UI.
    // Form element property visibility and default values are defined via
    // ::defaultProperties.
    //
    // @see \Drupal\webform\Plugin\WebformElementBase::form
    // @see \Drupal\webform\Plugin\WebformElement\TextBase::form
    return $form;
  }

}

```

the /src/Element/MyWebformSeatBookingElement.php

```
<?php

namespace Drupal\my_webform_seatbooking_element\Element;

use Drupal\Core\Render\Element;
use Drupal\Core\Render\Element\FormElement;
use Drupal\Core\Form\FormStateInterface;

/**
 * Provides a 'my_webform_seatbooking_element'.
 *
 * Webform elements are just wrappers around form elements, therefore every
 * webform element must have correspond FormElement.
 *
 * Below is the definition for a custom 'my_webform_seatbooking_element' which just
 * renders a simple text field.
 *
 * @FormElement("my_webform_seatbooking_element")
 *
 * @see \Drupal\Core\Render\Element\FormElement
 * @see https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Element%21FormElement.php/class/FormElement
 * @see \Drupal\Core\Render\Element\RenderElement
 * @see https://api.drupal.org/api/drupal/namespace/Drupal%21Core%21Render%21Element
 * @see \Drupal\my_webform_seatbooking_element\Element\HwWebformSeatbookingElement
 */
class HwWebformSeatbookingElement extends FormElement {

  /**
   * {@inheritdoc}
   */
  public function getInfo() {
    $class = get_class($this);
    return [
      '#input' => TRUE,
      '#size' => 60,
      '#process' => [
        [$class, 'processWebformElementSeatbooking'],
        [$class, 'processAjaxForm'],
      ],
      '#element_validate' => [
        [$class, 'validateWebformSeatbookingElement'],
      ],
      '#pre_render' => [
        [$class, 'preRenderWebformSeatbookingElement'],
      ],
      '#theme' => 'input__my_webform_seatbooking_element',
      '#theme_wrappers' => ['form_element'],
    ];
  }

  /**
   * Processes a 'my_webform_seatbooking_element' element.
   */
  public static function processWebformElementSeatbooking(&$element, FormStateInterface $form_state, &$complete_form) {
    // Here you can add and manipulate your element's properties and callbacks.

    return $element;
  }

  /**
   * Webform element validation handler for #type 'my_webform_seatbooking_element'.
   */
  public static function validateWebformSeatbookingElement(&$element, FormStateInterface $form_state, &$complete_form) {
    // Here you can add custom validation logic.
    //dpm($element['#value']);

  }

  /**
   * Prepares a #type 'email_multiple' render element for theme_element().
   *
   * @param array $element
   *   An associative array containing the properties of the element.
   *   Properties used: #title, #value, #description, #size, #maxlength,
   *   #placeholder, #required, #attributes.
   *
   * @return array
   *   The $element with prepared variables ready for theme_element().
   */
  public static function preRenderWebformSeatbookingElement(array $element) {
    $element['#attributes']['type'] = 'text';
    Element::setAttributes($element, ['id', 'name', 'value', 'size', 'maxlength', 'placeholder']);
    static::setAttributes($element, ['form-text', 'webform-seatbooking-element']);
    return $element;
  }

}

```

I get a Notice:

```

    Notice: Array to string conversion in Drupal\webform\WebformSubmissionStorage->saveData() (line 1350 of modules/contrib/webform/src/WebformSubmissionStorage.php).
    ...
    Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 52)
    Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 592)
    Drupal\Core\Form\FormBuilder->processForm('webform_submission_platzreservierung_add_form', Array, Object) (Line: 320)

```

Sorry for all that stuff. Maybe it helps.

# Answer
The mistake was in the twig code. Somehow I added an \[value\] to the "name" attribute of the input field.

```
<input type="text" name="{{ element['#name'] }}[value]" value="{{ element['#value'] }}" class="form-control">

```

Using something like this, it works.

```
<input type="text" name="{{ element['#name'] }}" class="form-control">

```
> 0 votes

---
Tags: webforms
---


# Question
Title: How do I define a separate form template for a multistep form?
I have a multistep webform in Drupal 8. I want to define spearate page template for each page in the webform.

I'm trying to define it using hook\_theme\_suggestions\_hook() like below. But how can I identify the current webform page currently viewing from $variables.

```
function custom_module_theme_suggestions_webform(array $variables) {
  $suggestions = array();

  $suggestions[] = 'webform__'.$current_page;

  return $suggestions;
}

```

# Answer
> 2 votes
I have fixed the issue using D8 temp storage functionality. I was able to get the current step in my form\_alter() hook, and I stored it in to a temp variable and accessed it in theme\_hook\_suggestions() hook().

```
/**
 * Implements hook_form_alter().
 */
function custom_module_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if($form_id == 'mywebform_id') {

    $current_page = $form_state->get('current_page');

    $tempstore = \Drupal::service('user.private_tempstore')->get('custom_module');
    $tempstore->set('current_page', $current_page);
  }
}

function custom_module_theme_suggestions_webform(array $variables) {
  $tempstore = \Drupal::service('user.private_tempstore')->get('custom_module');
  $current_page = $tempstore->get('current_page');

  $suggestions = array();

  $suggestions[] = 'webform__'.$current_page;

  return $suggestions;
}

```

# Answer
> 0 votes
You need to enable twig debugging in sites/default/services.yml If you don't have this file, you must do :

```
cd sites/default
cp default-services.yml services.yml

```

Set debug to true in place of false, in the twig.config section.

Then using Firebug or SHIFT+CTRL+c in chrome you'll be able to identify in the code source of the page the templates suggestions section by section, from page level, to a simple field or block level.

# Answer
> 0 votes
There are two options depending on what your template suggestion varies by - either page route or page path

**Page Route**

```
function custom_module_theme_suggestions_webform(array $variables) {
  $suggestions = array();
  $current_page = \Drupal::routeMatch()->getRouteName();
  // Replace non-alphanumeric characters with hyphens.
  $current_page = \Drupal\Component\Utility\Html::cleanCssIdentifier($current_page);
  $suggestions[] = 'webform__' . $current_page;

  return $suggestions;
}

```

**Page path / url**

```
function custom_module_theme_suggestions_webform(array $variables) {
  $suggestions = array();
  $current_url = \Drupal\Core\Url::fromRoute('<current>')->toString();
  $current_page = substr($current_url, strlen(\Drupal::request()->getBaseUrl()))
  // Replace non-alphanumeric characters with hyphens.
  $current_page = \Drupal\Component\Utility\Html::cleanCssIdentifier($current_page);
  $suggestions[] = 'webform__' . $current_page;

  return $suggestions;
}

```

# Answer
> 0 votes
I implemented this method in drupal 9 and webform latest version:

```
/**
 * Implements hook_webform_submission_form_alter().
 */
function module_name_webform_submission_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
if ($form['#webform_id'] === 'your_webform_id' && ($current_page = $form_state->get('current_page')) !== '') {
    $form['current_step'] = [
      '#type' => 'value',
      '#value' =>  $current_page,
    ];
  }
}

/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */
function module_name_theme_suggestions_webform_submission_form_alter(array &$suggestions, array $variables, $hook) {
  if ($variables['form']['#webform_id'] === 'your_webform_id') {
    $suggestions[] = $hook . '__' . $variables['form']['#webform_id'] . '__' . $variables['form']['current_step']['#value'];
  }
}

```

---
Tags: theming, 8, webforms
---


title: Disable theme debug.. just in one field

text:
# Question
Title: Disable theme debug.. just in one field
Is it possible to disable theme debug in one field? I don't want to disable theme debug, but when I set up background file from field, theme debug comments block this style functionality.

# Answer
No, this is not possible.

You would need to hack core in order to do it (`twig_render_template`), which might be ok for your local development.

The code in interest is this part:

```
if ($twig_service->isDebug()) {
  $output['debug_prefix'] .= "\n\n<!-- THEME DEBUG -->";
  ...
}

```

You could add a condition, like this:

```
 if ($twig_service->isDebug() && $template_file != 'awesome-template-file') {

```

I'm not sure what `$template_file` looks like, but I'm sure you could use it to make a condition to make the template file in question be skipped debug. This actually requires that the field uses it's own template file though.
> 2 votes

# Answer
Late to the party, but you can do the following:

```
      $twig_service = \Drupal::service('twig');
      $was_debugging = FALSE;
      if ($twig_service->isDebug()) {
        $was_debugging = TRUE;
        $twig_service->disableDebug();
      }

...
Do your thing.
...

      if ($was_debugging) {
        $twig_service->enableDebug();
      }

```
> 0 votes

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


title: Move term to a different vocabulary

text:
# Question
Title: Move term to a different vocabulary
I want to move a term from one vocabulary to another. In drupal 7 one can use taxonomy manager to do this but drupal 8 branch has not implemented MOVE yet and the module has not received any update in some time.

Taxonomy merge that is suggested in this thread has not even been ported in drupal 8 yet.

Thus the only way that is left to do such a task is programmatically.

How do you update programmatically the vocabulary or a term?

# Answer
> 7 votes
You should load existing term using term id and then update vid of term from new vocabulary vid then save it.

```

use Drupal\taxonomy\Entity\Term;

$term = Term::load($tid);
$term->vid->setValue('ID value');
$term->Save();

```

# Answer
> 0 votes
https://www.drupal.org/project/term\_manager

You can use Term Manager to move Term to new Vocabulary

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


title: How to use TrustedRedirectResponse()?

text:
# Question
Title: How to use TrustedRedirectResponse()?
I have used the following code on submit of a form to first send the form contents via guzzle and then redirect the form. I get the error

```
Error: Call to undefined function TrustedRedirectResponse()

```

this is my code:

```
use Drupal\Core\Routing\TrustedRedirectResponse;

function mymodule_submit(&$form, FormStateInterface $form_state){
$url="xyz.com";
$post_data=array("color"=>"red");

$client = \Drupal::httpClient();
  $response = $client->request('POST', $url, [
    'headers' => ['Content-Type' => 'application/x-www-form-urlencoded'],
     'verify'=>false,
    'form_params' => $post_data,

     ]);
    $status = $response->getStatusCode();

    $response = TrustedRedirectResponse(Url::fromUri($url));
    $form_state->setResponse($response);
}

```

I have two questions - how can I avoid the error , and is the order of getting the guzzle response and then getting the redirect response the correct order?

# Answer
> 5 votes
Your order seems correct, you need to instanciate a new TrustedRedirectResponse object like:

```
$response = new TrustedRedirectResponse($url_string);

```

# Answer
> -2 votes
The client-\>request is then unnecessary

```
 function my_module_submit(&$form, FormStateInterface $form_state) {
      $block = Block::load('bid');
      $block_settings = $block->get('settings');
      $url = $block_settings['url'];
      $query=$form_state->getValue('search_query');
      if (!empty($query)) {
        $url .= $query;
      }
      $response = new TrustedRedirectResponse($url);
      $form_state->setResponse($response);
    }

```

---
Tags: 8, forms, redirection
---


# Question
Title: Notice: Undefined index: elements in block_theme_suggestions_block()
I created block in the custom module. This block works, but I see Notice in the Recent log messages.

> Notice: Undefined index: elements in block\_theme\_suggestions\_block() (line 179 of /var/www/html/drupal-8.3.x-dev/core/modules/block/block.module)

I see `block_theme_suggestions_block()`.

```
function block_theme_suggestions_block(array $variables) {
  $suggestions = array();
  $suggestions[] = 'block__' . $variables['elements']['#configuration']['provider'];

```

And for my block `$variables['elements']['#id']` is `NULL`.

I can't understand why my block can't pass the ID as other blocks.

The code I am using is the following.

```
/**
 * @Block(
 *   id = "hello_messages",
 *   admin_label = @Translation("Hello messages"),
 * )
 */
class HelloMessagesBlock extends BlockBase {

  // ....

  /**
   * {@inheritdoc}
   */
  public function build() {
    $config = $this->getConfiguration();
    $hello_messages = hello_messages_block_get_messages($config['amount_messages']);

    return array(
      '#theme' => 'block--hello_messages_block',
      '#type' => 'markup',
      '#content' => $hello_messages,
      '#attached' => array(
        'library' => array(
          // Custom .css styles for block.
          'hello_messages_block/hello_messages_block',
        ),
      ),
    );
  }
}

```

```
/**
 * Implements hook_theme().
 */
function hello_messages_block_theme($existing, $type, $theme, $path) {
  return array(
    'block--hello_messages_block' => array(
      'variables' => array('content' => NULL),
      'base hook' => 'block',
    ),
  );
}

```

This is the content of block--hello-messages-block.html.twig.

```
{% extends "block.html.twig" %}
{% set attributes = attributes.addClass('block-hello-messages') %}
{% block content %}
{% for key, value in content %}
    <div class="message {{ key }}">
      <div class="user_image"><img src= "{{ value.image }}" /></div>
      <div class="username">{{ value.user }}</div>
      <div class="time">{{ value.time }}</div>
      <div class="message">{{ value.text }}</div>
    </div>
{% endfor %}
{% endblock %}

```

Why doesn't my block pass `$variables['elements']['#id']` to the theme suggestion hook?

UPDATE:

Thank you, Berdir. This solution helps me.

```
function hello_messages_block_theme($existing, $type, $theme, $path) {
  return array(
    'block--hello-messages-block' => array(
      'variables' => array('content' => NULL),
      'template' => 'block--hello-messages-block',
    ),
  );
}

```

# Answer
> 3 votes
You are not supposed to use the block template like this. This will be added automatically and it will be done so one level higher in the render array structure.

Check other block plugins, none of them use #theme like this, like SystemBrandingBlock::build()

You have two options:

1. Define the block template suggestions like system\_theme() does it and then overidde the output there. (the first in the list is the one for the branding block linked above, so you can easily connect the two things)
2. Make your own template for the content within the block. It will be wrapped by a generic block template, so you don't have to worry about that at all.

# Answer
> 0 votes
I've found that this notice is triggered when I include an extra underscore in my theme suggestion. This would not apply to your particular case, so I won't adapt my answer to your code. This is another way that this particular notice can be triggered, so hopefully it's helpful for someone who finds themselves here (probably future me). I can't explain why, I can only say that it's true.

**Doesn't trigger the notice:**

In block plugin build() method:

```
$menu_build['#theme'] = "menu__group_menu_breadcrumbs_admin";
return $menu_build;

```

In .module file:

```
/**
 * Implements hook_theme().
 */
function mymodule_groups_theme($existing, $type, $theme, $path) {
  $path .= '/templates';
  return [
    'menu__group_menu_breadcrumbs_admin' => [
      'template' => 'menu--group-menu-breadcrumbs--admin',
      'path' => $path . '/menu',
      'base hook' => 'block',
    ],
  ];
}

```

**Triggers the notice:**

In block plugin build() method:

```
$menu_build['#theme'] = "menu__group_menu_breadcrumbs__admin";
return $menu_build;

```

In .module file:

```
/**
 * Implements hook_theme().
 */
function mymodule_groups_theme($existing, $type, $theme, $path) {
  $path .= '/templates';
  return [
    'menu__group_menu_breadcrumbs__admin' => [
      'template' => 'menu--group-menu-breadcrumbs--admin',
      'path' => $path . '/menu',
      'base hook' => 'block',
    ],
  ];
}

```

---
Tags: 8, blocks, theming
---


# Question
Title: Which hook will allow me to change links in a page?
Which hook would allow me to change each link (given in `<a>` tags) in content pages and menus and change their attributes?

I need to implement this in a theme that uses Olivero as parent theme and the obvious `MYTHEME_preprocess_links()` results in a blank white screen (WSOD).

The only hook I've been able to use to change the page content is this one.

```
function MYTHEME_preprocess_field(&$variables): void {
    $content = $variables['items'][0]['content'] ?? false;
    $type = $content['#type'] ?? '';

    if ($content && $type === 'processed_text') {
        $dom = new DomDocument();

        libxml_use_internal_errors(true);
        $dom->loadHTML($variables['items'][0]['content']['#text']);
        $errors = libxml_get_errors();
        libxml_clear_errors();

        if (count($errors) === 0) {
            $edited = 0;

            foreach ($dom->getElementsByTagName('a') as $link) {
            }
        }
    }
}

```

# Answer
With thanks to the commenters I was able to figure out how to edit the DOM in content pages and menus.

Regarding version: **Drupal 10**.

*Replace "MYTHEME" with the machine name of your theme. Open your `MYTHEME.info.yml` file to see the name of your theme. It is case-sensitive.*

Within your `/themes/MYTHEME/` directory you may have a `MYTHEME.theme` file wherein you are able to declare hook functions. These hooks include those that allow you to preprocess data before it gets build into a template. It is here that you are able to adjust the HTML strings to your needs.

These hooks include a `$variables` parameter that will eat up all of your available memory if you try to print it via `var_dump`.

# Editing content

Content includes those that you build in `/admin/content` and those you build in `/admin/structure/block/block-content`.

The hook used to adjust the HTML of content pages is `MYTHEME_preprocess_field(&$variables)`.

Inspect `$variables['entity_type']` to determine if you are editing content or block-content.

The HTML string that will be used to build your content is in `$variables['items'][0]['content']['#text']`. Adjust that string via string manipulation or DOM manipulation with DOMDocument then overwrite `$variables['items'][0]['content']['#text']` with your edited string.

If using DOMDocument you may need to ignore all errors generated by loadHTML() because this feature does not understand HTML5 elements, but it can still work with them.

```
function MYTHEME_preprocess_field(&$variables): void {
    $content = $variables['items'][0]['content'] ?? false;
    $type = $content['#type'] ?? '';
    // Blocks are the pieces that are not content. These include the sidebar, search, header, and footer.
    $block = $variables['entity_type'] === 'block_content';

    if ($content && $type === 'processed_text') {
        $dom = new DomDocument();

        libxml_use_internal_errors(true);
        $options = LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD | LIBXML_NOERROR;
        $dom->loadHTML('<div>' . $content['#text'] . '</div>', $options);
        // Use this variable to inspect the errors when troubleshooting.
        // $errors = libxml_get_errors();
        libxml_clear_errors();

        $parsedHTML = $dom->saveHTML();

        // Errors are fine as long as the HTML string was successfully parsed by DOMDocument.
        if ($parsedHTML) {
            // Your code here to manipulate DOM.
        }
    }
}

```

# Editing menus

The hook used to adjust the HTML of menus is `MYTHEME_preprocess_menu(&$variables)`.

There are various menus in a Drupal page. These include `admin`, `main`, and `account`.

The menu items to adjust are within `$variables['items']`. The structure of each element within that array is:

```
items(array)
 - menu_link_content:{unique_id}(array)
 -  - is_expanded(boolean)
 -  - is_collapsed(boolean)
 -  - in_active_trail(boolean)
 -  - attributes(object)
 -  - title(string) Sample menu item
 -  - url(object)
 -  - below(array)
 -  -  - menu_link_content:{unique_id}(array)
 -  -  -  - is_expanded(boolean)
 -  -  -  - is_collapsed(boolean)
 -  -  -  - in_active_trail(boolean)
 -  -  -  - attributes(object)
 -  -  -  - title(string) Sample sub-menu item
 -  -  -  - url(object)
 -  -  -  - below(array)
 -  -  -  - original_link(object)

```

Each menu item may have sub-items. These are saved in the `['below']` key as an array.

If you want to adjust the url the `['url']` element holds a Drupal URL object. Refer to the documentation on how to adjust a Drupal URL object.

Here is an example to get you started:

```
function adjustMenuItem($item) {
    // Your code to adjust the elements of the $item array.

    // Handle recursive array elements.
    if (isset($item['below']) && is_array($item['below']) && count($item['below']) > 0) {
        foreach ($item['below'] as $key => $value) {
            $item['below'][$key] = adjustMenuItem($value);
        }
    }

    return $item;
}

function MYTHEME_preprocess_menu(&$variables): void {
    $name = $variables['menu_name'] ?? '';

    if ($name === 'main' && is_array($variables['items'])) {
        foreach ($variables['items'] as $key => $value) {
            $variables['items'][$key] = adjustMenuItem($value);
        }
    }
}

```
> 0 votes

---
Tags: hooks
---


# Question
Title: Adding Count Up module to custom front page
My end goal is to put several Count Up numbers on my custom front page. But I'm having trouble getting it implemented.

First, I installed the Count Up library (https://github.com/inorganik/CountUp.js) and put it in the libraries directory.

Then in mytheme.libraries.yml, I put

```
countup:
  version: 1.0
  js:
    /libraries/countup.js/dist/countUp.umd.js: {}
  dependencies:
    - core/jquery

```

And then in page--front.html.twig, I put

```
{{ attach_library('mytheme/countup') }}
            <div class="countup">
              <div id="transit_count">0</div>
              <script>
                $(function() {
                  let transits = new CountUp('transit_count', 6699);
                  if (!transits.error) {
                    transits.start();
                  } else {
                    console.error(transits.error);
                  }
                });
              </script>
            </div>

```

When I flushed the cache, I got this error: "Uncaught ReferenceError: CountUp is not defined".

What am I missing here? I'm pretty weak at JS so it could be something obvious.

Thanks!

# Answer
> 0 votes
Working sample:

```
     <!DOCTYPE HTML>
     <html>
     <head>
       <meta charset="UTF-8">
       <title>CountUp.js</title>

       <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
       <script src="dist/countUp.umd.js"></script>
     </head>

     <body>

        <div class="countup">
          <div id="transit_count">0</div>
          <script>
            (function ($) {
              let transits = new countUp.CountUp('transit_count', 6699);
              if (!transits.error) {
                transits.start();
              } else {
                console.error(transits.error);
              }
            })(jQuery);

          </script>
        </div>

    </body>
    </html>

```

# Answer
> 1 votes
You basically had it right, just a typo in your JS as the Nikit pointed out. The correct answer should include the JS in the template file.

In `mytheme.libraries.yml`:

```
countup:
  js:
    /libraries/countup.js/dist/countUp.umd.js: {}

```

Because that's there, there's no need to put it in the HEAD again.

And then in the template file, `page--front.html.twig`, put:

```
<script>
    (function () {
        let transits = new countUp.CountUp('transit_count', 6699);
        if (!transits.error) {
            transits.start();
        } else {
            console.error(transits.error);
        }
    });
</script>

```

However, you shouldn't *need* to put this in a template file, rather you should put it in a custom theme JS file(s) that deals with theme JS.

---
Tags: theming, javascript, 9
---


# Question
Title: Why does the error 'You have requested a non-existent parameter "site.path"' occur on module configure buttons?
When I click some configuration buttons for example in layout builder UI or the following buttons.  I get the following error in admin/reports/dblog

```
Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException:
You have requested a non-existent parameter "site.path". en Drupal\Component\DependencyInjection\Container->getParameter()
(linea 328 de /var/www/html/core/lib/Drupal/Component/DependencyInjection/Container.php)

```

A coworker with the same local but using windows (without wsl) has everything working normally. I used docker and ddev on ubuntu 22.04 LTS and on windows but with wsl, it doesn't work on both. Could it be something about permissions? I have sites/default/files and sites/default with a+w permissions

As the title says I am using Drupal 8.9.20 and I really do not know what to do.

If you need more information just ask me for it and I will edit the post.

Debugger data when gets to line 328

# Answer
The error is caused by the module CKEditor Anchor Link:

*/modules/contrib/anchor\_link/src/Plugin/CKEditorPlugin/AnchorLink.php*

```
 /**
   * Get the CKEditor Link library path.
   */
  protected function getLibraryPath() {
    // Following the logic in Drupal 8.9.x and Drupal 9.x
    // ----------------------------------------------------------------------
    // Issue #3096648: Add support for third party libraries in site specific
    // and install profile specific libraries folders
    // https://www.drupal.org/project/drupal/issues/3096648
    //
    // https://git.drupalcode.org/project/drupal/commit/1edf15f
    // -----------------------------------------------------------------------
    // Search sites/<domain>/*.
    $directories[] = \Drupal::getContainer()->getParameter('site.path') . "/libraries/";

```

The last line listed works only in Drupal \>=9.

You will find an increasing number of modules switching to Drupal 9/10 because Drupal 8 is no longer supported. The only issue here is that the module is still marked as `Works with Drupal: ^8 || ^9 || ^10`.

You either need to upgrade to Drupal 9 (recommended) or downgrade the module.

As a quick fix, until you find time to upgrade to Drupal 9, you can patch this code line to work with Drupal 8:

```
$directories[] = \Drupal::service('site.path') . "/libraries/";

```
> 1 votes

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


title: Adding cache tags to custom block

text:
# Question
Title: Adding cache tags to custom block
I have a **custom block** which load some taxonomy terms.

When I made changes to my taxonomies, the block isn't loading the new data (due to the cache). I'm passing all my taxonomy tags to my `#cache return`, but nothing append when I reload my page. I still have to `drush cr` to see the changes (even tried with `taxonomy_term_list`, but didn't work either)

Here's a simplified version of my block :

```
<?php

**
 * @Block(
 *   id = "custom_block",
 *   admin_label = @Translation("custom block"),
 *   category = @Translation("Custom")
 * )
 */
class CustomBlock extends BlockBase implements ContainerFactoryPluginInterface {

    // properties ...
    // constructor...
    // create() ...

    public function build() {
        // ...
        $tags = generate_tags_by_id($terms, self::CACHE_TAXONOMY);
        // ['taxonomy_term:34', 'taxonomy_term:40' ... ]
        return [
            /// ...
            '#cache' => [
                // 'tags' => //$tags,
                'tags' => ['taxonomy_term_list'],
            ]
        ];
    }
}

```

Here's my container config :

```
parameters:
  http.response.debug_cacheability_headers: false
  twig.config:
    debug: false
    auto_reload: false
    cache: true

```

Also tried to hook on taxonomy update, launch a custom event which invalidate those caches, but not working.

I'm using drupal 9.5.7

# Answer
> 1 votes
The issue seems to be that you don't build a render array and render it in the block.

If you want to theme a taxonomy term list then don't try to do this in the `block.html.twig` template. Use a custom template and put it in the block render array:

```
public function build() {
  // query $terms
  return [
    '#theme' => 'my_term_list',
    '#terms' => $terms,
    '#cache' => [
       'tags' => ['taxonomy_term_list'],
    ],
  ];
}

```

Then `#cache` will be recognized containing the list cache tag necessary if you query taxonomy terms in the database. The template can then include the cache tags of the single terms while rendering them.

Alternatively you can use a core `#type` or `#theme`, for example to render the terms in list tags. See Create unordered list in render array

---
Tags: blocks, 9, caching
---


# Question
Title: CKEditor 5 - access PHP plugin configuration from JS plugin?
I have provided a CKEditor 5 plugin a PHP configuration class. I am able to set and store configuration for the text editor plugin now, but do not know how to access that configuration value(s) from my JS plugin files that create the editor button/logic. How do you do that?

# Answer
Figured this out.

Your editor plugin YAML definition needs to specify a class and path to that class like so:

```
class: Drupal\mymodule\Plugin\CKEditor5Plugin\MyClass

```

Within that plugin, implement the following method:

```
  /**
   * {@inheritdoc}
   */
  public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array {
    $options = $static_plugin_config;
    $config = $this->getConfiguration();

    return [
      'your_ckeditor5_plugin_name' => [
        // an array or multidimensional array of config values
        // ex. 'foo' => $config['foo'] ?? $options['foo'],
      ]
    ];
  }

```

In your editor plugin JS, you can then access those values:

```
const config = this.editor.config.get('your_ckeditor5_plugin_name');

```

You need an appropriate schema too for both the Drupal configuration as well as the plugin configuration in the mymodule.ckeditor5.yml plugin definition. These serve as the default values, while `getDynamicPluginConfig` overrides that from what the user has provided in the configuration screen for that text format.
> 1 votes

---
Tags: 9, plugins
---


title: Find drupal site root directory path

text:
# Question
Title: Find drupal site root directory path
We have hosted one of our Drupal 7 site at Acquia.

How do I find site root directory - `/mnt/www/html/mysite/docroot/`?

> I'm using dpr(shell\_exec("drush status")); command in devel/php

Is there anyother way to find it?

# Answer
> 4 votes
Use `DRUPAL_ROOT`.

It is defined in index.php as:

```
define('DRUPAL_ROOT', getcwd());

```

# Answer
> 0 votes
Extending Krishna Mohan's answer, you can change directories to the root with:

```
cd `drush ev "echo DRUPAL_ROOT;"`; cd ..

```

---
Tags: drush
---


# Question
Title: how to alter entity reference field (taxonomies) field options in hook form alter
Can anyone please let me how to alter entity reference field (taxonomies) field options in hook form alter,

Seems the below code doesn't work.

```
/**
 * Implements hook_form_alter().
 */
function MY_MODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'node_article_edit_form' || $form_id == 'node_article_add_form') {
    $channel_options = [
      '1' => 'Term1',
      '2' => 'Term2',
      '3' => 'Term3',
      '4' => 'Term4',
      '5' => 'Term5',
    ];

    $form['field_channel'] = [
      '#title' => 'Channels',
      '#description' => 'Select Channel',
      '#type' => 'select',
      '#options' => $channel_options,
    ];
  }

}

```

**For context :**

I have a field named as channels in node article which is entity reference to channel taxonomy.

I would like to limit the list of terms visible to current user to the channels to which they are assigned in their user profile.

I am trying to achieve it by altering the node edit form and replacing channels field values from the current user logged in.

# Answer
> 0 votes
Thanks to @Hudri suggestion. I am able to achieve it without code using views module.

I followed the guide from How to Use Entity Reference Views in Drupal 8 - OsTraining and created a contextual filter to filter by current logged in user.

The important thing here is define Configure contextual filter When the filter value is NOT available.

---
Tags: forms, hooks, 9
---


# Question
Title: How to get value from object in twig template file?
I can print the result object by `{{ dump(item.value['#result']) }}` in theme `item-list--search-results.html.twig` template file.

I want to print the body field value("body"=\>"value") from the object.

How I will do ? I have tried some other ways which I know

* `{{ dump(item.value['#result']['node'].#values['body'][0]['value']) }}`
* `{{ dump(item.value['#result']['node']['#values']['body'][0]['value']) }}`

# Answer
For normal fields you can get the field value by appending the property name `.value`:

```
{% set node = item.value['#result']['node'] %}

{{ node.field_foo.value }}

```

For the body field you need an extra step to process the stored text format:

```
{{ {
  '#type': 'processed_text',
  '#text': node.body.value,
  '#format': node.body.format,
} }}

```
> 3 votes

---
Tags: 8, theming
---


# Question
Title: Why is MethodNotAllowedException thrown when an image is uploaded with CKEditor 5?
After updating Drupal to 9.5.3, I had this warning: `Deprecated modules found: CKEditor`.
So I upgraded from CKEditor to CKEditor 5 following this documentation.
After some setup on text formats, I made some tests creating a basic page.
When I try to insert one image using CKEditor button, the image appears and immediately I get an error message saying `Couldn't upload file`:  After validating the message, the picture is not there anymore.
Looking at Recent log messages, I found this error: `Symfony\Component\Routing\Exception\MethodNotAllowedException: in Drupal\Core\Routing\MethodFilter->filter() (line 46 of /Users/efalzon/Sites/falzon/core/lib/Drupal/Core/Routing/MethodFilter.php).`  I don't understand how it is relevant...
Any help?

# Answer
> 1 votes
If you have selected any language in "Administration pages language" in user settings try to set "no preference". This works for me in Drupal 10.

---
Tags: 9, wysiwyg
---


# Question
Title: Combine two fields to be displayed together
I have a content type that represents an object and amongst other fields this has two fields for dimensions - width and height. Currently the display has each field displayed one above the other:

```
                      10cm
                      20cm

```

because these are in independent divs I do not see a way to use CSS to position these in line with each other to give output like (should be centred on page as well):

```
                      Size 10cm x 20cm

```

The 'manage display' for a content type does not have any option to rewrite the output. How do I go about getting the output I require?

# Answer
> 2 votes
A simple way is achieve your job by jquery,( but if you have drupal developing knowledge you can do it in `tpl.php` or custom module) but quick method is using jquery, get `text` from one element , the append it to second and hide first

```
<div id="first">
blah 1
</div>
<div id="second>
blah 2
</div>

```

and your js will be something like this

```
$('.second').append($('.first').text());
$('.first').hide();

```

# Answer
> 1 votes
A few ideas:

1. You might look at physical field module, and then, if needed, create a custom formatter (either in code or using the custom formatter module). Note: I haven't tried the physical field module.
2. You could create another field called something like "dimensions", and use the computed field module to populate this field.
3. You could so the same thing as #2 without the computed field module using hook\_node\_presave ()
4. The display suite module provides a number of options for creating and displaying fields as well. Display suite does a lot of other things too. It could make sense if you want some of its other functions.

# Answer
> 1 votes
You can combine fields in modern Drupal (8, 9, 10 etc) with Field Token Value. This module provides a field type with a widget that allows defining the value containing tokens (which can be the values of other fields) as well as any plain text you want to put in there, with a simple field formatter to output the results of these tokens.

# Answer
> 0 votes
The cleanest way I see to accomplish this task is to use:

```
.field-one {
  float:left;
  width: xxx;
}

.field-two {
  float:left;
  width: xxx;
}

```

in your CSS. Drupal usually gives distinctive names for CSS per field. You can try this in Chrome Dev tools on your question above (on the spans, deleting the middle one).

This avoids adding an unnecessary module or involving jQuery for no reason.

You can accomplish the "Size" and "X" by using prefix/suffix in the field settings admin.

# Answer
> 0 votes
Even better, like in my case, a volume of volumes:

```
CSS:
.field-name-field-volume::before {
    content: "Volumes: ";
    float: left;
}
.field-name-field-volume {
    float: left;
}
.field-name-field-volume-total::before {
    content: " / ";
    float: left;
}

Template:
<?php print render($content['field_volume'])?>
<?php print render($content['field_volume_total'])?>

```

---
Tags: entities, nodes
---


title: Strip exif data from images

text:
# Question
Title: Strip exif data from images
It seems most people rather keep the exif data, and have trouble keeping it. I have the opposite problem - we have a profile picture upload and it keeps the exif data. I'd like to strip that off the images. Is there a way to actively do that?

# Answer
> 3 votes
You can do this by implementing `hook_file_presave($file)`

> This hook is called when a file has been added to the database. The hook doesn't distinguish between files created as a result of a copy or those created by an upload.

In this hook, you need to:

1. Test if file is really an image. I suggest using mimetype for this task: `$file->filemime`
2. Recognize which image processing library your Drupal is using. See `image_get_available_toolkits()`, `image_gd_check_settings()` and ImageMagick.
3. Process that file. This part is general programming issue already well answered on Stack Overflow \- I see no point in reposting it here, I think I covered Drupal part of the question now.

# Answer
> 0 votes
Now, it looks like the easiest way to do this is with File metadata manager (Drupal 8 and above). It has a submodule file\_mdm\_exif, which allows you to read and write EXIF information for JPEF and TIFF images.

You would still need to add some custom code to automatically remove EXIF data before saving.

# Answer
> 0 votes
To strip the metadata from image styles, you can use the Image Effects module. Install the module, go to the relevant image styles (`/admin/config/media/image-styles/manage/`), and then add the **Strip metadata** effect.

---
Tags: media
---


# Question
Title: Barrio Theme 5.5.10 Main Menu submenu does not output list items
I need help with the Barrio Theme submenus. I upgraded our site to 5.5.10 to discover the menu has stopped working. In my attempt to figure this out, I recreated a test site locally and installed a Drupal 9.5.5 legacy-project and barrio 5.5.10.

The submenu is not outputting the listing of the submenu. The documentation says all parents must be expandable and they are. I dont know the system is ignoring the menu items.

Any ideas?

Code that outputs:

```
<ul class="clearfix nav navbar-nav">
 <li class="nav-item">
    <a href="/legacy/" class="nav-link nav-link--legacy- is-active" data-drupal-link-system-path="<front>">Home</a>
  </li>
    <li class="nav-item menu-item--expanded dropdown">
    <a href="" title="EMTP Products " class="nav-link dropdown-toggle nav-link-" data-bs-toggle="dropdown" aria-expanded="false" aria-haspopup="true">Products</a>
        <ul class="dropdown-menu">
            <li class="dropdown-item">
                    <a href="/legacy/products/emtp" title="EMTP Software for transient analysis" class="nav-link--legacy-products-emtp">EMTP</a>
              </li>
            <li class="dropdown-item menu-item--collapsed">
                    <a href="" title="Modules to extend EMTP" class="nav-link-">Modules</a>
              </li>
        </ul>
  </li>

```

Greatly appreciated if anyone has an idea

# Answer
1. First make sure you have set the **Number of levels to display** as required(3 in your case). You can do it by visiting `admin/structure/block/manage/Your_Theme_Machine_Name`.

2. Then check the **Flyout style main menu** option in your theme settings under `Components > Navbar behaviour`. You can do it by visiting `admin/appearance/settings/Your_Theme_Machine_Name`.

**Explanation**: The third level items are not showing because according the maintainer of the contrib theme bootstrap\_barrio, that's how it is designed. Bootstrap Navbar by default supports only 2 levels of dropdown menu. You can read more about this issue here. https://www.drupal.org/project/bootstrap\_barrio/issues/3133347#comment-14021486
> 0 votes

---
Tags: theming
---


# Question
Title: how to get form element value before submit in drupal
I have a form with fields for first name and last name. When users log in, I want to redirect them to another page and get first name and last name values.

This is what I tried.

```
function doner_user_login(&$edit, $account) {
  drupal_get_form('doner_step_3');
  $val = $form_state['values']['about_fname'];

  $edit['redirect'] = "http://test.good.com/moll/ijs/d67/step31?fname=$val";
}

```

# Answer
Once an user has logged in, the GLOBALS $user with the information related to this user is ready to use. It isn't neccesary to add an argument to the URL in your redirection.

If it isn't loaded the information you want, you could store that variable in the $user object.

```
function doner_user_login(&$edit, $account) {
  drupal_get_form('doner_step_3');
  $GLOBALS['user']->doner_variables = $form_state['values']['about_fname'];
}

```
> 1 votes

# Answer
`hook_user_login()` implementations should not render a new form; they should change the values of the `$account` object (which is for the account used to log in), save values in a database table, or redirect users to a different page, for example.

It is not clear from the question which form is the *doner\_step\_3* form, which values it contains, and in which way those values are related to the logged-in user.
Supposing that `doner_get_fname($uid)` is a function that returns a user first name given the user ID, the code to use should be similar to the following one.

```
function doner_user_login(&$edit, $account) {
  $edit['redirect'] = 'http://test.good.com/moll/ijs/d67/step31?fname=' . doner_get_fname($account->uid);
}

```

`doner_get_fname()` should retrieve the first name from where the form submission handler for the *doner\_step\_3* form stored it. Normally, the values submitted in a form are stored in persistent variables or a database table. (In the case of values associated to users, the latter is more common.)
> 0 votes

---
Tags: 7, users
---


# Question
Title: How to save the input values in an unfinished node form
Drupal 6:

Is there a way to save the values in a node form, so that if the user leaves the page before the form is completed, they can access that form at a later time and have the values that they input still in their respective form fields?

Can you use node\_api to somehow save the node as "unpublished" once the user gets to a certain point in the form? How would it work if required fields aren't yet filled in at the time of the pre-save?

# Answer
> 1 votes
You could save the values in the users session (`$_SESSION`) and clear the value(s) when the form is submitted. You would have to use AJAX to update the values whenever a field is changed, as you can't do it when the user decides the leave the page.

# Answer
> 0 votes
In Drupal 8+, there are a couple of modules for this:

The latter looks like it's more up-to-date and has many more users.

---
Tags: forms, nodes
---


# Question
Title: Remove disabled attribute/state during submission
I would like to find a way to remove the `disabled` attribute from webform fields inside a **custom Handler**.

The `disabled` attribute is currently being applied to webform elements during user input via `conditions/states` with the UI and I would like to remove this attribute after clicking submit so that these webform fields will submit their values.

I've been looking through the available functions from the `WebformhandlerBase`: https://git.uwaterloo.ca/drupal-org/webform/blob/8.x-5.9/src/Plugin/WebformHandlerBase.php, but can't find where this attribute exists, and don't see an approach to alter/remove it.

`public function validateForm() {}` seems like a good moment in time to alter, but I can't find this attribute.

Noting I have success doing this with jQuery but would prefer doing this in my custom Handler

How do you remove a form field attribute (`disabled`) with a custom Handler after a user clicks submit?

# Answer
> 0 votes
Once you submit a form, you are not able to retrieve disabled inputs (https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#constructing-the-form-data-set). That said:

* You cannot modify input's attributes from server-side since the submission data is already posted.
* Developing your solution with jQuery on `.submit()` function is a good idea (far away from bad practices).
* You can also make another work around: instead of disabling you could use readonly="readonly" attribute (https://www.w3.org/TR/REC-html40-971218/interact/forms.html#h-17.12.2)

# Answer
> 0 votes
Here is a workaround that seems to work, for example

1. Create a number element with key as num\_a 2.Create a hidden checkbox element with its key as num\_a\_ignore
2. Add a condition to num\_a element in #1 to turn on the checkbox when value or num\_a is say greater than 10
3. Write a custom handler which probes for \*_ignore keys and matches them with any element keys. When a match is found and the value of \*_ignore key is true that element is disabled and processed accordingly.

---
Tags: 8, webforms
---