# Question
Title: How do I render content generated by a controller in a custom block?
To render a form in a block, I can use the following code.

```
class LoremIpsumBlock extends BlockBase {

  public function build() {
    // Return the form @ Form/LoremIpsumBlockForm.php.
    return \Drupal::formBuilder()->getForm('Drupal\loremipsum\Form\LoremIpsumBlockForm');
  }

```

How can I render in a block the output of a controller? Is it possible, or do I have to duplicate the controller class code in the block class?

The example in the documentation is too simple and it shows how to render a literal string.

```
class HelloBlock extends BlockBase {

  public function build() {
    return array(
      '#markup' => $this->t('Hello, World!'),
    );
  }
}

```

# Answer
> 4 votes
you can call the controller class inside the custom block,

check this below example,

Controller:

```
   <?php

    namespace Drupal\custom_example\Controller;

    class ExampleController {

         public function example(){

           return array(
             '#title' => 'Example',
             '#markup' => 'This is a custom module',

            );
         }
    }

```

custom Block: Here, Use the ExampleController like this,

```
 use Drupal\custom_example\Controller\ExampleController;

```

ExampleController should be the class name of the Controller

```
<?php

namespace Drupal\custom_example\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\custom_example\Controller\ExampleController;

class CustomBlock extends BlockBase {

  public function build() {

     $controller_variable = new ExampleController;
     $rendering_in_block = $controller_variable->example();
     return $rendering_in_block;

  }

}

```

Create the new instance using the class name and call the function in the block

# Answer
> 13 votes
@4k4 is correct in their answer that it is preferable to refactor the shared code into a separate class (probably a service).

However, if that is not an option (because you are building on core or contributed code that you cannot change) it is still possible to re-use the output of a controller that uses dependency injection (DI). To do so, inject the class\_resolver service into your block and use it to get a controller object. Your block code would look something like this:

```
<?php

namespace Drupal\my_module\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\DependencyInjection\ClassResolverInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a custom block containing the output of a controller.
 *
 * @Block(
 *  id = "controller_block",
 *  admin_label = @Translation("Controller block"),
 * )
 */
class ControllerBlock extends BlockBase implements ContainerFactoryPluginInterface {

  /**
   * Class Resolver service.
   *
   * @var \Drupal\Core\DependencyInjection\ClassResolverInterface
   */
  protected $classResolver;

  /**
   * Constructs a new ControllerBlock object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param string $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver
   *   The class resolver service.
   */
  public function __construct(
    array $configuration,
    $plugin_id,
    $plugin_definition,
    ClassResolverInterface $class_resolver
  ) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->classResolver = $class_resolver;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('class_resolver')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    // Assuming that \Drupal\my_module\Controller\MyController::build is a
    // public function that returns the controller output.
    $controller = $this->classResolver->getInstanceFromDefinition('\Drupal\my_module\Controller\MyController');
    return $controller->build();
  }

}

```

# Answer
> 6 votes
A controller depends on a request and route match. In simple cases you can treat the controller like a normal class, but more complex controllers with DI and route arguments will fail. You should refactor the code so that the shared content of the controller and block is built in a different place both have access to, like this is the case in your block example, where this is a form.

# Answer
> 0 votes
Use namespace for your controller like:

"use Drupal\your\_custom\_module\Controller\your\_class\_name;"

then you can call the function of "your\_class\_name", where you have generated all the tables/html, inside you build() of Class "HelloBlock" .

# Answer
> 0 votes
Either the part of the code used by the controller and the block is implemented by a service, or the block code instances the controller using the *controller\_resolver* service.

```
namespace Drupal\mymodule\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Controller\ControllerResolverInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a custom block that shows a controller's output.
 *
 * @Block(
 *  id = "mymodule_block",
 *  admin_label = @Translation("Mymodule block"),
 * )
 */
class MymoduleBlock extends BlockBase implements ContainerFactoryPluginInterface {

  /**
   * The controller resolver service.
   *
   * @var \Drupal\Core\Controller\ControllerResolverInterface
   */
  protected $controllerResolver;

  /**
   * Constructs a new \Drupal\mymodule\Plugin\Block\MymoduleBlock object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param string $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
   *   The controller resolver service.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, ControllerResolverInterface $controller_resolver) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->controllerResolver = $controller_resolver;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('controller_resolver')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    // $controller is a string "$class_or_service:$method" or "$class_or_service::$method".
    $callable = $this->controllerResolver->getControllerFromDefinition($controller);
    // $callable is an array [$object, $method].
  }

}

```

---
Tags: 8, blocks
---


# Question
Title: How do I convert special characters into html in twig
I have some list items in drupal 8 which created by `item_list` template.I am sending some `<a>` tagged data to the `item_list` template. My idea was to get the output as `<a href="/this-is-new.html">This is new page</a>`.

But it returns the output as `<li><a href="/this-is-new.html">This is new page</a></li>`.

I need to print this in a twig template. But with the output I had it renders as a string in the template not as a html anchor tag. I needed to view a link to another page in template. But all I am getting is a string with the `<a href="/this-is-new.html">This is new page</a>`. What should I do?

# Answer
> 6 votes
**NOTE:** this should be avoided as it is considered bad practice as mentioned in the comments, leaving here as an **example to avoided**

Inside your twig template try this

```
  {{ var|raw }}

```

where `var` is the variable being printed.

For more information here

# Answer
> 3 votes
Try using convert\_encoding('UTF-8', 'HTML-ENTITIES') twig filter. For example {{ item|convert\_encoding('UTF-8', 'HTML-ENTITIES')}}.

# Answer
> 3 votes
To send html markup to a template use a `#markup` render element

```
$variables['link'] = [
  '#markup' => '<a href="/this-is-new.html">This is new page</a>',
];

```

so that the html tags are not escaped when you output the variable in twig:

```
{{ link }}

```

The link here is only an example. There are better ways to build links, see How do I create a link?

# Answer
> 3 votes
There is a module to use the old convert\_encoding('UTF-8', 'HTML-ENTITIES') for D9 https://www.drupal.org/project/twig\_htmlspecialchars\_decode

# Answer
> 2 votes
> But it returns the output as `<li><a href="/this-is-new.html">This is new page</a></li>`.

The reason for this, is because Twig is auto escaping your HTML. List only allows list related HTML tags, like `<li>`.

> I have some list items in drupal 8
>
> My idea was to get the output as `<a href="/this-is-new.html">This is new page</a>`

Don't use List as your field type, instead use Link and set it to **unlimited**.

---

Now when you add a new node:

# Answer
> 1 votes
You can make use `Markup class` which defines an object that passes safe strings through the render system.

1.) You first need to create a TwigExtension.php class inside a module and define a function which will actually return a formatted string.

2.) Use that function inside any of your twig files to render formatted strings.

3.) Do Rebuild the cache, using `Drush cr`.

-\> **Create a module\_name.services.yml file under modules/module\_name:**

```
services:
  module_name.twig.TwigExtension:
    class: Drupal\module_name\TwigExtension
    tags:
      - {name: twig.extension}

```

-\> **Create a TwigExtension.php under modules/module\_name/src/TwigExtension.php :**

```
<?php

namespace Drupal\module_name;

use Drupal\Core\Render\Markup;

/**
 * Class DefaultService.
 *
 * @package Drupal\module_name
 */
class TwigExtension extends \Twig_Extension {

  /**
   * {@inheritdoc}
   * This function must return the name of the extension. It must be unique.
   */
  public function getName() {
    return 'block_display';
  }

  /**
   * In this function we can declare the extension function
   */
  public function getFunctions() {
    return array(
      new \Twig_SimpleFunction('render_string', array($this, 'render_string'), array('is_safe' => array('html'))),
    );
  }

  /**
   * Function to decode html special chars
   */
  public function render_string($string) {
    $render_string = Markup::create($string);
    return $render_string;
  }

```

-\> \**Insert twig function inside your twig file: \**

```
{% set str = render_string('<a href="/this-is-new.html">This is new page</a>') %}
....
....
{{ str }}

```

Hope, this will help you.

# Answer
> 0 votes
Here is a special case for title field:

```
{# Template field--node--title--my-node-bundle.html.twig #}

{%
  set classes = [
  'field',
  'field--name-' ~ field_name|clean_class,
  'field--type-' ~ field_type|clean_class,
  'field--label-' ~ label_display,
]
%}
<span{{ attributes.addClass(classes) }}>
  {%- for item in items -%}
    {# transform title from "inline_template" render element into "markup", to avoid escaping #}
    {% set content = item.content|merge({'#type': 'markup', '#markup': item.content['#context']['value']}) %}
    {{ content }}
  {%- endfor -%}
</span>

```

# Answer
> 0 votes
You can render links with `item_list`. Here's an example how to from the book module:

```
  public function bookRender() {
    $book_list = [];
    foreach ($this->bookManager->getAllBooks() as $book) {
      $book_list[] = Link::fromTextAndUrl($book['title'], $book['url']);
    }
    return [
      '#theme' => 'item_list',
      '#items' => $book_list,
      '#cache' => [
        'tags' => $this->entityTypeManager()->getDefinition('node')->getListCacheTags(),
      ],
    ];
  }

```

The key is to not pass it as markup, but as a renderable array/object.

---
Tags: 8, theming
---


# Question
Title: AliasManagerInterface -deprecated Drupal\Core\Path\AliasManagerInterface
Error:

> The website encountered an unexpected error. Please try again later. TypeError: Argument passed to Drupal{module name}\Theme{class name}::\__construct() must implement interface Drupal\path\_alias\AliasManagerInterface, instance of Drupal\Core\Path\AliasManager

Getting error in the construct method, please suggest a solution to rectify the error.

Try to modify the "AliasManagerInterface" as "use Drupal\Core\Path\AliasManagerInterface" deprecated and we are now using "use Drupal\path\_alias\AliasManagerInterface" but actually getting error inside construct method as mentioned below.

code:

```
 use Drupal\path_alias\AliasManagerInterface;

  /**
   * Protected pathAlias variable.
   *
   * @var Drupal\path_alias\AliasManagerInterface
   */
  protected $pathAlias;

  public function __construct(AliasManagerInterface $pathAlias) {

    $this->pathAlias = $pathAlias;

  }

```

# Answer
You must be on Drupal 8.8, or Drupal 8.9.

Drupal8, until 8.7, declared the `path.alias_manager` service, that referred to `Drupal\Core\Path\AliasManager`. In Drupal 8.8, that service was deprecated, to be removed in Drupal 9.x. A new service was introduced as a replacement, the `path_alias.manager` service, which refers to `Drupal\path_alias\AliasManager`.

The dependency injection from the original question is expecting an object of implementing the interface `Drupal\path_alias\AliasManagerInterface`, and the `path_alias.manager` service does implement this interface. However, the error says that the dependency injection is not receiving an object that implements `Drupal\path_alias\AliasManagerInterface`, it is incorrectly receiving an object of type `Drupal\Core\Path\AliasManager`, giving you the error.

The original question does not show how the dependency is being generated, but in Drupal the two most common methods are creating a service and declaring dependencies in the `*.services.yml` file for the module, or in the `create()` method of the class. Whichever method was used, is still using the old `path.alias_manager` service, and therefore passing `Drupal\Core\Path\AliasManager` to the class instead of `Drupal\path_alias\AliasManager`. The solution is to change service being injected from `path.alias_manager` to `path_alias.manager`.

Further reading: https://www.drupal.org/node/3092086
> 4 votes

---
Tags: 8, path-aliases, dependency-injection
---


# Question
Title: How to programmatically set a checkbox value of an user account which field is not in /people/accounts/fields
I need to set a checkbox which has an unknown field (machine) name in the user account. the checkboxes are in the user account /user/?/edit

but they doesn't appear as fields in people/accounts/fields and are provided by the
DANSE Content Moderation Module.

I need to update them through a twig template with a custom form controller which works fine, but i cannot find the right way to update the field. I've tried:

```
$checkarticle = $values->get('checkmailarticle'); //--> field from custom form
$user_load = User::load($userID_current);
$user_load->danse_subscriptions_settings_content_node_article_0_update->value = $checkarticle;

```

but where to find the correct

```
$user_load->"this field name?"->value

```

Or is there another way to update the settings?

# Answer
> 1 votes
because the module stores the settings information in the userObject and not in fields you can use

```
$userData = \Drupal::service('user.data');
$userData->set('danse', $userID_current, 'content-node-"your content type machine name"-0-publish', 1);

```

for set the checkbox on, or

```
$userData->set('danse', $userID_current, 'content-node-"your content type machine name"-0-publish', 0);

```

for set it off

to find the right keys (third argument in the set function) you can log them in the service.php of the danse module

---
Tags: forms, users, 9
---


# Question
Title: How do I create menu links programmatically?
I need to add some links to existing menu (or to new) programmatically in Drupal 8.

# Answer
> 28 votes
In order to create a menu item automatically this can be placed in a `hook_update_N()` implementation in the .install file; it will run when the database is updated.

```
/**
 * Put the following line on the top of the file containing the
 * following code.
/*
use Drupal\menu_link_content\Entity\MenuLinkContent;

$items = [
  '1' => 'Menuitem 1',
  '2' => 'Menuitem 2',
  '3' => 'Menuitem 3'
];

foreach($items as $nid => $title) {
  $menu_link = MenuLinkContent::create([
    'title' => $title,
    'link' => ['uri' => 'internal:/node/' . $nid],
    'menu_name' => 'main',
    'expanded' => TRUE,
  ]);
  $menu_link->save();
}

```

You can also programmatically create an entire menu.

```
$menu = \Drupal::entityTypeManager()
  ->getStorage('menu')
  ->create([
    'id' => 'menu_test',
    'label' => 'Test menu',
    'description' => 'Description text',
  ]);
$menu->save();

```

# Answer
> 12 votes
If you would like to create module-defined menu links, add something like this example to your *custom\_module.links.menu.yml* file:

```
custom_module.admin_item_1:
  title: 'New Admin Item 1'
  parent: system.admin
  description: 'Description of link goes here.'
  route_name: view.some_view_id.page_1

```

`parent` (optional) is the `id` column of the parent in the `menu_tree` table, and `route_name` is Drupal's internal route ID for where you'd like the menu item to link to. It's in the `menu_tree` table as `route_name`.

See Providing module-defined menu links and Add a menu link for more details and options.

# Answer
> 5 votes
To expand on @skorzh answer and reply to the comment from @Matt, if you want to nest a menu item inside another you have to get the parent id and set it as 'parent'. As an example this code nests the item inside the top level using the variable `$top_level` below.

```
$menu_link_storage = \Drupal::entityTypeManager()->getStorage('menu_link_content');

$my_menu = $menu_link_storage->loadByProperties(['menu_name' => 'my-menu-name']);

foreach ($my_menu as $menu_item) {
  $parent_id = $menu_item->getParentId();
  if (!empty($parent_id)) {
    $top_level = $parent_id;
    break;
  }
}

$menu_link_storage->create([
  'title' => 'My menu link title',
  'link' => ['uri' => 'internal:/my/path'],
  'menu_name' => 'my-menu-name',
  'parent' => $top_level,
  'expanded' => TRUE,
  'weight' => 0,
])->save();

```

# Answer
> 0 votes
For anyone who want to create a menu link associated with a node, you should put the format below for the link URI

> entity:node/{node-id}

instead of

> internal:/node/{node-id}

For example:

```
MenuLinkContent::create([
  'title' => 'Menu Title',
  'link' => [
    'uri' => "entity:node/{$node_id}",
  ],
  'menu_name' => $menu_name,
  'parent' => "$menu_name:",
])->save();

```

---
Tags: 8, navigation
---


# Question
Title: Hiding machine name from a form temporarily only during validation
I’m looking for a solution to hide machine\_name from a form temporarily (only during validation) and restore it afterward.

When the form has **validation with errors** the machine name appears (with a different label like: "Internal name"). I need to hide the machine name while validation has errors. And also force the user to change the name of the source to avoid errors.

My solution (that still not working) is:

1. In form\_alter() add a new validation function callback in form alter before calling to the validation add `$form["name"]["access"] = FALSE; //to hide the machine name from the form.`
2. In the validation function check if the element name is unique.

```
if false (meaning error)
  $form_state->setError()
else
  $form["name"]["access"] = TRUE;
  $form_state->setRebuild(TRUE);

```

This works to the point that the machine name is hidden and when there is an error it shows my error message.

The problem is that if the name of the element is unique (meaning there are no validation errors) - It doesn't save the form.

What am I missing here?

\[I'm using drupal 9 on The Apigee Developer Portal Kickstart distribution\]

# Answer
By denying access you are removing the form element and there will be no value submitted.

For hiding you can try CSS

```
$form['name']['#attributes']['class'][] = 'visually-hidden';

```

or transform the form elment to #type = hidden.
> 1 votes

---
Tags: forms
---


# Question
Title: How do I create a condition to test if the value of a field is unchanged?
In Drupal 7 Rules I could create a condition "Data Value is Empty" and could drill down in the data selector to node-unchanged.field\_to\_test.

However in Drupal 9 Rules when I create a condition "Data Value is Empty" and drill down in the data selector "node\_unchanged." does not display the node's fields to select.

I have created a condition "entity is of bundle" successfully and the node's fields display in a "Data Comparison" condition but not in a "Data Value is Empty" condition.

So my basic question is how to create a Rules condition to display and test that a field's value has not changed?

# Answer
In Rules

Select Condition: Entity is of bundle

entity: node\_unchanged

type:node\_unchanged

bundle: "machine name of content type"
> 0 votes

---
Tags: rules, 9
---


# Question
Title: Print total value in footer but unable to modify footer value using hook_views_pre_render()
Using below code to modify footer value in hook\_views\_pre\_render() but it's not working

```
function hook_views_pre_render(ViewExecutable $view) {
  foreach($view->result as $result) {
    $totalamt = $result->_entity->amount->value + $totalamt;
  }
  $options = array(
      'id' => 'area_1',
      'table' => 'views',
      'field' => 'area_text_custom',
      'relationship' => 'none',
      'group_type' => 'none',
      'admin_label' => '',
      'empty' => TRUE,
      'tokenize' => FALSE,
      'content' => 'Total is:'. $totalamt,
      'plugin_id' => 'text_custom',
    );
    $view->setHandler('page_1', 'footer', 'area_1', $options);
}

```

# Answer
> 1 votes
If that is a copy of your code, you need to replace the `hook` word in the function name `hook_views_pre_render` with your module name.

EG. Your module is called `mymodule`

`hook_views_pre_render(ViewExecutable $view)` =\> `mymodule_views_pre_render(ViewExecutable $view)`

https://api.drupal.org/api/drupal/core%21core.api.php/group/hooks

---
Tags: views, 9
---


title: How do I use CKEditor 5?

text:
# Question
Title: How do I use CKEditor 5?
It has been told that Drupal 9 comes with CKEditor 5.

How do I use it?

# Answer
Drupal core will provide an upgrade path of switching from CKEditor 4 to 5 without data loss. You should be able to switch the editor from 4 to 5 in your text format with an action as simple as changing the editor and saving the text format.

Check for the updates provided in DrupalCon Portland in this video - https://www.youtube.com/watch?v=YwDFCLaQVbY
> 1 votes

---
Tags: 9
---


# Question
Title: How do I get my custom module controller logic to trigger on only certain url paths?
Hi all I am very new to Drupal and am trying to write a custom module. So my site has a bunch of different urls for example *example.com/users/3* or *example.com/articles/47*. I want my custom module code to run whenever the user is on a path that has *exmaple.com/users/..* in it.

The custom code is in the module controller and has some api calls in it using Drupals global user entity. Right now I got it working where in the routing.yml file it takes the path I give it and just creates a new page where the custom code is working `path: '/custom/page'`

How do I get my custom code to trigger on certain url paths?

# Answer
> 1 votes
I would:

1. create a custom module
2. Add a `hook_page_preprocess()` function.
3. Check the URL with `$current_path = \Drupal::service('path.current')->getPath();` (See this answer for more info)
4. Do your logic in the path match  `example.com/users/`

You could also checkout Event Subscribers below, but I'm unfamiliar with them.

For more info, see https://www.drupal.org/docs/creating-modules/subscribe-to-and-dispatch-events

---
Tags: page-controller
---


title: Create vocabularies with the JSON API

text:
# Question
Title: Create vocabularies with the JSON API
I found this identical question but it seems to be dead and none of the answers help me. I also don't have enough reputation to ask in a comment, so, since I'm at the end of my rope with this issue, I'm posting my own question.

I'll preface the issue with what I've done as I have put effort into solving this on my own:

I have the additional operations enabled:

I'm using the path `/jsonapi/taxonomy_vocabulary/taxonomy_vocabulary`.

I'm sending the following request body:

```
{
  "data": [
    {
      "type": "taxonomy_vocabulary--taxonomy_vocabulary",
      "id": "d0a3157e-58ad-7a43-93ff-a9b76f2273b6",
      "attributes": {
        "name": "Listing Categories",
        "drupal_internal__vid": "listing_categories"
      }
    }
  ]
}

```

And I get the following response:

```
{
  "jsonapi": {...},
  "errors": [
    {
      "title": "Method Not Allowed",
      "status": "405",
      "detail": "No route found for \"POST /jsonapi/taxonomy_vocabulary/taxonomy_vocabulary\": Method Not Allowed (Allow: GET, HEAD)",
      "links": {...},
      "source": {...},
      "meta": {...}
    }
  ]
}

```

I'm having no issues creating nodes, terms, or even paragraphs with POST requests, so I'm at a complete loss as to why POST requests to create vocabularies are being denied. I've tried searching various terms to see if this is a known bug with vocabularies, but I haven't been able to find anything, which leads me to suspect that I'm missing something on my end. Thanks in advance

Lastly, I apologize for the tags. I'm not used to asking on stack exchange, so I might be missing something obvious, but I can't seem to actually add relevant tags such as `jsonapi`, `json`, `rest`, `taxonomy`, or `vocabulary`. The only thing close I can add is `taxonomy-terms`.

# Answer
> 1 votes
Vocabularies are config entities, and config entities don't currently allow post operations.

See this issue:

https://www.drupal.org/node/2300677

---
Tags: taxonomy-terms
---


# Question
Title: Remove "Payment method" tab in user profile
Commerce don't give me any customize options for the user profile of the user, I don't want the "Payment method" tab to appear in the user profile, how can I cleanly remove/disable this?

Can someone confirm me if it's work with tab tamer? I read this issue: How to add / remove tabs from user profile? But i can't use it because i have bootstrap barrio as theme and the module have a problem with barrio ...

# Answer
> 0 votes
What about simply not granting the "Manage own payment methods" permission? That is a simple solution that doesn't require coding?

# Answer
> 0 votes
this is not a solution, if i change this permission the tab is is from the user profile removed, this is correct, BUT the problem of this permission change is that all users can't select anymore a payment method if they want to buy a product... it is not only for the user page... i solved it with a custom module, but it's sad that Commerce isn't mature enough to solve something like this without extra code either, I've been dealing with Drupal Commerce 2 since D8,D9 for 3 years now and I have to regret this decision... I have the feeling it will never really finished and it's nothing for simple users... the time I've invested... never again a shop with Drupal

# Answer
> 0 votes
So having to write a few lines of code means Commerce isn't mature enough? So what is your suggestion? We create an admin page to disable all routes defined by Commerce?

> I've been dealing with Drupal Commerce 2 since D8,D9 for 3 years now and I have to regret this decision... I have the feeling it will never really finished and it's nothing for simple users... the time I've invested... never again a shop with Drupal

So all of this frustration just for a simple problem like this? As far as I know, no-one forced you to use Drupal Commerce... I'm here trying to help you and I'm getting a rant back... And then people complain when they don't get a timely answer...

# Answer
> 0 votes
I solved it simply in CSS. Drupal is often overcomplicated. Maybe not the "Drupal way" but outcome is the same:

```
.path-user .tabs--primary a[href*="payment-methods"] {
    display: none;
}

```

---
Tags: commerce
---


# Question
Title: How can I delete properly an old translation string?
I found an old string into `locales_source` table, like that:

The associated `8.5.3` version seems outdated. I would like to understand the usefulness of the keep this data in my database ? How to clean it properly ?

# Answer
> 0 votes
In Drupal 7, you could delete unnecessary strings in the UI.

Drupal 8 and 9 are missing this functionality; there is an open bug report to add it back, and hopefully it will eventually be fixed in Drupal 10.

There is a working patch in the issue to get a mostly working version of the function now.

---
Tags: database, 9
---


# Question
Title: How edit or alter the links in the secondary toolbar?
I'm on D9.3.x with Gin theme and Gin Toolbar.

I need to edit the link available in the *secondary toolbar*.

Namely, I'd need to hide the *shortcuts* link for everyone and hide the *edit profile* sub-link for some roles.

Is that possible to do somehow via configuration? I could find nothing, so I've also tried to use `hook_toolbar_alter`. However, I can't understand how the "user" link part is build, so I can't actually hide the *edit* link - I'll attach below the export of `$items['user']` variable.

Any suggestions on how solve this? Thanks

```
 [
    '#type' => 'toolbar_item',
    'tab' =>
      [
        '#type' => 'link',
        '#title' =>
          [
            '#lazy_builder' =>
              [
                0 => 'user.toolbar_link_builder:renderDisplayName',
                1 =>
                  [
                  ],
              ],
            '#create_placeholder' => TRUE,
          ],
        '#url' =>
          Drupal\Core\Url::__set_state([
            'urlGenerator' => NULL,
            'urlAssembler' => NULL,
            'accessManager' => NULL,
            'routeName' => 'user.page',
            'routeParameters' =>
              [
              ],
            'options' =>
              [
              ],
            'external' => FALSE,
            'unrouted' => FALSE,
            'uri' => NULL,
            'internalPath' => NULL,
            '_serviceIds' =>
              [
              ],
            '_entityStorages' =>
              [
              ],
          ]),
        '#attributes' =>
          [
            'title' =>
              Drupal\Core\StringTranslation\TranslatableMarkup::__set_state([
                'string' => 'My account',
                'arguments' =>
                  [
                  ],
                'translatedMarkup' => NULL,
                'options' =>
                  [
                  ],
                'stringTranslation' => NULL,
              ]),
            'class' =>
              [
                0 => 'toolbar-icon',
                1 => 'toolbar-icon-user',
              ],
          ],
        '#cache' =>
          [
            'contexts' =>
              [
                0 => 'user.roles:anonymous',
              ],
          ],
      ],
    'tray' =>
      [
        '#heading' =>
          Drupal\Core\StringTranslation\TranslatableMarkup::__set_state([
            'string' => 'User account actions',
            'arguments' =>
              [
              ],
            'translatedMarkup' => NULL,
            'options' =>
              [
              ],
            'stringTranslation' => NULL,
          ]),
        'user_links' =>
          [
            '#lazy_builder' =>
              [
                0 => 'user.toolbar_link_builder:renderToolbarLinks',
                1 =>
                  [
                  ],
              ],
            '#create_placeholder' => TRUE,
          ],
      ],
    '#weight' => 1000,
    '#attached' =>
      [
        'library' =>
          [
            0 => 'user/drupal.user.icons',
          ],
      ],
  ]

```

# Answer
The easy way:

```
/**
 * Implements hook_toolbar_alter().
 */
function MYMODULE_toolbar_alter(&$items) {
  // Remove the 'Shortcuts' toolbar item.
  unset($items['shortcuts']);
}

/**
 * Implements hook_preprocess_HOOK().
 */
function MYMODULE_preprocess_links__toolbar_user(&$variables) {
  // Remove the 'Edit profile' menu item.
  unset($variables['links']['account_edit']);
}

```

One could also override the *user.toolbar\_link\_builder* service for even more control.
> 0 votes

---
Tags: navigation, 9
---


# Question
Title: CKEditor 4 style to add a class to a paragraph instead of replacing existing classes
Certain rich text contains the following HTML:

```
<p class="indent">paragraph text</p>

```

in **Text formats and editors** for CKEditor, I have added the following line to the styles dropdown:

```
p.narrow|Narrow Paragraph

```

While editing the rich text, if I select the paragraph and click "Narrow Paragraph" in the styles dropdown, the HTML becomes:

```
<p class="narrow">paragraph text</p>

```

Is there a way to set up a class definition in the styles dropdown so that the class is *added* to any existing classes if it doesn't exist or *removed* if it does exist? In other words, in the example above, I would like the outcome to be

```
<p class="indent narrow">paragraph text</p>

```

Another click on "Narrow Paragraph" with the same paragraph selected would switch it back to

```
<p class="indent">paragraph text</p>

```

Can this be done?

# Answer
> 3 votes
No. The styles combo dropdown doesn't allow for multi-select (which your desired result would require).

If you want to stick with the styles combo dropdown, the only way to accomplish what you want is to simply add another style with both classes:

```
p.indent|Indented paragraph
p.narrow|Narrow paragraph
p.indent.narrow|Narrow indented paragraph

```

For further extended use cases, you can't use the styles combo plugin, but have to create/use a custom CKEditor plugin/module providing multiple buttons for the toolbar (one per CSS class, similar to the "bold", "italic", ... buttons of the fonts plugin), or a modal dialog with a custom multi select element/checkboxes for each CSS class.

I didn't test the custom plugin mentioned in the following CKEditor stackexchange question, but it attempts to provide the desired functionality by replacing the styles combo dropdown:

https://stackoverflow.com/questions/43680918/stylescombo-plugins-with-multiple-class-selection

If you want to test it with your installation, you need to create a Drupal module that will register the plugin to the Drupal CKEditor. Explaining how to do this surely exceeds the scope of this question. But an example How-To can be found on this external site.

# Answer
> 1 votes
I was asking myself the same question. It seems that someone did a plugin for that, see https://stackoverflow.com/questions/43680918/stylescombo-plugins-with-multiple-class-selection.

His plugin can be downloaded at https://webutler.de/download/ckeditor\_plugins/ (the link in his stackoverflow post is broken)

I didn't have the time to test it though. Please share your outcome in case you test it.

---
Tags: 9, wysiwyg
---


title: How do I import/export menus?

text:
# Question
Title: How do I import/export menus?
I want to import/export all menus of site1 in into site2. Currently I am using the **entitysync** module to synchronize the content between two sites. I can see there is an option for "Custom Menu Links" but it will import/export only the main navigation items only.

I want to import/export:

**Structure -\> Menus**

1. Administration
2. Footer
3. Main Navigation
4. Tools
5. User Account Menu

Can anybody help me on this?

# Answer
> 0 votes
Try the Structure Sync module:

> Some websites might contain elements that are considered content by the Drupal CMS while they might not only be used as content. For example custom blocks might be used for a footer that is shared between all environments. Structure sync tries to give you a tool to get around this issue by allowing you to **synchronize taxonomy terms, menu links and custom blocks** through the configuration.

---
Tags: navigation, 9, importing-exporting, multi-sites
---


# Question
Title: What is the correct way to get the link url?
We have a `Basic Page` content type with a link field (`field_link`). When we call the `mymodule_preprocess_node(&$variables)` hook in a custom module we use `ksm($node->get('field_link')->first())` and it returns a `Drupal\link\Plugin\Field\FieldType\LinkItem`. We need to extract the URL from this fields and have found two ways to do it (see below). What is the correct way to get the URL from the field?

The reason for extracting the URL is that we need to wrap a set of custom fields with the link so we can have a HTML structure similar to below.

HTML structure:

```
<a href="/some/path" target="_blank">
  <img src="some/image/path">
  <span> Some title field </span>
</a>

```

**mymodule.module**

```
...
function mymodule_preprocess_node(&$variables) {
  $node = $variables['node'];
  $node_field_link = $node->get('field_link')->first();

  // Do we use this?
  $node_field_link_url = $node_field_link->getUrl()->getUri();

  // Or do we use?
  $node_field_link_url = $node_field_link->get('uri')->getValue();
}
...

```

# Answer
Get the Url object from the link field with LinkItemInterface::getUrl and build a new link, for example:

```
$variables['link_with_image'] => [
  '#type' => 'link',
  '#title' => [
    '#theme' => 'image',
    '#uri' => $image_uri,
    '#width' => 60,
    '#height' => 40,
    '#alt' => $image_alt,
  ],
  '#url' => $node->field_link->first()->getUrl();
  '#attributes' => ['target' => '_blank'],
];

```

Normally you don't do this in preprocess and build such render arrays in a field formatter, see for example Image Link Attributes and Linked Field.
> 2 votes

# Answer
I find the best way to get a url especially when I'm using it in cases where I need to wrap custom html around it is to get the url object and then use the toString Method.

```
$node_field_link_url = $node_field_link->getUrl()->toString();

```

The getUrl() method of the LinkItem object returns a Url object. See https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Url.php/class/Url/8.2.x And Url objects have a toString method that returns the string representation of that url.
> 1 votes

# Answer
I always get stuck when I have to deal with Link fields, so let me answer this question for anyone who can help and for myself in the future:

The URL field is a `\Drupal\Core\Field\FieldItemList` object.

PHP:

If you only have one value:

```
$mylink_url = $node->field_link->first()->getUrl()->toString();
// or
$mylink_url = $node->field_link[0]->getUrl()->toString();

$mylink_title = $node->field_link->first()->title;
// or
$mylink_title = $node->field_link[0]->title;

// On ...->first() you get a \Drupal\link\Plugin\Field\FieldType\LinkItem
// On ...->getUrl() you get a \Drupal\Core\Url object.

```

Twig:

You can't use the `first` method, it will throw a `Twig\Sandbox\SecurityError` error.

```
My URL link: {{ node.field_link[0].url.toString() }}
My URL title: {{ node.field_link[0].title }}

```

If your field has more than one value, just use a `for` or `foreach`.
> 0 votes

---
Tags: 8, nodes, hooks
---


# Question
Title: How to use Easy breadcrumb module so that breadcrumb reflects the URL path segments?
For example, if URL ends with /test/flower , breadcrumb should be Home/test/flower.

First time working with this module,and it's not clear to me how to do this. Could you please help me?

Thanks in advance

# Answer
> 2 votes
Easy Breadcrumb works on the principle that every segment in your path is actually a reachable page (more on this later) and it builds the page's breadcrumb based on that path sequence. This works best when used with Pathauto to define aliases.

For example, let's take an example URL of `https://example.com/blogs/space/how-to-reach-mars`. The expectation is that the breadcrumb would be `Home / Blogs / Space / How To Reach Mars`. To make this work:

* `https://example.com/` must be a working page (it should, it's your home page)
* `https://example.com/blogs` could be a Views page listing all Article nodes.
* `https://example.com/blogs/space` could be a Views page with a contextual filter, filtering all Article nodes by a topic field containing "space".
* `https://example.com/blogs/space/how-to-reach-mars` an Article node whose alias is constructed with pattern `/blogs/[node:field_topic]/[node:title]`

Now Easy Breadcrumb does allow you to set unreachable pages on the in-between segments (e.g. the pages might be permissioned away or just non-existent), there is a configuration for this. In the example above, you can totally leave out the Views pages (`/blogs` and `/blogs/[topic]`) and still have the Node's path be `/blogs/space/how-to-reach-mars`. The breadcrumb on the page is still `Home / Blogs / Space / How To Reach Mars` but "Blog" and "Space" are unclickable.

---
Tags: breadcrumbs
---


# Question
Title: How do I insert migrated file info into a file field?
Successfully migrated public and private files to D9 system using core d7\_file and d7\_file\_private migrations.

Now trying to migrate the file info into file fields (entity\_reference\_revisions:paragraph migration). My source plugin is generating the source fields, but nothing is being migrated to the file fields and there are no messages. All other fields are migrating successfully.

These are the two file fields in the paragraph entity into which I am trying to insert file info:

* field\_private\_files (file field)
* field\_public\_files (file field)

My source plugin (d7\_agenda\_section):

* does a migrate\_lookup and gets the migrated file fids for this paragraph
* does a lookup in the source database and gets the source file description for each fid
* creates (using prepareRow()) both a **private** and **public** field each of which contains the file **target\_id** and **description** in the following array format:

> ```
> (
>     [0] => Array
>         (
>             [target_id] => 325
>             [description] => 3.C. Employment Chart (v4)
>         )
>
>     [1] => Array
>         (
>             [target_id] => 339
>             [description] => 5.A. Nurse School Board Report
>         )
>
>     [2] => Array
>         (
>             [target_id] => 340
>             [description] => 5.B. Board Calendar
>         )
>
> )
>
> ```

This is my migration code:

```
source:
  plugin: d7_agenda_section
  key: migrate
  langcode: en
process:
  'field_content/value': body_value
  'field_content/format': body_format
  field_private_files:
    -  plugin: skip_on_empty
       method: process
       source: private
    -  plugin: sub_process
       process:
         target_id: target_id
         display:
           plugin: default_value
           default_value: 1
         description: description
  field_public_files:
    -  plugin: skip_on_empty
       method: process
       source: public
    -  plugin: sub_process
       process:
         target_id: target_id
         display:
           plugin: default_value
           default_value: 1
         description: description
destination:
  plugin: entity_reference_revisions:paragraph
  default_bundle: agenda_section
    migration_dependencies:
    required:
    -  sbn_migrations_d7_file
    -  sbn_migrations_d7_file_private

```

I run the migration and the **field\_content** is migrated, but nothing in **field\_public\_files** or **field\_private\_files**.

I am thinking my problem is with the **skip\_on\_empty** usage as I have used similar array field processing code successfully to migrate nested paragraphs:

```
  field_body1:
    source: prepare_multiple_paragraphs
    plugin: sub_process
    process:
      target_id: target_id
      target_revision_id: target_revision_id

```

See sample code: https://atendesigngroup.com/articles/drupal-8-migration-multiple-paragra...

Some paragraphs will have public and private files, some will have none, others will have one or the other. I have read that there are problems with the **sub\_process** plugin if the array is empty. So my goal here is to skip the field if it contains an empty array.

Looking for suggestions on how to resolve this.

# Answer
First, I made a code mistake. My source plugin generated fields are **public\_files** and **private\_files** (not **public** and **private**).

Next, I just took out the **skip\_on\_empty** completely. I am not quite sure yet what happens when a paragraph has no files, but for right now, migrated file data is being imported into the file field correctly:

```
process:
  'field_content/value': body_value
  'field_content/format': body_format
  field_private_files:
    source: private_files
    plugin: sub_process
    process:
      target_id: target_id
      display: display
      description: description
  field_public_files:
    source: public_files
    plugin: sub_process
    process:
      target_id: target_id
      display: display
      description: description

```
> 0 votes

---
Tags: files, migrations
---


# Question
Title: How do I display user signatures in comments?
Drupal 7 has a "personalization" section on ...admin/config/people/accounts

If this exists in Drupal 9, I'd love to know where it is. The goal: enable signatures for user accounts.

If it's truly gone in D9, the question then becomes what's the best workaround?

* A custom field in user account: then how to display that in the comment?
* Is there a module I haven't found that does this? I see a signatures module but it appears underdeveloped and lacks the security OK.

# Answer
Custom field + twig solution: It is also possible to use a combination of custom field in 'user' and then print in comments.html.twig

\[edit to add version that does not use '|raw'\]

```
{{- content|without('links') -}}  {# suppress links #}
    {# add sig #}
    <div class="usersig">
     {% set usersig = comment.getOwner.YOUR_FIELDNAME.value %}
            {%  if usersig|length == 0 %}
              {% set usersig = ' ' %}
            {%  endif %}
              {% set sigbody = {
                  '#type':   'processed_text',
                  '#text':    usersig,
                  '#format':  comment.getOwner.YOUR_FIELDNAME.format,
                } %}
              {{sigbody}}
    </div>
    {# add previously suppressed links #}
   {{content.links}}

```

\[end edit\]

Original method (probably not a good idea)...

```
{{ comment.getOwner.INSERT_CUSTOM_FIELDNAME.value|raw }}

```

The "|raw" is for formatted text field (renders the html as html). If your field is plain text omit that.

**The advantage of this approach** is that it is lighter and does not depend on a module that is not ready for production use. Disadvantage: the module appears to offer some more features.

**On the safety of the |raw switch** \- One method is to use the Twig Tweak module's check\_markup feature. That and other options discussed here: How to print text (formatted, long) in twig without raw filter?
> -1 votes

# Answer
`git log -Spersonalization` led me to https://www.drupal.org/node/1548204, which leads to https://www.drupal.org/project/signature and https://www.drupal.org/node/2457545. So, this feature was moved to contrib before Drupal 8 launched in 2015 and this functionality is now in the Signature module.
> 3 votes

---
Tags: users, 9, comments
---


title: Sort Views table field by alphabet

text:
# Question
Title: Sort Views table field by alphabet
Table field 'Manufacturer' is set to sort by ascending or descending and when you sort it. At first it looks like it's sorting by alphabet, it starts with A, B, C etc. but eventually ends up with A again at the bottom?

The Manufacturer field is a taxonomy term. I can recreate that on a new view just with this field and it still won't sort. Title field sorts fine.

**update** Looks like you can't sort a taxonomy term alphabetically in a Table View, to reproduce that just create a random view for a content type that has a random taxonomy field that is limited to 1, so you can enable Sort in the Table settings. And if you try to sort, it makes no sense, not alphabetical at all.

# Answer
> 1 votes
Taxonomy term fields are entity reference fields. They only store the reference to the entity, which usually a number that is the ID for that entity. In case of Taxonomy the reference fields store the TID (taxonomy term ID) which is the number you can see in the path when you edit the term in the admin area.

When you sort your table using the reference field, it will follow the number sort of the term IDs.

But you want to sort alphabetically using **term names**.

Term names aren't stored in node tables in the database, taxonomy module has its own tables. You have to pull the term data into your node views in order to use it as a sorting criteria.

To pull related data into views use Relationships.

In your case you have to add the Relationship for the Manufacturer taxonomy term field. After you add that Relationship you will be able to add a new field to your views called `Taxonomy term: Name`. You will be able to sort your table using that field, and the results will be sorted alphabetically!

Remove your original Manufacturer field if you don't need it for anything else, the Term name field should be able to work as a full replacement while also providing the alphabetic sort criteria.

# Answer
> 0 votes
For what it's worth, I had the same problem with a View in a Drupal 9 installation.

All I had to do was add the relation to the term field under Advanced (Taxonomy term referenced from field\_my\_taxonomy\_field) and save the view.

Et viloa! Now the sort was OK on the existing term field picked from the content type - which sorted totally crazy before.

Martin

---
Tags: 7, views
---


title: How can I merge or combine facets?

text:
# Question
Title: How can I merge or combine facets?
I have a search page with a faceted filter on 'Content Type' field.

I basically need to merge some of the content types into one single facet.

Example:

* Content Type A
* Content Type B
* Content Type C

Should be turned into:

* Content Type AB
* Content Type C

How can I achieve this?

My Drupal setup for this scenario is the following:

Search API + Search API Solr + Facetapi + Views

# Answer
> 1 votes
I wrote this articule: "Drupal 8 - Combine two facets" https://www.keboca.com/drupal-8-combine-two-facets

Where I am exposing a new processor plugin then I am able to merge both.

```
namespace Drupal\keboca_search\Plugin\facets\processor;

use Drupal\facets\Annotation\FacetsProcessor;
use Drupal\facets\FacetInterface;
use Drupal\facets\Processor\BuildProcessorInterface;
use Drupal\facets\Processor\ProcessorPluginBase;

/**
 * Class MergeArticlePage which's merging two hard-coded content types.
 *
 * @package Drupal\keboca_search\Plugin\facets\processor
 *
 * @FacetsProcessor(
 *   id = "keboca_search_merge_article_page",
 *   label = @Translation("Merge Articles and Pages together."),
 *   description = @Translation("An integration to force put together Articles
 *   and Pages into a single facet."),
 *   stages = {
 *     "build" = 60
 *   }
 * )
 */
class MergeArticlePage extends ProcessorPluginBase implements BuildProcessorInterface {

  /**
   * {@inheritdoc}
   */
  public function build(FacetInterface $facet, array $results) {
    /** @var \Drupal\facets\Result\Result[] $facets */
    $facets = array_reduce($results, function ($carry, $item) {
      /** @var \Drupal\facets\Result\Result $item */
      $carry[$item->getRawValue()] = $item;
      return $carry;
    }, []);

    /** @var \Drupal\facets\Result\Result $article */
    $article = $facets['article'] ?? NULL;
    /** @var \Drupal\facets\Result\Result $page */
    $page = $facets['page'] ?? NULL;

    // Parse `page` facet instance.
    if (!is_null($page)) {
      /** @var \Drupal\Core\Url $url */
      $url = $page->getUrl();
      /** @var array $query */
      $query = $url->getOption('query');

      // Init flag variables.
      $updated = FALSE;
      $filter = 'content_type:article';

      // Look-up for query string.
      if (!in_array($filter, $query['sitewide'])) {
        // Inject filter to current query.
        $updated = TRUE;
        $query['sitewide'][] = $filter;
      }
      // Verify when current facet is active.
      elseif ($page->isActive()) {
        // Remove duplication filter values.
        $updated = TRUE;
        $query['sitewide'] = array_filter($query['sitewide'], function ($param) use ($filter) {
          return $param != $filter;
        });

        // Remove whole query string when there are not filters.
        if (empty($query['sitewide'])) {
          unset($query['sitewide']);
        }
      }

      // Overwrite URL options then define it back to facet.
      if ($updated) {
        $url->setOption('query', $query);
        $page->setUrl($url);
      }

      // Update facet count value when article facet was found.
      if (!is_null($article)) {
        $page->setCount($page->getCount() + $article->getCount());

        // Remove `article` facet instance.
        unset($facets['article']);
      }
    }

    return array_values($facets);
  }
}

```

PD: I'm not pretty sure how this thing about posting solution or stuff works. I got my last previous commnented deleted. So I am just sharing it again. If it works fine, otherwise I am not sure how it supposes to do. From what I can see the first comment is an URL which's pointing to a resource what does not event exits, tho. Any feedback is more than welcome BTW.

# Answer
> 0 votes
I fact all you need is

`hook_facet_items_alter(&$build, &$settings);`

There you can change the queries and hide/show other facets like

> ```
>       $build['A']['#markup'] = 'NewA';
>       $build['A']['#count']  = $build['A']['#count'] + $build['B']['#count'];
>       $size = count($build);
>       $build['A']['#query']['f'][$size] = 'field_filter:B';
>
> ```

# Answer
> 0 votes
I ended up using a field for the nodes, "Content type filter", hidden from display and edition. Content of type A and B will have default value AB, content C has default value C. Then I can use this field in the facet. It is a very basic approach but also very easy.

---
Tags: search
---


# Question
Title: How do I get a DateTime from a timestamp field?
Suppose I have a timestamp base field on an entity type. I can do $entity-\>timefield-\>value and get the UNIX timestamp.

But how do I get a DateTime object from this?

I can see there is a Timestamp::getDateTime() method which does exactly what I want. But that's the DataType class.

The field definition, TimestampItem, defines the 'value' property as a 'timestamp', so that is the Timestamp datatype. But I can't figure out how to get from one to the other.

# Answer
Instantiate a DrupalDateTime object with `new DrupalDateTime::createFromTimestamp`.
> 0 votes

---
Tags: entities
---


# Question
Title: How to bulk change the source language of field labels?
I have a French Drupal site that needs to be translated into English and Dutch. My question is only about the translation of the content types fields (label/description/...) which are configuration objects.

When I look at the source language of those fields, it is mostly set to English which is wrong. Approx 20% are set to French, which is fine.

I don't know how it comes but I am there... I would like to change the source language of all those items into French. Is there a way to handle this quickly (I have so many content types each with +/- 30 fields)

# Answer
Here is the process I used.

1-export all configuration files: `drush config-export` (see settings.php to get the export directory `$config['sync']=..`

2-copy all the `field.storage.node.field_*.yml` and `field.field.node.*.field_*.yml` into a directory named for example `content-fields`

3-replace the wrong english langcode from within the `content-fields` directory using sed: `for i in `find *` ; do sed -i -- 's/langcode: en/langcode: fr/g' $i; done`

4-import back the corrected files by using drush cim with the `partial` attribute: `drush cim --partial --source=<your path>/content-fields`

MAKE SURE TO USE THE PARTIAL ATTRIBUTE TO NOT DELETE MANY CONFIGURATION
> 0 votes

---
Tags: i18n-l10n
---


title: How to show webform as block

text:
# Question
Title: How to show webform as block
In drupal 7 we used to attach a webform to nodes and then we could render them as a block, nowadays in drupal 8 Webform is a dependent entity and is designed and developed on its own. now my question is :

> I've created a webform and now I want to place it in a block so user can simply fill it up in front page, How can I show a webform as a Block?

# Answer
> 15 votes
Special thanks to Peacog Web Development for their great tutorial .Here is the tip:

> Rather than Drupal 7, Different Block types can be created by admin

so the solution is simple :

* Create a new block type using : admin/structure/block/block-content/types
* Add a Reference of type Webform to custom block type
* remove body if it's inappropriate
* modify custom block Manage Display so the form would be rendered as webform
* your new Block type is ready

now to add any new webform as block you, you will need to add new block of type Custom Block and refer to your webform, and that's done.

# Answer
> 11 votes
logeshvaran is correct: Webform for Drupal 8 already provides a block that can reference a webform. So no need to create a custom block type.

# Answer
> 8 votes
From Drupal 8 admin

1. Create your webform
2. Structure =\> Block Layout =\> click "Place Block" under your preferred region
3. Find Webform then =\> Place Block =\> under Webform type your webform title and it will find it
4. Save Block

You are all set

# Answer
> 0 votes
You can embed a webform programmatically:

```
$webform = $this->entityTypeManager->getStorage('webform')->load(self::WEBFORM_ID);
$build['content'][] = [
  '#type' => 'webform',
  '#webform' => $webform,
];

```

---
Tags: 8, blocks, webforms
---


# Question
Title: phpstan error installing Upgrade Status module
I'm on a freshly updates site running PHP 8.1.12. I followed the instructions on the module page. Worked fine till the final step when it failed.

```
  Problem 1
    - mglaman/phpstan-drupal[1.0.0, ..., 1.1.16] require phpstan/phpstan ^1.0 -> found phpstan/phpstan[1.0.0, ..., 1.9.x-dev] but these were not loaded, likely because it conflicts with another require.
    - mglaman/phpstan-drupal[1.1.17, ..., 1.1.20] require phpstan/phpstan ^1.7.0 -> found phpstan/phpstan[1.7.0, ..., 1.9.x-dev] but these were not loaded, likely because it conflicts with another require.
    - mglaman/phpstan-drupal[1.0.x-dev, ..., 1.1.25] require phpstan/phpstan ^1.6.0 -> found phpstan/phpstan[1.6.0, ..., 1.9.x-dev] but these were not loaded, likely because it conflicts with another require.
    - drupal/upgrade_status[3.18.0, ..., 3.x-dev] require mglaman/phpstan-drupal ^1.0.0 -> satisfiable by mglaman/phpstan-drupal[1.0.0, ..., 1.1.25].
    - Root composer.json requires drupal/upgrade_status ^3.18 -> satisfiable by drupal/upgrade_status[3.18.0, 3.x-dev].

```

I used these commands right off the module's page instructions:

```
composer show drupal/core | grep versions
composer require --dev drupal/core-dev:9.4.8 --update-with-all-dependencies
composer require drupal/upgrade_status --update-with-all-dependencies

```

There is nothing in my composer.json about upgrade\_status or phpstan.Here is the complete file:

```
{
    "name": "drupal/recommended-project",
    "description": "Project template for Drupal 8 projects with a relocated document root",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "homepage": "https://www.drupal.org/project/drupal",
    "support": {
        "docs": "https://www.drupal.org/docs/user_guide/en/index.html",
        "chat": "https://www.drupal.org/node/314178"
    },
    "repositories": {
        "drupal": {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        "0": {
            "type": "vcs",
            "url": "https://github.com/mcaskill/composer-merge-plugin"
        },
        "1": {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        "2": {
            "type": "composer",
            "url": "https://asset-packagist.org"
        },
        "3": {
            "type": "composer",
            "url": "https://packagist.org"
        }
    },
    "require": {
        "composer/installers": "^1.2",
        "drupal/admin_toolbar": "^3.2",
        "drupal/adminimal_theme": "^1.6",
        "drupal/anti_duplicates": "^3.1",
        "drupal/antibot": "^1.4",
        "drupal/blazy": "^2.0@RC",
        "drupal/block_class": "^1.1",
        "drupal/block_visibility_groups": "^1.3",
        "drupal/captcha": "^1.6",
        "drupal/composer_deploy": "^1.6",
        "drupal/computed_field": "^3.0@alpha",
        "drupal/config_update": "^1.6",
        "drupal/contact_block": "^1.4.0",
        "drupal/core": "^9",
        "drupal/core-composer-scaffold": "^9",
        "drupal/core-project-message": "^9",
        "drupal/core-recommended": "^9",
        "drupal/core-vendor-hardening": "^9",
        "drupal/ctools": "^3.2.0",
        "drupal/embed": "^1.3",
        "drupal/encrypt": "^3.0",
        "drupal/entity_browser": "^2.2.0",
        "drupal/entity_embed": "^1.0.0",
        "drupal/entity_reference_revisions": "^1.7",
        "drupal/features": "^3.8.0",
        "drupal/field_group": "^3.3",
        "drupal/field_permissions": "^1.2",
        "drupal/fivestar": "1.x-dev@dev",
        "drupal/flag": "^4.0",
        "drupal/honeypot": "^2.0",
        "drupal/image_url_formatter": "^1.0",
        "drupal/imce": "^2.2",
        "drupal/inline_entity_form": "^1.0.0-rc2",
        "drupal/metatag": "^1.11",
        "drupal/paragraphs": "^1.10.0",
        "drupal/pathauto": "^1.6.0",
        "drupal/profile": "^1.0.0",
        "drupal/real_aes": "^2.3",
        "drupal/recaptcha": "^3.0",
        "drupal/redirect": "^1.5",
        "drupal/schema_metatag": "^2.1",
        "drupal/simple_sitemap": "^3.6",
        "drupal/simplenews": "^2.0",
        "drupal/slick": "^2.0",
        "drupal/slick_extras": "^1.0.0-rc2",
        "drupal/slick_views": "^2.3",
        "drupal/social_media_links": "^2.6.0",
        "drupal/token": "^1.5.0",
        "drupal/tvi": "^1.0@RC",
        "drupal/twig_field_value": "^2.0",
        "drupal/views_bulk_edit": "^2.7",
        "drupal/views_bulk_operations": "^3.9",
        "drupal/views_infinite_scroll": "^1.6.0",
        "drupal/votingapi": "^3.0@beta",
        "drupal/webform": "^6.0",
        "drush/drush": "^10.0.0",
        "wikimedia/composer-merge-plugin": "dev-feature/composer-v2 as 1.5.0"
    },
    "require-dev": {
        "drupal/core-dev": "9.4.8",
        "kint-php/kint": "^4.2",
        "palantirnet/drupal-rector": "^0.11.4"
    },
    "conflict": {
        "drupal/drupal": "*"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "sort-packages": true,
        "allow-plugins": {
            "composer/installers": true,
            "drupal/core-composer-scaffold": true,
            "drupal/core-project-message": true,
            "drupal/core-vendor-hardening": true,
            "wikimedia/composer-merge-plugin": true,
            "dealerdirect/phpcodesniffer-composer-installer": true
        }
    },
    "extra": {
        "installer-types": [
            "npm-asset",
            "bower-asset"
        ],
        "drupal-scaffold": {
            "locations": {
                "web-root": "web/"
            }
        },
        "installer-paths": {
            "web/core": [
                "type:drupal-core"
            ],
            "web/libraries/{$name}": [
                "type:npm-asset",
                "type:bower-asset",
                "type:drupal-library",
                "bower-asset/bLazy",
                "bower-asset/jquery.easing",
                "npm-asset/slick-carousel"
            ],
            "web/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "web/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "web/themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "drush/Commands/contrib/{$name}": [
                "type:drupal-drush"
            ],
            "web/modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "web/themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ]
        },
        "drupal-core-project-message": {
            "include-keys": [
                "homepage",
                "support"
            ],
            "post-create-project-cmd-message": [
                "<bg=blue;fg=white>                                                         </>",
                "<bg=blue;fg=white>  Congratulations, youâ€™ve installed the Drupal codebase  </>",
                "<bg=blue;fg=white>  from the drupal/recommended-project template!          </>",
                "<bg=blue;fg=white>                                                         </>",
                "",
                "<bg=yellow;fg=black>Next steps</>:",
                "  * Install the site: https://www.drupal.org/docs/8/install",
                "  * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html",
                "  * Get support: https://www.drupal.org/support",
                "  * Get involved with the Drupal community:",
                "      https://www.drupal.org/getting-involved",
                "  * Remove the plugin that prints this message:",
                "      composer remove drupal/core-project-message"
            ]
        },
        "merge-plugin": {
            "include": [
                "web/modules/contrib/webform/composer.libraries.json"
            ]
        }
    }
}

```

# Answer
The drupal-rector constraint is incompatible with the current version of upgrade\_status. Try the following:

```
composer require --dev palantirnet/drupal-rector --with-all-dependencies
composer require drupal/upgrade_status --update-with-all-dependencies

```
> 1 votes

---
Tags: composer
---


# Question
Title: Context Definition for Taxonomy Term Not Working
For the life of me, I can not get the taxomony term context definition to work for me. I'm trying to extend the ConditionPluginBase. I can get it working for nodes, but not for terms. I want to show a block on certain node and term pages.

When I just use the node context, it works for nodes.

When I add the term context, it doesn't work at all - not for nodes or terms.

### Works

```
/**
 * @Condition(
 *   id = "blog_content",
 *   label = @Translation("Blog Content"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node", label = @Translation("node")),
 *   }
 * )
 */

```

### Does Not Work

```
/**
 * @Condition(
 *   id = "blog_content",
 *   label = @Translation("Blog Content"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node", label = @Translation("node")),
 *     "taxonomy_term" = @ContextDefinition("entity:taxonomy_term", label = @Translation("Taxonomy Term"))
 *   }
 * )
 */

```

I see the TermRouteContext class. I know this exist. I just can't figure out why I can't trigger it.

### Full Code

```
<?php

namespace Drupal\admin_helper\Plugin\Condition;

use Drupal\Core\Condition\ConditionPluginBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * @Condition(
 *   id = "blog_content",
 *   label = @Translation("Blog Content"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node", label = @Translation("node")),
 *     "taxonomy_term" = @ContextDefinition("entity:taxonomy_term", label = @Translation("Taxonomy Term"))
 *   }
 * )
 */
class BlogContent extends ConditionPluginBase implements ContainerFactoryPluginInterface {

  /**
   * {@inheritdoc}
   */
  public static function create(
    ContainerInterface $container,
    array $configuration,
    $plugin_id,
    $plugin_definition
  ) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return ['show' => 0] + parent::defaultConfiguration();
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(
    array $form,
    FormStateInterface $form_state
  ) {
    $form['show'] = [
      '#title' => $this->t(
        'Display for blog post nodes and pages marked as "Blog Landing."'
      ),
      '#type' => 'checkbox',
      '#default_value' => $this->configuration['show'],
    ];

    return parent::buildConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(
    array &$form,
    FormStateInterface $form_state
  ) {
    $this->configuration['show'] = $form_state->getValue('show');
    parent::submitConfigurationForm($form, $form_state);
  }

  /**
   * {@inheritdoc}
   */
  public function evaluate() {
    if (empty($this->configuration['show']) && !$this->isNegated()) {
      return TRUE;
    }

    $node = $this->getContextValue('node');

    if (
      ($node->getType() == "blog_post") ||
      (
        $node->hasField('field_page_type') &&
        $node->get('field_page_type')->target_id === '597'
      )
    ) {
      return TRUE;
    }

    $term = $this->getContextValue('taxonomy_term');

    if ($term) {
      return TRUE;
    }

    return FALSE;
  }

  /**
   * {@inheritdoc}
   */
  public function summary() {
    if ($this->configuration['show']) {
      // Check if the 'negate condition' checkbox was enabled.
      if ($this->isNegated()) {
        // The condition is enabled and negated.
        return $this->t(
          'The block will be shown on all pages except the Blog-related pages.'
        );
      }
      else {
        // The condition is only enabled.
        return $this->t('The block will be shown only on Blog-related pages.');
      }
    }
    // The condition is not enabled.
    return $this->t('The block will be shown on all pages.');
  }

}

```

# Answer
Context depends on the presence of one or more context providers *and how they extract that data*. In this case of `TermRouteContext`, it extracts Term information *from the route*.

```
if ($route_object = $this->routeMatch->getRouteObject()) {
  $route_parameters = $route_object->getOption('parameters');

  if (isset($route_parameters['taxonomy_term']) && $term = $this->routeMatch->getParameter('taxonomy_term')) {
    $value = $term;
  }
  elseif ($this->routeMatch->getRouteName() == 'entity.taxonomy_term.add_form') {
    $vocabulary = $this->routeMatch->getParameter('taxonomy_vocabulary');
    $value = Term::create(['vid' => $vocabulary->id()]);
  }
}

```

*(Quick aside, you can debug the context provider's `getRuntimeContexts()` and walk through how and if it's getting the information. They always execute iirc.)*

This means that in order for `TermRouteContext` to extract Term information and provide it to your condition plugin, your code must be executing from a route where a parameter named `taxonomy_term` is present and has a value (most likely the term ID). *If any of the context values are empty, your condition plugin's context requirements are not satisfied and Drupal won't execute your plugin*.

If you still intend to run your plugin knowing full well that the term from context can be empty, missing, or just not provided, you can set `required = FALSE` on your `@ContextDefinition` for `entity:taxonomy_term`. In your case, you want to execute this condition on node or term pages, you can set `required = FALSE` on both and you deal with when either value is present or empty.

```
/**
 * @Condition(
 *   id = "blog_content",
 *   label = @Translation("Blog Content"),
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node", required = FALSE, label = @Translation("node")),
 *     "taxonomy_term" = @ContextDefinition("entity:taxonomy_term", required = FALSE, label = @Translation("Taxonomy Term"))
 *   }
 * )
 */

```

If `TermRouteContext` doesn't fit your use case (e.g. the term isn't on the route, or if you have to dig it out of some field on the current node), you can always build your own context provider.
> 1 votes

---
Tags: 9
---


# Question
Title: How do I add a product variance title to the order information page?
I am looking to have the Product Title appear in the Order Information page. However, the data is pulling the price versus the product title. I attempted to change the views. No luck. I am not a developer, so, if development is needed, okay. Just looking for an easy way to make this work.

# Answer
> 0 votes
That second column, 'Price: $34' is created from the Summary display of the Product variant. If you've created your own new Product variant type, it won't have any Summary display, so Commerce uses the Default display, which shows the Price.

To fix it, go to Commerce \> Configuration \> Products \> Product variation types, then choose ‘Manage display’ for your Product variation type. Click Custom Display Settings, put a tick next to ‘Summary’, and Save.

Now you’ll a see choice of Default or Summary display. Click on Summary, then rearrange the fields to show what you want to appear in that second column.

On our site I changed it to show only the product's name, so:

* FIELD: Product
* LABEL: Hidden
* FORMAT: Label, with ‘Link label to the referenced entity’ disabled

Save, clear caches, and check the order information page shows what you want.

---
Tags: commerce
---


title: Combining exposed filter with Facet

text:
# Question
Title: Combining exposed filter with Facet
This is my big problem, I want to combine a field of free search (text) generated with an **exposed filter** and **facet filter**.

The main problem is the follow: if I do a search across exposed filter then facets are update regularly. (as it should be).

If, however, at the first filter the view with facets and then I do a search with the field exposed, the facets are reset. Is it possible combine facet and exposed filter?

Need some idea pls.

# Answer
> 2 votes
Better is late than never :) you can use views with AJAX mode and my module ajax\_facets

# Answer
> 0 votes
For Drupal \>=9 see https://www.drupal.org/project/facets/issues/3013702#comment-14685036. Facets 3.x (still dev) will have this functionality built in. It can then also be combined with better\_exposed\_filters for further customization.

---
Tags: views, search
---


# Question
Title: How do I add a pagination on a template file?
I'm currently new with Drupal 8 and right now I'm trying to output a pagination on my twig file using entity query. So far this is my current code that I came up with. My goal is output the news content type using entity and add a pagination. I've already added `pager(9)` to display only 9 items. I tried inserting `{{pager}}` on my twig file but I don't see any pagination being rendered. I'm not sure what I'm missing here. Really need some help.

```
// Entity Query for News
//////////////////////////////////////////////////

$newsPostings = $query->get('node')
    ->condition('status', 1, '=')
    ->condition('type', 'article')
    ->sort('created', 'desc')
    ->pager(9)
    ->execute();

foreach ($newsPostings as $key => $news_postings) {

    $newsNode = _nodeLoad($news_postings);

    $publishDate = strtotime($newsNode->get('created')->value);
    $articleCreated = date('F j, Y', $publishDate);

    $variables['article'][$key]['title'] = $newsNode->get('title')->value;
    $variables['article'][$key]['image'] = $newsNode->field_image->entity->url();
    $variables['article'][$key]['path'] = $newsNode->toUrl();
    $variables['article'][$key]['date'] = $articleCreated;
}

// Pager for News Entity Query
//////////////////////////////////////////////////
$nodesNews =  \Drupal\node\Entity\Node::loadMultiple($newsPostings);
$pathNews = base_path();

$pager = $query->extend('Drupal\Core\Database\Query\PagerSelectExtender')->limit(9);
$result = $pager->execute();

 $build['results'] = array(
     '#theme' => 'page__news',
     '#items' => $nodesNews,
     '#path'  => $pathNews,
   );

   $build['pager'] = array(
     '#type' => 'pager'
   );

return $build;

```

# Answer
Modify your query to add pager,for the pagination we need to extend the pagerselectextender and add limit in the query.

```
 $pager = $query->extend('Drupal\Core\Database\Query\PagerSelectExtender')->limit(9);
 $result = $pager->execute();

/////////////////updated////////////////////
     $query->get('node')
     $query->condition('status', 1, '=')
     $query->condition('type', 'article')
     $query->sort('created', 'desc')
     $pager = $query->extend('Drupal\Core\Database\Query\PagerSelectExtender')->limit(1);
     $newsPostings = $pager->execute();
////////////////////updated///////////////////////////

  $build['results'] = array(
      '#theme' => 'page__news',
      '#items' => $nodesNews,
      '#path'  => $pathNews,
    );

    $build['pager'] = array(
      '#type' => 'pager'
    );

```
> 0 votes

# Answer
Use the render service either via dependency injection or directly from service container.

```
$pager = array(
      '#type' => 'pager'
    );

$build['results'] = array(
      '#theme' => 'page__news',
      '#items' => $nodesNews,
      '#path'  => $pathNews,
      '#pager' => \Drupal::service('renderer')->render($pager)
    );

```

Then print **{{ pager }}** into your twig file.
> 0 votes

---
Tags: 8, paging
---


# Question
Title: When I add an emoji in full HTML with CKeditor 5, I get a PHP error
I created a custom block with Full HTML text format and CKeditor 5. When I add an emoji, I have a PHP error in my Drupal 9 logs :

Drupal\Core\Entity\EntityStorageException : SQLSTATE\[22007\]: Invalid datetime format: 1366 Incorrect string value: '\xF0\x9F\xAB\xB6 V...' for column `z33ygz_app_drupal`.`ymce_block_content__body`.`body_value` at row 1: INSERT INTO "ymce\_block\_content\__body" ("entity\_id", "revision\_id", "bundle", "delta", "langcode", "body\_value", "body\_summary", "body\_format") VALUES (:db\_insert\_placeholder\_0, :db\_insert\_placeholder\_1, :db\_insert\_placeholder\_2, :db\_insert\_placeholder\_3, :db\_insert\_placeholder\_4, :db\_insert\_placeholder\_5, :db\_insert\_placeholder\_6, :db\_insert\_placeholder\_7); Array ( \[:db\_insert\_placeholder\_0\] =\> 20 \[:db\_insert\_placeholder\_1\] =\> 93 \[:db\_insert\_placeholder\_2\] =\> basic \[:db\_insert\_placeholder\_3\] =\> 0 \[:db\_insert\_placeholder\_4\] =\> fr \[:db\_insert\_placeholder\_5\] =\>

**Vous êtes producteur et vous proposez la vente à la ferme.**

\[:db\_insert\_placeholder\_6\] =\> \[:db\_insert\_placeholder\_7\] =\> full\_html ) dans Drupal\Core\Entity\Sql\SqlContentEntityStorage-\>save() (ligne 811 de /home/clients/588444ff5555fg4g4g4g5396/sites/www.example.com/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).

Why can't I use emoji in the text box ?

# Answer
> 2 votes
The problem is probably that the Drupal site was setup some years ago when they still used UTF-8 with three bytes per character because many versions of MYSQL didn't support more than that.

You need to change the column in the database to a `mb4` collation for multibyte strings with 4 bytes per character, like this emoji `\xF0\x9F\xAB\xB6`.

Whether you use `utf8mb4_general_ci` or `utf8mb4_unicode_ci` doesn't matter for storing the emoji, this is important for sorting and filtering. The first one has a better performance, the second one can sort and filter in multiple languages. If in doubt use the second one because the performance disadvantage is negligible in most cases.

The current Drupal 9 version is using `utf8mb4_0900_ai_ci` if the MySQL database is supporting this, which has improved language support.

Example:

```
mysql -u mysqluser -p
Enter password:
use my_drupal_database;
ALTER TABLE block_content__body MODIFY body_value LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE block_content_revision__body MODIFY body_value LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

```

---
Tags: blocks, 9
---


# Question
Title: How can I filter by taxonomy term after the first level filter?
I have two content types (*Book* and *Video*), each with its own vocabularies: *Book Vocabulary* with *Newspaper*, *Novel*, and *Magazine*; *Video Vocabulary* with *Movie*, *TV Show*, and *Documentary*.

I have a view showing all the Book and Video nodes. My goal is to be able to filter by content type first, then by taxonomy terms (of the selected vocabulary/content type).

# Answer
> 0 votes
I’m not positive this will work correctly but you could try utilizing field groups.

1. enter your view, under filter criteria select add. Now under category drop-down select content. Find the option “Content Type” and select it, then select “Add and configure filter criteria”. Select top checkbox “expose this filter to visitors” then select content type “book” and also content type “video” then select apply.
2. Again select add, go to content, and this time select “has taxonomy terms”, again expose filter, and select the specific terms you mentioned above, then apply. You will need to do this step twice, so you have a taxonomy filter for both book taxonomies and video taxonomies.
3. Now select the arrow just to the right of “add”, then select “and/or rearrange”. In the top right select “create new filter group”. You will want to select all operators as “or”. Arrange group one to have “content: content type = book” as well as “content: has taxonomy terms” and arrange group two to have “content: content type = video” as well as “content: has taxonomy terms”.

Select apply and then save the view and see if that does the trick

---
Tags: views
---


# Question
Title: Why is core installed into the vendor directory?
When I am trying to upgrade module or theme via Composer, I get this exception.

> Fatal error: Cannot redeclare config\_get\_config\_directory() (previously declared in D:\xampp\htdocs\itdlocal\_test\web\core\includes\bootstrap.inc:214) in D:\xampp\htdocs\itdlocal\_test\web\vendor\drupal\core\includes\bootstrap.inc on line 214

Please let me know on the fix for the error. I have tried removing the lock file and vendor folder but the issue not rectified when we are trying to run composer update.

My composer.json is the following.

```
{
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        },
        {
          "type": "package",
          "package": {
            "name": "ckeditor/find",
            "version": "4.8.0",
            "type": "drupal-library",
            "extra": {
              "installer-name": "find"
            },
            "dist": {
              "url": "https://download.ckeditor.com/find/releases/find_4.8.0.zip",
              "type": "zip"
            }
          }
        }
    ],
    "require": {
        "composer/installers": "^1.2",
        "cweagans/composer-patches": "^1.6",
        "drupal/addtoany": "1.16",
        "drupal/admin_toolbar": "^2.0",
        "drupal/advagg": "^4.1",
        "drupal/anchor_link": "^2.4",
        "drupal/auto_entitylabel": "^3.0",
        "drupal/autologout": "^1.3",
        "drupal/better_exposed_filters": "^4.0",
        "drupal/blazy": "^2.0",
        "drupal/block_class": "2.0",
        "drupal/block_token": "1.x-dev",
        "drupal/blockgroup": "1.5",
        "drupal/blocktabs": "^1.0",
        "drupal/chosen": "^2.9",
        "drupal/ckeditor_accordion": "^1.2",
        "drupal/ckeditor_copyformatting": "^1.0",
        "drupal/ckeditor_find": "^1.0@beta",
        "drupal/ckeditor_font": "1.3",
        "drupal/ckeditor_liststyle": "^1.3",
        "drupal/ckeditor_media_embed": "1.11",
        "drupal/ckeditor_pastefromword": "^1.0",
        "drupal/ckeditor_rm": "^6.0",
        "drupal/coder": "^8.3",
        "drupal/colorbox": "2.0",
        "drupal/colorbox_load": "1.2",
        "drupal/colorbutton": "^1.1",
        "drupal/config_ignore": "^2.2",
        "drupal/config_log": "^2.1",
        "drupal/content_export_csv": "^3.0@beta",
        "drupal/content_language_access": "^1.1",
        "drupal/content_moderation_notifications": "^3.2",
        "drupal/core-composer-scaffold": "^8.8",
        "drupal/core-project-message": "^8.8",
        "drupal/core-recommended": "^8.8",
        "drupal/core-vendor-hardening": "^8.8",
        "drupal/crop": "^2.0",
        "drupal/csv_importer": "^1.6",
    },
    "conflict": {
        "drupal/drupal": "*"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "sort-packages": true,
        "allow-plugins": {
            "composer/installers": true,
            "cweagans/composer-patches": true,
            "drupal/core-composer-scaffold": true,
            "drupal/core-project-message": true,
            "drupal/core-vendor-hardening": false
        }
    },
    "enable-patching": true,
    "extra": {
        "drupal-scaffold": {
            "locations": {
                "web-root": "./"
            }
        },
        "patches": {
            "drupal/core": {
                "Drupal core patch for enabling exposed filter": "https://www.drupal.org/files/issues/2019-09-30/2681947-33.patch",
                "Allow exposed form to preserve URL query parameters": "https://www.drupal.org/files/issues/2020-02-04/2681953-23.patch"
            },
            "drupal/blocktabs": {
                "Views Ajax not working in block tabs": "https://www.drupal.org/files/issues/2019-10-24/blocktabs-preview-2992052-2.patch"
            },
            "drupal/videojs": {
                "In videojs changed the js files in librariesyml": "patches/videojs_library.patch"
            },
            "drupal/admin_toolbar": {
                "'admin_toolbar - Multi column": "patches/added-multi-column-menu-dropdown-2917168-20.patch"
            },
            "drupal/better_exposed_filters": {
                "preserve URL query parameters for bef": "patches/preserv_query_param.patch"
            },
            "drupal/SMTP": {
                "Invalid mail address" : "patches/SMTP_mail.patch"
            },
            "drupal/token_for_file_name_without_extension": {
                "Token for displaying Filename excluding the file extension":"patch_for_tokens_filename_without_extension.patch"
            },
            "drupal/chosen_dropdown_expand_dropdown_on_spacebar_press": {
                "Expanding the chosen dropdown on click of spacebar":"do_not_autosubmit_chosenjs_search.patch"
            }
        },
        "installer-paths": {
            "core": ["type:drupal-core"],
            "libraries/{$name}": ["type:drupal-library"],
            "modules/contrib/{$name}": ["type:drupal-module"],
            "profiles/contrib/{$name}": ["type:drupal-profile"],
            "themes/contrib/{$name}": ["type:drupal-theme"],
            "drush/Commands/contrib/{$name}": ["type:drupal-drush"],
            "modules/custom/{$name}": ["type:drupal-custom-module"],
            "themes/custom/{$name}": ["type:drupal-custom-theme"]
        },
        "drupal-core-project-message": {
            "include-keys": ["homepage", "support"],
            "post-create-project-cmd-message": [
                "<bg=blue;fg=white>                                                         </>",
                "<bg=blue;fg=white>  Congratulations, you’ve installed the Drupal codebase  </>",
                "<bg=blue;fg=white>  from the drupal/legacy-project template!               </>",
                "<bg=blue;fg=white>                                                         </>",
                "",
                "<bg=yellow;fg=black>Next steps</>:",

                "  * Install the site: https://www.drupal.org/docs/8/install",
                "  * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html",
                "  * Get support: https://www.drupal.org/support",
                "  * Get involved with the Drupal community:",
                "      https://www.drupal.org/getting-involved",
                "  * Remove the plugin that prints this message:",
                "      composer remove drupal/core-project-message"
            ]
        }
    }
}

```

# Answer
There are two installs of Drupal. You probably said "no" to the Composer extension called `composer-installers`. Please check the value for `composer-installers` in the `config.allow-plugins` section of `composer.json`. The value you should use is `true`.
> 3 votes

---
Tags: composer
---


# Question
Title: How to programatically publish content after form validation
I have a content type of which its `status` is set to unpublished and is disabled. A site manager needs to publish the content after approval.

The site manager wants to skip this validation process when creating the same content and immediately publish the content after submitting the creation form.

In my `_form_validate` function:

```
  if (in_array('site_manager', $user->getRoles())) {
    if ($given_email == 'info@example.com') {
      $form_state->setValue('status', ['value' => True]);
    }
  }

```

And the value in `$form_state` is properly set to: True when inspecting with XDebug. But it does not publish the content automatically. How can I achieve this?

# Answer
> 2 votes
You're trying to combine what should be two steps, into one. Validation handlers are for validation, so skipping the validation happens in the validation handler. Processing, which in this case setting is setting the node to published, happens in the submit handler.

In the validation handler:

```
if (!in_array('site_manager', $user->getRoles()) || $given_email !== 'info@example.com') {
    // Form validation for users other than the site manager goes here.
  }
}

```

In the validation handler (assuming this is a node form):

```
if (in_array('site_manager', $user->getRoles()) && $given_email == 'info@example.com') {
    $node = $form_state->getFormObject()->getEntity();
    $node->setPublished()
      ->save();
  }
}

```

However, this is not how I would go about this. Hard coding an email address into this makes it difficult to change if the email address changes in the future. Instead, I would:

1. Create a new role.
2. Create a new permission in \[MODULE\].permissions.yml (don't forget to clear the registry after):

```
bypass my form validation:
  title: 'Bypass my form validation'
  description: 'Bypasses validation of My Form'
  restrict access: true

```
3. Assign the new permission to the role created in step one.
4. Assign the role to the admin user who is to bypass validation.
5. Change the validation code to this:

```
if (!\Drupal::currentUser()->hasPermission('bypass my form validation')) {
    // Form validation for users other than the site manager goes here.
  }
}

```
6. Change the submit handler to this:

```
if (\Drupal::currentUser()->hasPermission('bypass my form validation')) {
  $node = $form_state->getFormObject()->getEntity();
  $node->setPublished()
    ->save();
  }
}

```

This gives a more dynamic solution, in that the user can change their email address in the system, without having to update the code for the new email address. It also allows for adding additional users that can be skipped in the future if the need comes up, simply by assigning them the role created in step one.

---
Tags: forms, 9
---


# Question
Title: How can I use custom HTML/CSS in the login page?
I have custom HTML and CSS code for a login page. I want to customize my site's login form to look like the custom login page I have. How can I customize the default login page with the HTML and CSS code I have? All similar questions I saw were either outdated or didn't address this "custom HTML/CSS code" aspect.

# Answer
> 1 votes
You can write a custom module to use attaching a library to a form

As forms are just render arrays, attaching a library works just the same:

```
/**
 * Implements hook_form_alter().
 */

    function yourmodule_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
      if ($form_id == 'article_node_form') { {
          $form['#attached']['library'][] = 'yourmodule/yourlibrary';
        }
    }

```

Here is the official documentation with an anchor to the part that explain how to add it to a form : https://www.drupal.org/docs/creating-custom-modules/adding-stylesheets-css-and-javascript-js-to-a-drupal-module#s-attaching-a-library-to-a-form

---
Tags: 9
---


# Question
Title: Removing orphaned paragraph references from the user
## Setup

Drupal 9 site has Users and each user has a Paragraph that contains "Phone" data. User =\> Phone Paragraph connection is made via field `$user->field_phone_para`.

## Issue

Somehow database has gotten "ghost" references for the `$user->field_phone_para` field. When I load the user and print the phone paragraph reference values/targets, it gets 3 responses. In reality there should be only one.

```
$user = User::load(4049);
dd($user->field_phone_para->getValue());

```

Outputs:

```
array:3 [
  0 => array:2 [
    "target_id" => "8555"
    "target_revision_id" => "15528"
  ]
  1 => array:2 [
    "target_id" => "17677"
    "target_revision_id" => "36696"
  ]
  2 => array:2 [
    "target_id" => "26289"
    "target_revision_id" => "45308"
  ]
]

```

`user__field_phone_para` database table confirms the same - 3 entries for this user.

Yet if I check the `paragraph__field_phone` database table for those 3 target\_id-s , there is entry only for the ID `26289`. Which means that 8555 and 17677 are kind of ghosts and should be gone.

## Question

What is the correct way to clean up the database from those ghost / orphaned entries?

## Ideas / what I've tried

* Manually saving the user in the Drupal admin removes the ghost references (but not viable due to the amount of users).
* Just loading the user and then saving the user via `save()` does not remove the ghost references.
* Tested https://www.drupal.org/project/entity\_reference\_purger \- does not seem to work with Users + Paragraphs.

Would it make sense to have a SQL query to delete all the entries from the `user__field_phone_para` database table which don't have corresponding entries in the `paragraph__field_phone` table? Matching would be done by `user__field_phone_para.field_phone_para_target_id` and `paragraph__field_phone.entity_id`.

Only possible issue with deleting directly via the SQL query is that the "delta" would not be reset in the `user__field_phone_para` table to what it should be - in the current example case it should become 0 for the real entry since we remove 2 ghosts. Yet when new phone number is added via the admin form, Drupal would take care of resetting the delta anyway so probably not an issue.

# Answer
> What is the correct way to clean up the database from those ghost / orphaned entries?

Use `drush errp` to clean up orphaned paragraph entities.

Make sure to have a database backup before running the above command.
> 0 votes

---
Tags: entities, users, paragraphs
---


# Question
Title: Set restrictions to nodes displayed after submission
I have a content type (*AppointmentApplication*), which can be used from anonymous users; all the information can be viewed by administrator users.

I don't want all the entered information to be shown right after the node submission by anonymous users in the success page. I just want to show a serial number which can be used from users as their application number. When I restrict the access to this content type display, it effects everyone.

>

# Answer
Sounds like this is more a job for Webform.

While Content Types/Nodes are quite flexible, it's more for building content pages. Your use case sounds more like arbitrary one-time form submission, which is what Webforms is designed for.
> 2 votes

---
Tags: views
---