# Question
Title: How do I upcast route parameters for entity_revision?
My custom entity is revisionable. I can see revisions, but my revision revert form doesn't work. The route for the form is definited in *msul\_rovi\_games.routing.yml*.

```
entity.rovi_game.revision_revert_confirm:
  path: '/rovi_game/{rovi_game}/revisions/{rovi_game_revision}/revert'
  defaults:
    _title: 'Revert to an earlier revision'
    _form: '\Drupal\msul_rovi_games\Form\RoviGameRevisionRevertForm'
  requirements:
    _permission: 'administer rovi_game entities'
    rovi_game: \d+
  options:
    _node_operation_route: TRUE
    rovi_game:
      type: entity:rovi_game
    rovi_game_revision:
      type: entity_revision:rovi_game

```

The form is defined in *src/Form/RoviGameRevisionRevertForm.php*.

```
namespace Drupal\msul_rovi_games\Form;

use Drupal\Component\Datetime\TimeInterface;
use Drupal\Core\Datetime\DateFormatterInterface;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\msul_rovi_games\Entity\RoviGameInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides a form for reverting a rovi_game revision.
 *
 * @internal
 */
class RoviGameRevisionRevertForm extends ConfirmFormBase {

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, RoviGameInterface $rovi_game_revision = NULL) {
    $this->revision = $rovi_game_revision;
    $form = parent::buildForm($form, $form_state);

    return $form;
  }
}

```

When I attempt to revert, I get the following error.

> TypeError: Argument 3 passed to Drupal\msul\_rovi\_games\Form\RoviGameRevisionRevertForm::buildForm() must implement interface Drupal\msul\_rovi\_games\Entity\RoviGameInterface or be null, string given in Drupal\msul\_rovi\_games\Form\RoviGameRevisionRevertForm-\>buildForm() (line 116 of /opt/drupal/web/modules/custom/msul\_rovi\_games/src/Form/RoviGameRevisionRevertForm.php)

What am I missing?

# Answer
You are just missing a level, 'parameters', in your options array. See Upcasting route slug name options. Note that parameters must be nested under *options \> parameters*.

```
foobar.view:
  path: '/foobar/{foobar_placeholder}'
  defaults:
    _controller: '\Drupal\foobar\Controller\Foobar::content'
    _title: 'Oh yeah foobar'
  options:
    parameters:
      foobar_placeholder:
        type: entity:foobar

```

Your code updated:

```
entity.rovi_game.revision_revert_confirm:
  path: '/rovi_game/{rovi_game}/revisions/{rovi_game_revision}/revert'
  defaults:
    _title: 'Revert to an earlier revision'
    _form: '\Drupal\msul_rovi_games\Form\RoviGameRevisionRevertForm'
  requirements:
    _permission: 'administer rovi_game entities'
    rovi_game: \d+
  options:
    _node_operation_route: TRUE
    # Nest parameters under "parameters"
    parameters:
      rovi_game:
        type: entity:rovi_game
      rovi_game_revision:
        type: entity_revision:rovi_game

```
> 4 votes

---
Tags: routes, 9
---


# Question
Title: hook_form_alter() to add placeholder to a text field via custom module
It should be very straightforward and yet, I can't identify the reason why this doesn't add a placeholder to a field in a form:

```
function posts_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == "node_post_form" || $form_id == "node_post_edit_form") {
    $form['field_post_subject']['#attributes']['placeholder'] = t("blah");
    dpm($form['field_post_subject']);
  }
}

```

This confirms that the key `placeholder` is being set:

The hook\_form\_alter() works as expected for other things I need to change, except the placeholder. I looked everywhere and it's always the same solution so I'm wondering what I'm missing?

# Answer
> 2 votes
You are now setting the placeholder attribute to a container, which should be visible in the source HTML, but doesn't have any effect on the form.

You need to add the placeholder to a form element. You find at least one, for multi-value or multi-property fields multiple, inside the `widget` key (in your debug output a children of the container).

Text fields have already a configurable option for placeholders. If you need to overwrite it dynamically you have to look for the form element and set a new #placeholder.

This is the form element you are looking for:

*StringTextfieldWidget::formElement*

```
$element['value'] = $element + [
  '#type' => 'textfield',
  '#default_value' => $items[$delta]->value ?? NULL,
  '#size' => $this->getSetting('size'),
  '#placeholder' => $this->getSetting('placeholder'),
  '#maxlength' => $this->getFieldSetting('max_length'),
  '#attributes' => ['class' => ['js-text-full', 'text-full']],
];

```

---
Tags: 9
---


# Question
Title: How can I update the node date for all nodes
I have imported a number of nodes to a fresh installed Drupal 9. Later, the original content creation date (from the previous website) became important.

I have the information according to the new node ids. I don't know where to update?

I have tried to update the created and changed columns in node\_field\_data table, but in the content list I still see the import date... Where should i look? (of course I'm open to suggestions with modules, tricks in administration interface etc, I thought updating sql tables would be easier).

# Answer
First off, I would avoid as much as possible making direct DB updates for entities. Drupal 8+'s entity model is tightly bound to its abstraction layers, implemented as hooks. It is considered best practice to always modify entities via the entity API. This will allow Drupal to keep all things in sync.

Now, the short answer to your question is that clearing your site's cache will likely result in the new values being displayed.

A better answer would be to script some PHP in order to iterate through all nodes and update their content creation date via entity API. I often use Drush in order to perform these types of operations. Below is an example that should suit your needs, based on the following presumption:

* You have loaded your node:date values into an array called `$new_node_dates`, where the keys are NIDs and the values are Unix timestamps representing the new creation dates. See here for an example of reading a CSV file into an array. If the dates are not in a Unix timestamp format, you can use strtotime() to convert them.

The Drush statement would then be:

`drush eval '$node_storage = \Drupal::entityTypeManager()->getStorage("node"); foreach($new_node_dates as $nid => $creation_date) { $node = $node_storage->load($nid); $node->created = $creation_date; $node->save(); }'`

Best of luck!
> 1 votes

---
Tags: nodes, datetime, 9
---


# Question
Title: How to store a safevalue of a field in addition to the original?
I have a custom field type that I create with a custom module. It is a plain text field where the user type in a string. I want to retain two copies of this field:

1. The exact string value as typed by the user.
2. A safe value of the same string.

This is how I create the field:

```
class MyItem extends FieldItemBase {

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'value' => [
          'type' => 'text',
          'size' => 'tiny',
          'not null' => FALSE,
        ],
        'safevalue' => [
          'type' => 'text',
          'size' => 'tiny',
          'not null' => FALSE,
        ],
      ],
    ];
  }
…

}

```

I assume I should generate a `safevalue` of the string in `hook_node_presave()` and somehow get into the entity there (but corrections to these assumptions are welcome).

I have no problem getting the string value as typed by the user and to compute a safe value:

```
$value = $entity->field_myfield->getString();
$safevalue = makeSafe($value);

```

But I do not know how to get the `$safevalue` stored in the database.

### Edit

I see that this has two nearly identical answers. Both work fine if the cardinality of the field is one, so I've upvoted both. Since I cannot accept both, I've accepted the one from apaderno for the extra detail about `propertyDefinitions()`.

I am still not able to get this to work with a multivalue field, but I think that probably need to be a separate question.

# Answer
If `safeValue` has been defined as field property in `propertyDefinitions()`, it can be accessed as `$entity->field_myfield->safeValue`, either to read it or write it.

In Drupal core, an example of field that stores a processed copy of the field value is the `TextItem` class, whose `propertyDefinitions()` method contains the following code.

```
$properties['value'] = DataDefinition::create('string')
  ->setLabel(t('Text'))
  ->setRequired(TRUE);
$properties['format'] = DataDefinition::create('filter_format')->setLabel(t('Text format'));
$properties['processed'] = DataDefinition::create('string')
  ->setLabel(t('Processed text'))
  ->setDescription(t('The text with the text format applied.'))
  ->setComputed(TRUE)
  ->setClass('\\Drupal\\text\\TextProcessed')
  ->setSetting('text source', 'value')
  ->setInternal(FALSE);

```

That class defines the property as computed. That's why its `schema()` method doesn't include that property.
> 2 votes

# Answer
For saving:

```
$value = $entity->field_myfield->getString();
$entity->field_myfield->safevalue = makeSafe($value);

```

For loading:

```
$safe_value = $entity->field_myfield->safevalue;

```
> 2 votes

---
Tags: entities, 9
---


# Question
Title: How to get and apply current page query parameters from current AJAX request
I'm having a hard time figuring out how to do this.

Essentially I have a table displaying users on a page. The table is paginated with the PagerExtender and sortable with the TableSortExtender.

Each user row has links with "use-ajax" classes; these links perform actions on the user, and then rebuild the current table after performing those actions -- this happens all in AJAX.

The problem I am having is, when I rebuild the table in AJAX, the current request is the request for the AJAX action, and not the request which built this page. This means when the table is rebuilt via AJAX, the pager and sort settings are lost and you are reset to the first page, without any sorts.

I have found code somewhere to pull the previous request, and get the URL and parameters, but I don't know how reliable this is or how to implement it:

```
$current_request = \Drupal::request();
$previous_url = $current_request->server->get('HTTP_REFERER');
$previous_request = Request::create($previous_url);
// $url_object is a Url with the previous page paramters and URL
$url_object = \Drupal::service('path.validator')->getUrlIfValid($previous_request->getRequestUri());

```

The problem with the above is:

1. I don't know how reliable the HTTP\_REFERER will be
2. I don't know how to add the previous page request parameters to the current request, so the table is rebuilt properly
3. If the previous request is NOT the request that built the table/page, I'm stuck again

Is the solution always passing the previous request URL and Params with every AJAX request I make? I feel like **someone has solved this somewhere or somehow** but I am just lost in this area in Drupal 8, and have been beating my head constantly trying to figure out how to refresh parts of a page in an AJAX request.

EDIT: I am not certain the best place to put the "completed" code, but thanks to 4k4 I've put the following together:

```
  // create url object from route to render link
  $my_url = Url::fromRoute('my_module.my_route', array('param' => $value));
  // get the current query parameters for our page
  $query_options = \Drupal::request()->query->all();
  // add them to our Url
  $my_url->setOption('query', $query_options);

```

# Answer
> 2 votes
No, HTTP\_REFERER is not reliable and yes, the solution is to add the query parameters of the current request to each AJAX link. Form API does the same for form elements:

RenderElement::preRenderAjaxForm:

```
    // Add all the current query parameters in order to ensure that we build
    // the same form on the AJAX POST requests. For example,
    // \Drupal\user\AccountForm takes query parameters into account in order
    // to hide the password field dynamically.
    $settings['options']['query'] += \Drupal::request()->query->all();

```

# Answer
> 0 votes
This works for me in Drupal 9.3:

```
#ajax request body

$.ajax({
  url: Drupal.url('ajax-load-more'),
  type: 'post',
  data: { nid : drupalSettings.webform.dialog.entity_id },
  success: function (res) {
    console.log(res);
  }
});

```

In the controller file:

```
$nid = \Drupal::request()->get('nid');

```

---
Tags: ajax, http-request
---


# Question
Title: Set no cache when generating dynamic local action via derivatives
I'm trying to generate a dynamic local action via a derivative. The derivative works and returns a link generated dynamically but the cache seems to maintain its value.

As per this Drupal core change log, I understood I could set cache parameters on the derivative, which I tried but in vain so far - I'm not very familiar with these concepts yet so appreciate any guidance on how to prevent `$gid` from being cached.

Here's my local action `leads.links.action.yml`:

```
leads.new_deal:
  deriver: 'Drupal\leads\Plugin\Derivative\DynamicLocalTasks'

```

Here's my derivative:

```
<?php

namespace Drupal\leads\Plugin\Derivative;

use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Cache\CacheableDependencyInterface;
use Drupal\Core\Cache\CacheableDependencyTrait;

/**
* Defines dynamic local tasks.
*/
class DynamicLocalTasks extends DeriverBase {
  use CacheableDependencyTrait;
  /**
  * {@inheritdoc}
  */
  public function getDerivativeDefinitions($base_plugin_definition) {
    $groupLead = getGroupsUserIsLead();

    if (isset($groupLead[0])){
      $gid = $groupLead[0];
    }
    else{
      return \Drupal\Core\Access\AccessResult::forbidden();
    }

    // Implement dynamic logic to provide values for the same keys as in example.links.task.yml.
    $this->derivatives['leads.new_deal'] = $base_plugin_definition;
    $this->derivatives['leads.new_deal']['title'] = "New Deal";
    $this->derivatives['leads.new_deal']['route_name'] = 'entity.group_content.create_form';
    $this->derivatives['leads.new_deal']['appears_on'] = ['leads.deals'];
    $this->derivatives['leads.new_deal']['route_parameters'] = ['plugin_id' => 'group_node:deals','group' => $gid];
    $this->cacheMaxAge = 0;
    $this->getCacheMaxAge();

    return parent::getDerivativeDefinitions($base_plugin_definition);
  }

  public function getCacheMaxAge() {
    return 0;
  }

}

```

# Answer
Adding the CacheableDependencyTrait to a deriver doesn't make it fully cacheable. There is no code in Drupal checking for cacheable dependencies of derivers in a normal request. You have to return the title, route name and so on from a local task plugin where you can also use getCache\*() methods. See https://drupal.stackexchange.com/a/273293/47547
> 2 votes

# Answer
As suggested by @4uk4, here's what I ended up doing:

```
leads.new_deal:
  route_name: entity.group_content.create_form
  title: 'New Deal'
  route_parameters:
    plugin_id: group_node:deals
    group: 0
  class: 'Drupal\leads\Plugin\Menu\DynamicLocalTasks'
  appears_on:
    - 'leads.deals'

```

```
<?php

namespace Drupal\leads\Plugin\Menu;

use Drupal\Core\Menu\LocalActionDefault;
use Drupal\Core\Routing\RouteMatchInterface;

class DynamicLocalTasks extends LocalActionDefault {
  public function getRouteParameters(RouteMatchInterface $route_match) {
    $groupLead = getGroupsUserIsLead();

    $gid = $groupLead[0] ?? NULL;

    return [
      'plugin_id' => 'group_node:deals',
      'group' => $gid,
    ];
  }
}

```
> 1 votes

---
Tags: 9
---


# Question
Title: Is it possible to programmatically change the config_sync_directory path after profile installation?
Installing Drupal 9 using a custom profile installation, I have defined `"config_sync_directory"` in `settings.php` file in `$settings` array to pick up the profile config during installation.

1. During site installation Drupal asks to specify the "config" directory in the settings file
2. In a custom profile I have some default configurations, I want Drupal to read configurations from that directory during installation, the path I specified in the settings file.
3. Now, post-installation I want to specify a separate config sync directory, and do not want to edit the settings.php file, again and again, just wanted to update the sync directory path from a hook in the custom module.

Is it possible to change the path programmatically from a hook?

# Answer
Modules can override the values in configuration objects. As described in Configuration override system / Providing overrides from modules, a module needs to implement a service tagged *config.factory.override*. The class used for the service needs to implement `ConfigFactoryOverrideInterface`, as the example given in the documentation does.

```
services:
  config_example.overrider:
    class: Drupal\config_example\Config\ConfigExampleOverrides
    tags:
      - {name: config.factory.override, priority: 5}

```

```
namespace Drupal\config_example\Config;

use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Config\ConfigFactoryOverrideInterface;
use Drupal\Core\Config\StorageInterface;

/**
 * Example configuration override.
 */
class ConfigExampleOverrides implements ConfigFactoryOverrideInterface {

  /**
   * {@inheritdoc}
   */
  public function loadOverrides($names) {
    $overrides = [];
    if (in_array('system.site', $names)) {
      $overrides['system.site'] = ['name' => 'Overridden site name!'];
    }
    return $overrides;
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheSuffix() {
    return 'ConfigExampleOverrider';
  }

  /**
   * {@inheritdoc}
   */
  public function getCacheableMetadata($name) {
    return new CacheableMetadata();
  }

  /**
   * {@inheritdoc}
   */
  public function createConfigObject($name, $collection = StorageInterface::DEFAULT_COLLECTION) {
    return NULL;
  }

}

```

Keep in mind that the value in the *settings.php* file always override the module values. For a module to set a configuration value, the *settings.php* file needs not to set it.
> 0 votes

---
Tags: configuration, installation-profiles
---


# Question
Title: How to update taxonomy field with array of terms?
I am having a body like this

```
{
    "userid": 435,
    "territories_id":[176,139]
}

```

Where userid is the drupal user id. And I need to update field **field\_user\_territory** which is a taxonomy field. I do not want earlier territories to go instead I need to update with 2 more territories.

This is the code I tried.

```
foreach ($territories_id as $territory_id) {

            $user = \Drupal\user\Entity\User::load($userid);
            $user->field_user_territory->target_id = $territory_id;
            $user->save();

    }

```

But here the earlier territories got vanished.

# Answer
You probably want to append the field items:

```
$user = \Drupal\user\Entity\User::load($userid);
foreach ($territories_id as $territory_id) {
  // full version (works with autocomplete in an IDE)
  $user->get('field_user_territory')->appendItem(['target_id' => $territory_id]);
  // short version in array syntax
  // $user->field_user_territory[] = $territory_id;
}
$user->save();

```
> 3 votes

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


# Question
Title: How can I get a multivalue field correctly inserted?
I have a custom module that creates a field type. It is a plain text field abd I've added it to a content type using the Drupal UI. The cardinality of this field is "Unlimited".

This is how I create the field in code:

```
class MyItem extends FieldItemBase {

  /**
   * {@inheritdoc}
   */
  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'value' => [
          'type' => 'text',
          'size' => 'tiny',
          'not null' => FALSE,
        ],
        'safevalue' => [
          'type' => 'text',
          'size' => 'tiny',
          'not null' => FALSE,
        ],
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties['value'] = DataDefinition::create('string')
      ->setLabel(t('Value'));
    $properties['safevalue'] = DataDefinition::create('string')
      ->setLabel(t('Safe value'))
      ->setComputed(TRUE);
    return $properties;
  }

}

```

As you can see, there are two columns: `value` is supposed to store raw user input. `safevalue` is supposed to store a sanitized version of the data.

For testing this. I am just doing this inside `hook_node_presave()`:

```
function mymodule_node_presave(\Drupal\Core\Entity\EntityInterface $entity) {
  switch ($entity->getBundle()) {
    case 'mybundle':
      $entity->field_myfield = ['one', 'two', 'three'];
      $entity->field_myfield->safevalue =  ['one', 'two', 'three'];
      break;
  }
}

```

If the field has a cardinality 1 (i.e. the values inserted are scalars), this works fine.

However, if I insert arrays, when I examine the database, and look at the table `node__field_myfield`, I see that the columns `field_myfield_value` and `field_myfield_safevalue` both exist with identical configurations.

If I create a node using the UI, I observe this:

* `field_myfield_value` column contains three rows with the strings 'one', 'two' and 'three'. That's correct.
* `field_myfield_safevalue` have the string 'Array' in its first row, and NULL in the two others. That's wrong.

I guess that what makes things go wrong is that this is a multivalue field and that I need to use some other action to get the values correctly inserted.

How can I get a multivalue field correctly inserted in the `safevalue` column?

# Answer
> 1 votes
When you access

```
$entity->field_myfield->safevalue

```

That is implicitly the *first* item in the field list's safevalue. You're not setting the safe value for all deltas in that field.

To do that, you need to set each value separately. Like so:

```
$values = [
  ['value' => 'foo', 'safevalue' => 'bar'],
  ['value' => 'foo2', 'safevalue' => 'bar2'],
];
$entity->field_myfield = $values;

```

Note the are several different permutations of the above, this is just one of them, if your usual code style for setting entity properties is different it's fine to use that instead.

# Answer
> 3 votes
The field deltas are one level higher than the properties.

```
$entity->field_myfield = [
  0 => [
    'value' => 'one',
    'safevalue' => 'one',
  ],
  1 => [
    'value' => 'two',
    'safevalue' => 'two',
  ],
  2 => [
    'value' => 'three',
    'safevalue' => 'three',
  ],
];

```

BTW when you save the field property then don't specify \>setComputed(TRUE). This is only when you calculate the field value in a typed data plugin.

---
Tags: hooks, 9
---


# Question
Title: routing for dynamic block for custom entity
For a custom entity I have created several dynamic blocks. But the blocks are not displayed. They are placed in admin/structure/block. Below is an example of block 1.

myentity.routing.yml:

```
myentity.blocks:
  path: '/collection/{myentity}'
  defaults:
    _title: 'Stuff collection'
  requirements:
    _permission: 'access content'
    myentity: \d+
  options:
    parameters:
      myentity:
        type: entity:myentity
        bundle:
            - a

```

Part of src/Plugin/Block:

```
namespace DrupalCorePluginBlock;

use DrupalCoreBlockBase;

/**
 * Provides a 'Collection' block.
 *
 * @Block(
 *   id = "collection_block 1",
 *   admin_label = @Translation("Collection: Stuff"),
 *   category = @Translation("My Collection"),
 *   context_definitions = {
 *     "myentity" = @ContextDefinition("entity:myentity", label = @Translation("Myentity ID"))
 *   }
 * )
 */
class MyentityBlock1 extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    $myentity = $this->getContextValue('myentity');
    return [...];
}

```

If I replace myentity with node, it works, but for a custom entity I probably need to define something more. But what?

# Answer
You can follow Providing global context variables. You have to create a new service to provide a context variable for your custom entity. You can use some entity node, user, taxonomy\_term... because them already define.

https://git.drupalcode.org/project/drupal/-/blob/9.3.x/core/modules/taxonomy/taxonomy.services.yml#L7

```
  taxonomy_term.taxonomy_term_route_context:
      class: Drupal\taxonomy\ContextProvider\TermRouteContext
      arguments: ['@current_route_match']
      tags:
        - { name: 'context_provider' }

```

https://git.drupalcode.org/project/drupal/-/blob/9.3.x/core/modules/taxonomy/src/ContextProvider/TermRouteContext.php#L48

```
 /**
   * {@inheritdoc}
   */
  public function getRuntimeContexts(array $unqualified_context_ids) {
    $result = [];
    $context_definition = EntityContextDefinition::create('taxonomy_term')->setRequired(FALSE);
    $value = NULL;
    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()]);
      }
    }

    $cacheability = new CacheableMetadata();
    $cacheability->setCacheContexts(['route']);

    $context = new Context($context_definition, $value);
    $context->addCacheableDependency($cacheability);
    $result['taxonomy_term'] = $context;

    return $result;
  }

```
> 3 votes

---
Tags: 9
---


# Question
Title: check if a page has been redirected and then add a class to a certain div
Im using the redirect module to redirect /page/scheduling to /page.

I need to check if the user arrived to a certain page by this redirect.

by checking this i will then add a class to a certain div.

How can I accomplish this?

# Answer
Instead of redirecting to /page you redirect to /page?hello=world then you can check in JS for that URL query param and fire your magic.
> 1 votes

---
Tags: 7, javascript, redirection
---


# Question
Title: Render a fulltext exposed search bar separate from the rest of the filters
I would like to render my exposed fulltext search bar in a separate location from the rest of my search filters. My other exposed search filters are things like display number, sort order, etc... I am also using facets.

My current problem is that I need to render the search bar in a whole separate region from the rest of my exposed filters. My current solution is to render `{{ exposed }}` twice but then use CSS to `display: none` the items I don't want. This is just awfully hacky and is bad practice. Is there a way to split these forms into two separate exposed filters?

# Answer
You can render one by one by:

```
{{ exposed.filter_1}}
{{ exposed.filter_2}}

```

And group them as your wish.

About the render `{{ exposed }}` twice as your current solution, The items you don't want can be removed at the .twig, not CSS such:

```
{{ exposed|without('filter_1', 'filter_2') }}

```
> 1 votes

---
Tags: views, search
---


title: Custom entityquery sorting

text:
# Question
Title: Custom entityquery sorting
I have a normal "surname" and "firstname" fields, however I need something more than

```
->sort('field_surname', 'ASC')
->sort('field_firstname', 'ASC')

```

The surnames are old English names and contain prefixes to the names so a surname of "St John" would need to be sorted as "Saint John" to appear in the list in the correct place.

Other examples could contain an apostrophe which would need to be removed for the sort, but still displayed.

Ideally I'd like a nice pre-written module to do this, but suspect there's not one.

Is there any way to add a custom sort to an entity query? I will probably need to use this same sort in a view so something that is re-usable (for example in a view) would be ideal.

# Answer
> 2 votes
Entity query only has pretty basic sort available.

You could write a more complicated query such as a SELECT query.

However, given that you want to reuse this in Views, and given that you probably have several rules that you want to apply, I would just add another field ("name for sorting") and then use hook\_entity\_presave() to compute the value by using whatever rules you want.

Using `hook_entity_presave()` ensures that the value will be updated when the node is created or edited, so it will always be current.

You can hide this field in the entity display settings and then sort by it in Views, entityquery, and anything else you want.

The downside of this approach is that you have another field in the database, but I think this approach is easier to maintain and troubleshoot than a complicated sort.

# Answer
> 0 votes
In case it helps others, I resolved this by pulling all the records with a basic sort and then using PHP's usort with a bespoke function to pull back the desired fields from the node object, manipulate and compare and then display as needed.

```
$node_ids = \Drupal::entityQuery('node')
            ->condition('type', 'my_type', '=')
            ->execute();
$nodes = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple($node_ids);
usort($nodes, [$this, "my_node_sort"]);

```

It sorted around 1800 complex nodes with no noticeable delay, so may not be a perfect solution, but workable. Also came in useful for another sort where it was not a straight alphabetical sort. Have not looked into Views, but suspect I can use a similar process.

---
Tags: entities
---


title: Media Library results filtered by user

text:
# Question
Title: Media Library results filtered by user
I am working on a project that will be using 100's users and potentially thousands of users. The users will be required to upload at the very least 5 images and possibly some PDF files.

Created a content type, and added some Media fields, which works perfect for this project. The user files uploaded will be all public but the issue is that when the user goes to browse for their files all files from all users are listed and available. Once the site reaches a high level of users, browsing hundreds if not thousands of images and/or files is just not ideal.

How can I filter the Media browser to only show the files that user uploaded?

# Answer
> 1 votes
That should be quite straightforward to set up:

1. Add a contextual filter to the View which powers the Entity Browser
2. Choose "Authored by" as the field
3. Under *When the filter value is not available*, choose *Provide default value*
4. In that dropdown, select *User ID from logged in user*

---
Tags: media, 9
---


title: Link in URL field to Media File

text:
# Question
Title: Link in URL field to Media File
Before the Update to the latest DruPal 8, we were able to link to `public://foo/bar.pdf` to a file which was in `/sites/default/files/`. No the `public://` prefix does not work anymore in the URL input field.

We are still able to enter the full link, but this might have the downside that it needs to be updated when the file name changes.

We also tried `/media/1337` but it shows a new page with the download link, while we need a direct download.

Can this still be accomplished?

# Answer
> 2 votes
I think that the issue is that `public://` is a PHP file stream wrapper defined by Drupal, which is a PHP language feature, and is not a URL, which is a publicly defined standard. The field is specifically requesting a URL.

The url `/sites/default/files/<file name>` should wok. Relative URLs are considered best practice.

The issue of changing file names is separate from the topic of file stream wrappers and URLs. A common method for mitigating this issue is to use the Pathauto module.

---
Tags: 8, media
---


# Question
Title: Programmatically create result row in views
I have created a bunch of content types. Since I am using Drupal only for displaying results fetched from another service I was wondering if there is a way to display results in a view without actually having objects in the database?

For example, I get data from a certain endpoint and I want to display them in a table view. Is there a way to achieve that or would another approach be recommended?

# Answer
The short answer is No. Views is only capable of returning Content entities.

The approach I recommend is to use Feeds to import your data into custom entities. You can either define your own custom content entity, or use ECK to define a custom content entity via UI.

In our organization, we use this basic Feeds -\> ECK -\> Views approach all the time and it has the benefit of not requiring our support staff to know any PHP. You might also find the Ultimate Cron module to be useful if you need to retrieve data at a frequency shorter than one hour.
> 0 votes

---
Tags: views
---


# Question
Title: View only your own comments, no one else's?
I have a client who would like users to be able to comment on content without being able to see any other users' comments. This is for a review system where users shouldn't feel influenced by the views of other users. I'm using Drupal 9.3.14 and a subtheme of Radix.

I have tried adding this to my theme's comment.html.twig:

```
{% if author_id == user.id %}
    {{ content }}
{% endif %}

```

That works for a while, but after a while, users report that they can see *some* other users' comments, but not all of them.

How can I make sure that users can always see only their own comments and no one else's?

# Answer
> 1 votes
Finding `hook_ENTITY_TYPE_access`/`hook_comment_access` not working when trying to return `AccessResult::forbidden()->cachePerUser()` after comparing the comment owner ID and current user ID (probably related: #2879087), can you please try the following preprocess logic? As I currently have no project to properly check this out myself I'm not sure if it works that way and if `#plain_text` can simply be (mis-)used as a cache busting switch in a template at all.

```
/**
 * Implements hook_preprocess_HOOK().
 */
function MYMODULE_preprocess_comment(&$variables) {
  $variables['own_comment'] = [
    '#plain_text' => 'no',
    '#cache' => [
      'contexts' => ['user'],
    ],
  ];
  /** @var \Drupal\comment\Entity\Comment $comment */
  $comment = $variables['elements']['#comment'];
  if ($comment->getOwner()->id() === \Drupal::currentUser()->id()) {
    $variables['own_comment']['#plain_text'] = 'yes';
  }
}

```

```
{% if own_comment['#plain_text'] == 'yes' %}
  {{ content }}
{% else %}
  {{ 'Not your comment'|t }}
{% endif %}

```

Maybe I'm actually doing the same you did and in the end the only way is to implement your own comments field formatter, similar to the one in the Manage comments on own content module.

# Answer
> 0 votes
Sorry, no code with this, just an idea to try. Focus on writing a new permission with a custom module, not modifying the html that is cached. If you hook into Drupal's permissions, then the cache may not be an issue anymore. Plus, this feels more like a permission issue than html issue.

If you install drupal/console, you can run a command lines like `drupal generate:module` to stub out the initial module then `drupal generate:permissions` to addon to that module a permission. Quick way to stub out a custom module and then put similar php logic you already have in your head, but just add it to drupal a different way.

---
Tags: 9, comments
---


# Question
Title: Installing the dependencies of local modules without composer merge plugin
Currently I have a composer-based Drupal project with both third-party and custom modules. Third-party modules are managed by composer without any issues. But I would like my *custom* modules to declare their dependencies in a `composer.json` within their directories, and also have them install when I run `composer install` at the root of the project.

```
composer.json
web/
  modules/
    contrib/
      address/
      admin_toolbar/
      ...
    custom/
      my_module/
        composer.json
        ...
      my_other_module/
        composer.json

```

Currently:

* I have the composer merge plugin which works fine for the most part but would like to avoid using it. It has a nasty habit of calling `update` and bumping dependency versions when it shouldn't.
* I've already looked into Composer path repositories. While it does install the dependencies of my custom modules, it also symlinks/copies my custom module into `web/modules/contrib` which is unnecessary because the custom modules are already in the right place in `web/modules/custom`.

In the future, I would splinter off these custom modules into their own projects and stored in their own repositories. But for now, they're still housed in the same project as the Drupal site I'm building.

How do I install dependencies declared in the `composer.json` of my local custom modules together with everything else?

# Answer
> 1 votes
This what I have to make it work:

web/modules/custom/my\_custom/composer.json

```
{
    "name": "[provider]/my_custom",
    "type": "drupal-custom-module",
    "description": "My Custom Module.",
    "require": {
        "drupal/core": "^8.9 || ^9",
        "drupal/devel": "^2.1"
    },
    "minimum-stability": "dev",
    "repositories": [
        {
            "type": "composer",
            "url":  "https://packages.drupal.org/8"
        },
        {
            "type": "composer",
            "url": "https://asset-packagist.org"
        }
    ]
}

```

composer.json

```
{
...
  "repositories": [
    {
      "type": "path",
      "url": "web/modules/custom/my_custom"
    }
  ],
...
  "require": {
    ...
    "[provider]/my_custom": "*"
    ...
  },
  "extra": {
    "installer-paths": {
      ...
      "web/modules/custom/{$name}":   ["type:drupal-custom-module"],
      ...
    },
  }
...
}

```

---
Tags: 9, composer
---


# Question
Title: How do I display the language settings (Site language field) on the user registration form?
I'm trying to display the user's language settings field on the registration page, but no success so far.

I've tried using a template (form--user-register-form.html.twig). This works for other fields, like mail, name, but I don't know how to access the language setting field.

I also tried form\_alter (both in the theme and module MODULE\_user\_register\_form\_alter), and set `$form['language']['#access'] = true;` This hook doesn't seem to work at all, nothing happens when I try to use it (print out variables for example).

# Answer
> 0 votes
This is an old question but there's a current issue opened on Drupal core for this here https://www.drupal.org/project/drupal/issues/3163758

---
Tags: 8, users
---


# Question
Title: How do I test a CKEditor 5 text format field with Behat/Mink?
Drupal 10 is switching from CKEditor 4 to 5.

So, I installed the experimental CKEditor 5 module and am attempting to update my Behat tests to use CKEditor 5.

I am using an @javascript test in Behat on CircleCI to check my Drupal 8 site.

The standard `I fill in "my field" with "value"` step fails for fields that use CKEditor. For example, for a long text field with the label **Question**, if I add a step:

`And I fill in "Question" with "Will this work?"`

Then I get the error: `Element not interactable`

As described in this question about CKEditor 4, there is a gist by johnennewdeeson that works for CKEditor 4 (which basically uses JS to find the editor instance and set the data), but it does not work for CKEditor 5 (`CKEDITOR is not defined` error).

So how can I set the value of a text format field in Behat using CKEditor 5?

# Answer
As described in How to get the editor instance object from the DOM element?, you can search for `ck-editor__editable` and use that to locate the specific editor instance that you need to manipulate.

The following is a working example. Note that you have to replaced any underscores with hyphens in the machine name for `$field_hyphenated_machine_name`.

```
  /**
   * Input text using CKEditor.
   *
   * @Then I fill in the wysiwyg field :field_hyphenated_machine_name with :value
   * @Then I enter :value for wysiwyg field :field_hyphenated_machine_name
   */
  public function iFillInWysiwygOnFieldWith($field_hyphenated_machine_name, $value) {
    # https://ckeditor.com/docs/ckeditor5/latest/support/faq.html#how-to-get-the-editor-instance-object-from-the-dom-element
    $ckeditor5_drupal_editable_element = "div.form-item-$field_hyphenated_machine_name-display-0-value .ck-editor__editable";

    $this->getSession()
      ->executeScript(
        "
        const domEditableElement = document.querySelector(\"$ckeditor5_drupal_editable_element\");
        if (domEditableElement.ckeditorInstance) {
          const editorInstance = domEditableElement.ckeditorInstance;
          if (editorInstance) {
            editorInstance.setData(\"$value\");
          } else {
            throw new Exception('Could not get the editor instance!');
          }
        } else {
          throw new Exception('Could not find the element!');
        }
        ");
  }

```
> 3 votes

---
Tags: testing, input-formats
---


title: Use path alias as contextual filter

text:
# Question
Title: Use path alias as contextual filter
I have nodes in Drupal for News Articles that generates this automatic URL alias.

>

I also have a view for *News* nodes.

>

This is the data.

>

The problem is that I can't use *Content: Path (url)* or *Content: Path (Path)* as contextual filter.

*sync/newslist/1234*, where 1234 is node ID, works. I would like to pass the path or the URL to the contextual filter, so that *sync/newslist/world-first-chart-alerts-non-artists* will return that node.

# Answer
> 4 votes
You can for example create a custom ViewsArgumentValidator and transform the given alias to the Node ID.

```
<?php

namespace Drupal\my_module\Plugin\views\argument_validator;

use Drupal\path_alias\AliasManagerInterface;
use Drupal\views\Plugin\views\argument_validator\ArgumentValidatorPluginBase;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Validates whether an alias is a valid node alias and transform it to the nid.
 *
 * @ViewsArgumentValidator(
 *   id = "node_alias",
 *   title = @Translation("Node ID by alias")
 * )
 */
class NodeAlias extends ArgumentValidatorPluginBase {

  /**
   * The alias manager.
   *
   * @var \Drupal\path_alias\AliasManagerInterface
   */
  protected $aliasManager;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, AliasManagerInterface $alias_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->aliasManager = $alias_manager;
  }

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

  /**
   * {@inheritdoc}
   */
  public function validateArgument($argument) {
    // Prepend slash.
    $argument = '/' . ltrim($argument, '/');
    $path = $this->aliasManager->getPathByAlias($argument);

    if (preg_match('/node\/(\d+)/', $path, $matches)) {
      $this->argument->argument = $matches[1];
      return TRUE;
    }
    return FALSE;
  }

}

```

In the **validateArgument** function we are checking if an internal path for a node can be found with that alias and transform the given argument to the corresponding Node ID.

Add this file named **NodeAlias.php** to you custom module in **src/Plugin/views/argument\_validator** directory and clear the cache.

After that, you can use the **Content: Nid** contextual filter and select in the "When the filter value is in the URL or a default is provided" section the new Validator **Node ID by alias**.

---
Tags: views, nodes, path-aliases
---


title: How do I change a node ID?

text:
# Question
Title: How do I change a node ID?
I have a node whose ID is 548754. I need it to be 301.

Is there a safe way to do this? There are a lot of tables related to 548754.
What if I export the database, open the SQL file, replace the number, and then import the database. Will this work?

# Answer
A solution is using these two contrib modules:

They turn out to work together nicely. "Custom nid" only works for new nodes.. however "Quick node clone" takes you to an unsubmitted "new node" form... as such you can change the nid of the clone before saving it. After cloning you can throw away the original.
> 2 votes

---
Tags: nodes, database
---


# Question
Title: How to custom access for entity paragraphs_type?
I have a problem with entity paragraphs\_type, when I add a paragraphs\_type in a node, with paragraph items inside, and I set it unpublish status, anonymous users can still see it.  I try to custom access by different way :

```
/**
 * Implements hook_ENTITY_TYPE_access().
 * ENTITY_TYPE : paragraphs_type
 */
function my_module_paragraphs_type_access(
  Drupal\Core\Entity\EntityInterface $entity,
  $operation,
  \Drupal\Core\Session\AccountInterface $account
) {
  echo '<pre>';
  var_dump('my_module_paragraphs_type_access');
  var_dump($operation);
  var_dump($account);
  exit();
  //Hide paragraph for anonymous users if is not published
    if ($operation == 'view'
        && !$entity->isPublished()
        && ($account->isAnonymous() ||
        !$account->hasPermission('view unpublished paragraphs'))
      ) {
    return \Drupal\Core\Access\AccessResult::forbidden();
  }

  return \Drupal\Core\Access\AccessResult::allowed();
}

```

It's not work, `var_dump('my_module_paragraphs_type_access');` it's never executed

Or a custom class that extends ParagraphsTypeAccessControlHandler :

```
<?php

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\paragraphs\ParagraphsTypeAccessControlHandler;

/*
 * Add custom paragraphs_type access
 */
class CustomParagraphsTypeAccessControlHandler extends ParagraphsTypeAccessControlHandler {

  /**
   * {@inheritdoc}
   */
  protected function checkAccess(EntityInterface $entity, $operation, AccountInterface $account) {
    switch ($operation) {
      case 'view unpublished paragraphs':
        if($account->isAnonymous())
          return AccessResult::forbidden();
        break;
      case 'view label':
        return AccessResult::allowedIfHasPermission($account, 'access content');
      default:
        return parent::checkAccess($entity, $operation, $account);
    }
  }
}

```

but still the same... Another plan to hide them to anonymous users ?

I found an this issue :https://www.drupal.org/project/paragraphs/issues/3095959#comment-13363535

# Answer
I found the problem, the paragraph is render programmatically with hook\_preprocess\_node, I fix it with checking access like that :

```
function mymodule_preprocess_node__my_node(&$variables) {

  $node = $variables['node'];

  $paragraphs = $node->get('field_para_blocks');

  /** @var \Drupal\paragraphs\Entity\Paragraph $paragraph */
  foreach ($paragraphs->referencedEntities() as $paragraph) {

    $bundle = $paragraph->bundle();

    if ($paragraph->access('view')) {
      $bundle = $paragraph->bundle();
      $variables[$bundle] = \Drupal::entityTypeManager()
        ->getViewBuilder('paragraph')
        ->view($paragraph, 'my_paragraph_type');
    }
  }

```
> 0 votes

---
Tags: 9, paragraphs
---


# Question
Title: How can I filter multiple node IDs at the same time using exposed filters?
I have an view with an exposed filer for node IDs, which seems to only accept a single value.

Is there a way to filter nodes giving more than a node ID? I tried `1 and 2`, `1,2`, and `1 2`, but they didn't work.

# Answer
I don't think this can be done using only the Views module.

You must create a custom module that implements `hook_views_query_alter()`. (The code is for Drupal 7.)

```
function my_module_views_query_alter(&$view, &$query) {
  if ($view->current_display == 'my_current_display' && $view->exposed_raw_input['nid']) {
    $nids = explode(',', $view->exposed_raw_input['nid']);

    foreach ($nids as $nid) {
      $query->where[1]['conditions'][] = array(
        'field' => 'node.nid',
        'value' => $nid,
        'operator' => '!=',
      );
    }
  }
}

```

I found this solution on How to Pass Multiple Values through an Exposed Filter in Drupal Views. Credits go to Peter Schuelke, who wrote that article on October 17, 2012.
> 0 votes

# Answer
In views context filter settings is a section where you can enable multiple value splitting, e.g.: 1+2+3 (for OR) or 1,2,3 (for AND)
> 0 votes

---
Tags: 6, views
---


title: Add an event listener to select list

text:
# Question
Title: Add an event listener to select list
I've attached the following js to an exposed views form field and it works on first page load but when the form is changed (by ajax) it doesn't fire.

I can't quite work out where to add an event listener for onchange of the select list.

The following doesn't use jQuery but uses the core once library so I would like to avoid jQuery.

```
/**
 * @file
 * Landing page adjustments.
 */

 (function (Drupal, once) {
    'use strict';

    /**
     * Attached behavior for Custom DataLayer.
     *
     * @type {{attach: Drupal.behaviors.CurrentSelectOption.attach}}
     */
    Drupal.behaviors.CurrentSelectOption = {
      attach: function attach(context) {
        // First page load
        let elements = once('CurrentSelectOption', 'select#edit-field-event-country.form-select', context);
        elements.forEach(processingCallback);
      }
    };

    function processingCallback(value, index) {
      let option = value.options[value.selectedIndex]
      value.remove (option);
      value.add (option, 0);
    }

})(Drupal, once);

```

# Answer
> 0 votes
When an AJAX call is made through the Drupal API, behaviours are re-attached. So if the API is in use, the answer is simply to put the code inside the `attach` method in your behavior, where you already have it.

The twist is: don’t use IDs to target elements. This is a general best practice rule for CSS/JS DOM selection, but especially important here, as Drupal will generate a new ID for the form element it replaces. If you inspect the select and its wrapper after the AJAX call, you’ll see `-2` appended to the original ID.

Other than that (without a test) your code looks fine.

---
Tags: javascript, ajax
---


# Question
Title: How do I apply the `loading="lazy"` attribute to responsive media?
On my Drupal 9 installation when I create an "image" field, Drupal automatically adds the `loading="lazy"` attribute.

When I create a "media" field with an "Adaptive Image Styles" display, the `loading="lazy"` attribute is not applied.

How to apply the `loading="lazy"` attribute to responsive media?

If I go to a media image, there is "lazy" :

If I go to a media image with the adaptive image style, there is no "lazy" :

**UPDATED WITH cilefen REPLY**

I tested on Drupal 9.4 and it seems that the update does not fix the problem. `loading="lazy"` is unavailable for "Responsive image" :

While it is available for non-responsive image :

So I rest my question, how to apply `loading="lazy"` on the "Responsive image" ? This is a big problem for page performance.

# Answer
> 2 votes
This is an active area a research and development in Drupal Core. Although there is no quick fix, this issue is the locus of work. Test the patches and provide feedback.

---
Tags: media, 9, performance
---


title: Programmatically load node edit form

text:
# Question
Title: Programmatically load node edit form
I'm able to load node create forms like so

```
$node    = \Drupal\node\Entity\Node::create(['type' => 'avenue']);
$content = \Drupal::service('entity.form_builder')->getForm($node);

return $content;

```

However what if I want to load an edit form for a pre-existing node? I looked on this page https://api.drupal.org/api/drupal/core!modules!node!src!Entity!Node.php/class/Node/8.2.x but I can't find anything that would relate to the edit form. Is there a way to load the edit form for a specific node?

# Answer
> 4 votes
Yes, on the linked page you would find `Node::load()` to get a pre-existing node:

```
$node    = \Drupal\node\Entity\Node::load($nid);
$content = \Drupal::service('entity.form_builder')->getForm($node);

return $content;

```

# Answer
> 1 votes
In Controller -

```
if ($node) && !empty($node->id())) {
  $node = \Drupal\node\Entity\Node::load($node->id());
  $build = \Drupal::service('entity.form_builder')->getForm($node);
  return $build;
}
else {
  return $this->redirect('node.add', ['node_type' => 'CONTENT_TYPE']);
}

```

---
Tags: nodes, forms, 8
---


# Question
Title: Add a placeholder to search input text field
How can I add a placeholder for the input text of the search block (*Search on my website*)?

I've looked around, but on Drupal 8 template.php has been deprecated and it's not an option. I also need to translate the placeholder. Copy in red is what I want to do.

# Answer
> 3 votes
Thanks for your help @Kevin

So I edited my (MYTHEME).theme file and added that and it works:

```
function mytheme_form_search_block_form_alter(&$form, &$form_state) {
  $form['keys']['#attributes']['placeholder'][] = t('Search on my website');
}

```

---
Tags: search, 9
---


title: How can I hide a block from regions?

text:
# Question
Title: How can I hide a block from regions?
I successfully place block with twig\_teak module programmatically in my twig file. Unfortunately in order for this to work, it needs a region in the UI. How should I hide it from its original region? I'm placing it with code, so I don't want it showing up in any region, and disabling it removes it everywhere. Styling the unwanted one out on the front end is hopefully not the recommended solution here.

# Answer
Block configuration entities need a region, but not blocks in general. Twig Tweak can generate the block config on the fly and doesn't need them to be stored in the database:

```
{{ drupal_block('plugin_id', {label: 'Example'|t, some_setting: 'example', setting_array: {value: value}}) }}

```

If you don't know the plugin and the settings, configure a block in UI temporarily and export the YAML file (/admin/config/development/configuration/single/export). You find both near the end of the file.

https://git.drupalcode.org/project/twig\_tweak/-/blob/3.x/docs/blocks.md#block-plugin
> 3 votes

---
Tags: blocks, 9
---


title: Why Drupal is slow on WSL

text:
# Question
Title: Why Drupal is slow on WSL
Trying Drupal 9.3.15 on Ubuntu on Windows Subsystem for Linux (WSL). However it's very slow when browsing to `http://localhost/drupal9` and it timeout most of the times, **what could be the reason behind this slowness?**

1. Created directory for Drupal: `mkdir ~/projects/drupal9`
2. Download Drupal using composer: `composer create-project drupal/recommended-project ~/projects/drupal9`
3. Link my new project to `/var/www/drupal9`: `sudo ln -sT ~/projects/drupal9/web /var/www/drupal9`
4. Install Drupal using drush: `drush site:install`
5. Configure nginx:

```
server {
  listen 80 default_server;
  root /var/www;

  index index.php;

  location /drupal9 {
    try_files $uri $uri/ @rewrite;
  }

  location @rewrite {
    rewrite ^ /drupal9/index.php;
  }

  location ~ '\.php$|^/update.php' {
    fastcgi_split_path_info ^(.+?\.php)(|/.*)$;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param QUERY_STRING $query_string;
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
  }

```

# Answer
> 2 votes
Not exactly Drupal related, but nonetheless:

If you are on WSL1, upgrade to WSL2.

The reason for the slowness is WSL itself. There is a file performance IO penalty on Mac and Windows due to how virtualization works. The general advice especially on Windows is to do "all of your work" inside of Linux. Do not mount anything in from Windows. Second to that, make sure you are allocating enough RAM (like a minimum of 4GB) and storage resources to that virtual instance. Third, throw in memcache or redis so you arent using the database as a cache store.

---
Tags: 9
---


# Question
Title: attach an programmatically generated pdf file to a node
Im using PDF Using MPDF module to generate 4 files when a node is saved using its API function `pdf_using_mpdf_api`:

```
function MYMODULE_node_insert($node){
        // PDF generation :
        // Generate standard version
        $view = node_view($node, 'PDF');
        $html = drupal_render($view);
        pdf_using_mpdf_api($html, 'reference_'.$node->nid);

        // Generate short version
        $view = node_view($node, 'pdf_short');
        $html = drupal_render($view);
        pdf_using_mpdf_api($html, 'reference_'.$node->nid.'_short');

        // Generate Standard EN version
        $view = node_view($node, 'pdf_en');
        $html = drupal_render($view);
        pdf_using_mpdf_api($html, 'reference_'.$node->nid.'_en');

        // Generate short EN version
        $view = node_view($node, 'pdf_short_en');
        $html = drupal_render($view);
        pdf_using_mpdf_api($html, 'reference_'.$node->nid.'_short_en');
}

```

this code above generates 4 pdf files correctly and save them under `default/files/pdf_using_mpdf` directory. users should be able to download these PDFs, so I added 4 fields in my content type for each PDF version (field\_pdf1, field\_pdf2, field\_pdf3, field\_pdf4).

I want to attach these stored files into their corresponding fields inside private directory (after success, i'll remove them from default/files/pdf\_using\_mpdf directory).

Before Im used to use `field_attach_update` to attach fields to a node, but for file fields how can I do this ?

What should be the value of the field : `$node->field_pdf1['und'][0]['value']` ? and how can I store them into private directory ?

Thanks in advance.

# Answer
I didn't use PDF Using MPDF, so not sure what will be the file path for the PDFs got generated.

Anyway, these are general steps you need to perform for attaching files to a node.

* Create a file object representing our physical file
* Make it a managed file by calling `file_save()`
* Fill file field with file's properties and fill field's other properties like display and description
* Save the node to make attachment effective

You can utilize sample code below to get idea how to work on it.

```
<?php
// We have complete file path.
$file_path = '/whatever/path/to/file/sample.pdf';

$file = new stdClass;
$file->uid = $node->uid;
$file->filename = pathinfo($file_path, PATHINFO_BASENAME);
$file->uri = $file_path;
$file->filemime = file_get_mimetype($file_path);
// Make it permanent, otherwise it will get deleted later.
$file->status = FILE_STATUS_PERMANENT;

// Save file object to make it a 'managed file'.
file_save($file);

// We will save file under this location.
$destination = 'private://PDFs/';

// Make sure destination directory exists
//before moving files to that path.
// This will create directory if it does not exists.
file_prepare_directory($destination, FILE_CREATE_DIRECTORY);

// Now attach file to the file field.
$node->field_pdf[$node->language][0] = (array) $file;

// Default file type field comes with this extra properties.
$node->field_pdf[$node->language][0]['display'] = 1;
$node->field_pdf[$node->language][0]['description'] = 'Our special PDF';

// Save node to make the attachment effective.
node_save($node);

```

Apply correct file path and destination directory. Here is the post explaining it in detail: Programmatically Attach Files to Node in Drupal 7
> 2 votes

# Answer
If I'm reading your question correctly, you'll need to

* Move the generated PDFs to your private dir
* Save them into Drupal's file system
* Attach them to the `$node->field_pdfX` fields

See this post on how utilize the Drupal File API to save a file and attached it to a node field. All you'll need to do is substitute out the `public://` prefix with `private://` and reference the correct paths & field names.
> 1 votes

# Answer
I use FPDF module library to generate a PDF file object, this library is beautifull and very easy to learn, allows you to control perfect what your pdf will look, as you can see i use variable\_get, set & delete, its because in library header and footer funtcions is hard to pass variables as parameters, i define them in a form, and set values on submit, here is last lines of code that does the magic:

```
$pdf->Close();
$nombre_paciente = variable_get('paciente').'.pdf';
$np = trim($nombre_paciente);
$np = str_replace(' ', '-', strtolower($np));

$data = $pdf->Output($np,'S');
$destination = 'public://users/files/'. $pdf_node->uid . '/'.  $pdf_node->nid . '/'. $idioma;
file_prepare_directory($destination, FILE_CREATE_DIRECTORY);
// what to do when the destination file already exists
$replace = FILE_EXISTS_REPLACE;
$my_file_obj = file_save_data($data, $destination .'/'. $np, $replace);
// above code saves file to server
// set node file field data
$pdf_node->field_resultado_pdf[$pdf_node->language][0] = (array) $my_file_obj;
$pdf_node->field_resultado_pdf[$pdf_node->language][0]['display'] = 1;
$pdf_node->field_resultado_pdf[$pdf_node->language][0]['description'] = 'Resultado';

node_save($pdf_node);

variable_del('idioma');
variable_del('paciente');
$pdf->Output('D', $np, true);
exit();

```

it calls twice pdf-\>Output(), one to save file and attached to node, second to display or download PDF file, this beheaivor depends on browers, chrome downloads the file, mozilla displays it in a new tab and downlods it. My answer is based part in @Junaid answer.

```
$y = $pdf->GetY();
if($y > $page_brake){$pdf->AddPage('P', 'Letter');}

```
> 0 votes

---
Tags: 7, entities, files
---


# Question
Title: How can I use a text editor on a page summary field?
In Drupal 7 I have the WYSIWYG module installed which provides a configuration setting "Enable on summary fields" to allow the HTML editor to be used on summary fields.

The WYSIWYG module is not available on Drupal 9. Is there a way to configure Drupal 9 to use an HTML editor (CKEditor or something else) to edit summary fields?

I have searched for solutions and I don't want to create a new, separate "summary" field. Drupal already has a summary field that I am already using.

# Answer
> 1 votes
Not yet. This is an active locus of work in Drupal Core.

---
Tags: 9, wysiwyg
---


# Question
Title: Generate a Media entity from a remote URL?
I want to create embeddeable "media" similar to how embedding YouTube or Vimeo videos work. When a URL is pasted in, I want to store this as a media entity (its own type) and then render it out with an oEmbed formatter (it has an iframe tag and attached JS library). This way, adding them for editors is easy and later re-usable for embedding as media objects. Where do I look in the Media system to support this? (note - its not images or video)

# Answer
If it supports oEmbed you can use `OEmbed` Source plugin similar to below.

https://git.drupalcode.org/sandbox/Bhanu951-3225164/-/blob/1.x/src/Plugin/media/Source/TikTok.php

If it doesn't support oEmbed you can create your own media source plugin extending `MediaSourceBase` class similar to below.

https://git.drupalcode.org/project/media\_entity\_slideshow/-/blob/8.x-2.x/src/Plugin/media/Source/Slideshow.php

Edit 1 :

In order to store it as own media type you need to extended `oEmbed` class and define `providers` key to provide oEmbed source. All the additional metadata will be handled by `oEmbed` class.

You can alter the source data by using `hook_media_source_info_alter` refer https://git.drupalcode.org/sandbox/Bhanu951-3225164/-/blob/1.x/media\_entity\_tiktok.module#L11
> 2 votes

---
Tags: media, 9
---


# Question
Title: How to alter output of markup on a specific views field
Is there a way to change the output programatically on a specific field in d8 views?

I have a field called 'IMCID' which I want to output as a link, but the link is going to change based on the value of another field for that row.

For example, if IMCID of row #1 is 15, and Format of row #1 is 'Copy', then I want the output URL to be something like `example.com/copy/15`, however if IMCID of row #1 is 15, and Format is 'Hard Copy', then the output URL would be `example.com/hardcopy/15`

If possible, I would like to avoid making multiple template files for individual fields, as this functionality will be carried over onto other fields later on, and would rather not have to manage a ton of template files.

I have tried using `hook_pre_render()` and `hook_post_render()`, but the markup doesn't appear to be in this hook so I am not sure how to update the link URL.

# Answer
Views is mainly a UI tool, also for theming. Check this box in the field:

> REWRITE RESULTS
>
> \[x\] Override the output of this field with custom text

This opens a text box which accepts Twig code and field tokens of other fields which are placed above. Exclude those fields from display if you want to us them only in Twig. You can check the available tokens in REPLACEMENTS PATTERN below the text box. Look in REPLACEMENT PATTERNS for raw field values, don't use formatted output in Twig logic.
> 0 votes

# Answer
To anyone experiencing a similar situation, you can have a look at: https://drupal.stackexchange.com/a/264191/106121 For Global Text Fields in Views (nothing) using **HOOK\_views\_pre\_render(\Drupal\views\ViewExecutable $view) {}**

Or,

use **THEME\_preprocess\_views\_view\_field(&$vars) {}** which can affect a particular view raw in the View Results https://api.drupal.org/api/drupal/core%21modules%21views%21views.theme.inc/function/template\_preprocess\_views\_view\_field/8.2.x

**Update:**

You can also utilize the **Views Conditional Module** \[ https://www.drupal.org/project/views\_conditional \] to add display conditions to different view fields individually while discarding the use of Global Text. Views Conditional is a good alternative.

This article can give you an outline of its implementation on an existing or new view: https://www.webwash.net/conditionally-display-view-fields-using-views-conditional-in-drupal/
> 0 votes

---
Tags: 8, views
---


# Question
Title: Generate Link based on custom content field types
I am using Drupal 8.9.8 and I have created a custom content type with field types such as plain text, number (integer), and so on. Then, I created Content based on the custom content types and filled in the field values. This generated a /node/2 page.

I want to combine the field values from the custom content type and generate a URL link that will be displayed in the /node/2.

The generated URL will be in the following format based on the content type field values which are set as default values of the below:

field\_url = https:/www.example.com?SIG=

field\_id = 94ddkf03la1

https:/www.example.com?SIG=94ddkf03la1

I have created successfully a module that generates a URL link with .php and .yml accessible from localhost/drupal8/modulename.

I want to accomplish the same functionality, but fetching the values from the custom content type fields.

Where this source code should be placed? Inside modulename.module?

Here is a screenshot of the structure of the custom content type.

I search through the Internet and StackExchange, but I could not figure out or combine the solutions presented.

Please forgive me if the terminology is misleading as I am new to this and I am trying to learn.

# Answer
> 0 votes
Sorry for the late response but, haven't able to find myself some time to elaborate a good sample that may serve you as copy/paste answer.

Said that, first of all you need to register your extra field. Since you are trying to *generate a link* I think `generated_link` is a good name for this extra field.

```
/**
 * Implements hook_entity_extra_field_info().
 */
function mymodule_entity_extra_field_info() {
  return [
    // the entity-type you want the field, assuming node.
    'node' => [
      // the node-type you want the field, put your actual bundle here.
      'mybundle' => [
        // where the field should appear, can be form or display.
        'display' => [
          // the actual field.
          'generated_link' => [
            'label' => t('Generated link'),
            'description' => t('Add some comment here to describe your field.'),
            'weight' => 100,
            'visible' => TRUE,
          ],
        ],
      ],
    ],
  ];
}

```

This only places the extra field on the entity view display, now you need to provide the actual output for the field.

```
/**
 * Implements hook_ENTITY_TYPE_view().
 */
function mymodule_node_view(array &$build,
  \Drupal\Core\Entity\EntityInterface $entity,
  \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display,
  $view_mode) {
  // only do the extra work if the component is configured to be displayed.
  // this assumes a 'generated_link' extra field has been defined for the
  // entity bundle in hook_entity_extra_field_info().
  if ($entity->bundle() === 'mybundle'
    && $display->getComponent('generated_link')) {
    $build['generated_link'] = [
      // you need to implement the mymodule_generated_link_uri function to build the URI there.
      '#url' => \Drupal\Core\Url::fromUri(mymodule_generated_link_uri($entity)),
      '#type' => 'link',
    ];
  }
}

```

At this point, clear the cache, go to your node bundle view display setting and you will see the extra field there. Just drag it around to put it where you want it, and go to the node page to see it working.

Other way to get this done, is by using either Display Suite module with it's markup fields or the EFS module, both provide a no-code, full UI solution but you need to rely on tokens to get it done.

Finally, as @cilefen said on comments, using Drupal 8 at this time is not recommended and you should upgrade as soon as possible, since the longer you take to upgrade, more painful and effort consuming will be. Also on Drupal 9.3+ you can leverage the bundle classes feature, which is perfect for this use case.

---
Tags: 8, entities, hooks
---


# Question
Title: Use #state with taxonomy reference field (multiple terms)
If we add a “taxonomy” reference field, we have a field in the form that lists the terms. If I dump `$form`, I get for this field:

```
field_zone" => array:7 [▼
    "#type" => "container"
    "#parents" => array:1 [▶]
    "#attributes" => array:1 [▶]
    "widget" => array:15 [▼
      "#title" => "Zone"
      "#description" => ""
      "#field_parents" => []
      "#required" => false
      "#delta" => 0
      "#weight" => 0
      "#element_validate" => array:1 [▶]
      "#key_column" => "target_id"
      "#type" => "checkboxes"
      "#default_value" => []
      "#options" => array:12 [▼
        433 => Drupal\Core\Field\FieldFilteredMarkup {#6483 ▼
          #string: "Asie-Pacifique"
        }
        434 => Drupal\Core\Field\FieldFilteredMarkup {#6580 ▼
          #string: "-Asie de l’Est"
        }
        10 => Drupal\Core\Field\FieldFilteredMarkup {#6703 ▼
          #string: "Afrique"
        }
        11 => Drupal\Core\Field\FieldFilteredMarkup {#6704 ▼
          #string: "-Afrique de l’Ouest"
        }
        12 => Drupal\Core\Field\FieldFilteredMarkup {#6705 ▼
          #string: "-Afrique Centrale"
        }
        13 => Drupal\Core\Field\FieldFilteredMarkup {#6706 ▶}
        14 => Drupal\Core\Field\FieldFilteredMarkup {#6707 ▶}
        15 => Drupal\Core\Field\FieldFilteredMarkup {#6708 ▶}
        16 => Drupal\Core\Field\FieldFilteredMarkup {#6709 ▶}
        17 => Drupal\Core\Field\FieldFilteredMarkup {#6710 ▶}
        18 => Drupal\Core\Field\FieldFilteredMarkup {#6711 ▶}
        19 => Drupal\Core\Field\FieldFilteredMarkup {#6712 ▶}
      ]
      "#after_build" => array:1 [▶]
      "#field_name" => "field_zone_expertise"
      "#parents" => array:1 [▶]
      "#tree" => true
    ]

```

We can therefore see that the field is of the container type and that each taxonomy term is an option. In front, it appears as checkboxes.

Is it possible to use `#states` with these options? I have tried many things without success.

I know how to do it with a single field but not with this multiple field. I would like when we check on the parent term that the child terms are checked.

I tried to do it with custom JS but I encounter problems when I add the “checked” attribute :

```
$('#edit-field-zone-11').attr('checked', true);

```

It works but not always well because Drupal doesn't use this attribute.

# Answer
> 0 votes
Form `#states` API only works good with plain, native HTML inputs (all kind of text inputs, radios, checkboxes and select). So if you use checkboxes/radios or select as input widget for your taxonomy, it should work as expected. It does not really work well with Javascript widgets like tag-style taxonomy input, select2 or chosen

Background:

Basically form states API is just client-side javascript, that uses CSS selectors to check and set the state of the dependent fields. If the form widget heavily modifies the HTML structure in the browser (like the tag-style taxonomy widget), then the selectors from states API will no longer match with the rendered HTML/CSS in the browser and the states API will not trigger.

States that operate on the field's parenting div-container (visible/hidden) might still work even with JS widgets, states working with/compairing values will most likely fail due the manipulated HTML structure generated by the JS widget.

---
Tags: forms
---


# Question
Title: Drush emu throws error without hook_uninstall firing
I have a module that creates a custom entity. In the module.install file, in hook\_uninstall, I remove any entity records.

Running drush pmu results in an error because there are entity records. It turns out that the hook\_uninstall, which deletes the records along with performing other cleanup, is not firing before the error is thrown.

```
Drupal\Core\Extension\ModuleUninstallValidatorException: The following reasons prevent the modules from being uninstalled: There[error]
is content for the entity type: My Entities. <a href="/admin/modules/uninstall/entity/my_module">Remove my_entities
entities</a>. in /var/www/web/core/lib/Drupal/Core/Extension/ModuleInstaller.php:437
Stack trace:
#0 /var/www/web/core/lib/Drupal/Core/ProxyClass/Extension/ModuleInstaller.php(91):
Drupal\Core\Extension\ModuleInstaller->uninstall(Array, true)
#1 phar:///usr/local/bin/drush8/commands/core/drupal/environment_common.inc(187):
Drupal\Core\ProxyClass\Extension\ModuleInstaller->uninstall(Array)
#2 phar:///usr/local/bin/drush8/commands/core/drupal/pm.inc(79): drush_module_uninstall(Array)
#3 phar:///usr/local/bin/drush8/commands/pm/pm.drush.inc(1265): _drush_pm_uninstall(Array)
#4 phar:///usr/local/bin/drush8/includes/command.inc(422): drush_pm_uninstall(my_module')
#5 phar:///usr/local/bin/drush8/includes/command.inc(231): _drush_invoke_hooks(Array, Array)
#6 phar:///usr/local/bin/drush8/includes/command.inc(199): drush_command('my_module')
#7 phar:///usr/local/bin/drush8/lib/Drush/Boot/BaseBoot.php(67): drush_dispatch(Array)
#8 phar:///usr/local/bin/drush8/includes/preflight.inc(67): Drush\Boot\BaseBoot->bootstrap_and_dispatch()
#9 phar:///usr/local/bin/drush8/includes/startup.inc(465): drush_main()
#10 phar:///usr/local/bin/drush8/includes/startup.inc(369): drush_run_main(false, '/', 'Phar detected. ...')
#11 phar:///usr/local/bin/drush8/drush(114): drush_startup(Array)
#12 /usr/local/bin/drush8(10): require('phar:///usr/loc...')
#13 {main}

```

# Answer
> 2 votes
You need to manually delete the entities. Drupal will not allow you to have it as part of the uninstall, as that could delete user content without prompt, which would be a disaster. As far as I know, there is no way around this, as hook\_uninstall() will be called after the pre-check to see if there is any content in the database.

For better UX, I usually create both a drush command that deletes my content entities, then an admin page that does the same thing. This way users can easily delete the content then uninstall the module.

---
Tags: entities
---


# Question
Title: How do I copy an address onto an entity?
This use case involves copying an address from CiviCRM into a field on a commerce product.

1. Create a product

Based on an event trigger

```
protected function createProduct(EntityInterface $group) {
  $user = User::load($this->currentUser->id());
  $user_hash = $user->uuid();
  $sku = $this->getMachineName($group->get('label')
    ->getString()) . '_' .  $user_hash;

  $variation = ProductVariation::create([
    'type' => 'basic',
    'sku' => $sku,
    'price' => new Price('10.00', 'GBP'),
  ]);
  $variation->save();

  $product = Product::create([
    'type' => 'basic',
    'title' => t($group->get('label')->getString()),
    'variations' => [$variation],
  ]);
  $this->setAddress($product);
  $product->save();
}

```

However, setAddress() is the challenge

```
 protected function setProductAddress($civiCrmAddress, $contact, EntityInterface $product) {
   $addressList = $product->get('field_address');

```

Which provides an AddressFieldItemList. How do I create an AddressItem field?

Not like this: `$address = AddressItem::createInstance($addressDefinition);`

as I can't find $addressDefinition (ComplexDataDefinitionInterface)

Just create an array $address = \['country\_code' =\> 'US\]; ?

# Answer
> 1 votes
Yes, just create such an array $address and set it:

```
$product->set('field_adress', $address);

```

---
Tags: entities
---


# Question
Title: How do I use hook_preprocess_views_view_unformatted()?
I'm trying to use `hook_preprocess_views_view_unformatted()` on a Drupal 9 website. I tried to put very simple command into the function in mytheme.theme and in a custom module; unfortunately it didn't show any *test* output.

```
function mytheme_preprocess_views_view_unformatted(&$variables) {
  kint('test');
}

```

`kint()` works in `hook_preprocess_views_view()`, but I really need to use `hook_preprocess_views_view_unformatted()`.

I thought this is taking place because of some bugs in the core such as Specific preprocess functions for theme hook suggestions are not invoked, but that one is closed as fixed.

Does this preprocess function work at all?

# Answer
> -2 votes
Pass the object into the `$variables` array, and then in one of the Twig templates issue `{{ kint(var) }}`. Drupal might be using output buffering there, which would explain why you don't see any output when issuing those calls from the preprocess function.

---
Tags: views, 9
---


title: Watchdog table growing out of control

text:
# Question
Title: Watchdog table growing out of control
I have seen similar questions to this before but they do not solve my problem. This is Drupal 8.

Today the watchdog table on one of our sites exploded to 12GB in size. No other table in the DB is above a few dozen MBs if that.

Logging was only set to record the last 1000 events. I then turned even that down to 100 and ran cron a few times.

It dropped back down to 1GB... then up to 5.9GB in about 30min. When I try to inspect it with `brush wd-show --count=1000` or something like that it only shows about 100 entries.

What is all the size coming from?

Additionally, the mysql database is still showing a disk as reported by `du` of 12GB...

I've also tried flushing and clearing the cache query in mysql and restarting mysql.

I only have 20GB of space on this server and it is not a very big site, what is going on and how can I stop it? If this goes on it will crash the site.

I was messing around with a view that used a contextual filter to a taxonomy term name with multiple values. Ok, I could see that using up some cache or throwing some errors... but 12GB!

EDIT: Ok the size on disk after deletion can be fixed by Optimizing the table: `OPTIMIZE TABLE sitedb.watchdog`. However, I still would like to know if there is someway to stop watchdog growing out of control this way? I had already limited the entries so I do not understand how it could get so big...

# Answer
As mentioned by Clive you need to reclaim the diskspace, however when I had a similar issue in the past `OPTIMIZE` was too slow and crashed the site.

According to the MariaDB knowledge base it should be possible to run the following commands:

```
CREATE TABLE watchdog_new LIKE watchdog;
INSERT INTO watchdog_new SELECT * FROM watchdog;  -- This could take a long time
RENAME TABLE watchdog TO watchdog_old, watchdog_new TO watchdog;   -- Atomic swap
DROP TABLE watchdog_old;   -- Space freed up here

```

This ran pretty quickly and didn't cause any major problems to the site
> 1 votes

---
Tags: views, 8
---


title: Broken Image styles don't generate

text:
# Question
Title: Broken Image styles don't generate
1. I am on Drupal 9.3
2. Set the Private file system path in `settings.php` file `$settings['file_private_path'] = '../private';`
3. Create a folder name outside the `"web"` folder named `"private"`
4. While uploading an image the original image is getting saved to the "private" folder but Image styles not getting generated, that is broken.
5. Attached is the screenshot image field.

Thanks

# Answer
I was using the "convert" effect on all image styles on my website which has an issue in Drupal 9. This patch fixed the issue for me.
> 1 votes

---
Tags: media, 9
---


# Question
Title: First checkbox is always checked in config form
I'm making config form with checkboxes and I'm always getting first checkbox checked. But in Kint debug it is not checked:

Here is part of my code:

```
$user_roles = $this->entityTypeManager->getStorage('user_role')->loadMultiple();
$user_roles_indexed_array = [];
foreach ($user_roles as $user_role) {
  $user_roles_indexed_array[] = $user_role->label();
}
$form['restricted_user_roles_' . $content_type->id()] = [
  '#type' => 'checkboxes',
  '#options' => $user_roles_indexed_array,
  '#default_value' => $config->get('restricted_user_roles_' . $content_type->id()) ? $config->get('restricted_user_roles_' . $content_type->id()) : [],
];

```

What I'm doing wrong?

# Answer
I get solution here

This first part of code was wrong, it refers to default value:

```
        $form['restricted_user_roles_'.$content_type->id()] =
    [
      '#type' => 'checkboxes',
      '#options' => $user_roles_indexed_array,
      '#default_value' => $config->get('restricted_user_roles_'.$content_type->id()) ? $config->get('restricted_user_roles_'.$content_type->id()) : [],
    ];

```

I changed it to this:

```
      $form['restricted_user_roles_'.$content_type->id()] = [
    '#type' => 'checkboxes',
    '#options' => $user_roles_indexed_array,
    '#default_value' => $config->get('restricted_user_roles_'.$content_type->id()) ?? [],
  ];

```

Also, second part of my code was wrong, it refers to submit:

```
public function submitForm(array &$form, FormStateInterface $form_state)
{
$content_types = $this->entityTypeManager->getStorage('node_type')->loadMultiple();
foreach ($content_types as $content_type)
{
$this->config('ctarpr.settings')
->set('content_type_'.$content_type->label(), $form_state->getValue('content_type_'.$content_type->label()))
->set('restricted_user_roles_'.$content_type->label(), $form_state->getValue('restricted_user_roles_'.$content_type->label()))
->set('page_redirection_'.$content_type->label(), $form_state->getValue('page_redirection_'.$content_type->label()))
->save();
}
parent::submitForm($form, $form_state);
}

```

I changed it to this:

```
   public function submitForm(array &$form, FormStateInterface $form_state)
  {
$content_types = $this->entityTypeManager->getStorage('node_type')->loadMultiple();

foreach ($content_types as $content_type) {
  $this->config('ctarpr.settings')->set('content_type_'.$content_type->id(), $form_state->getValue('content_type_'.$content_type->id()));
  $this->config('ctarpr.settings')->set('page_redirection_'.$content_type->id(), $form_state->getValue('page_redirection_'.$content_type->id()));
  // Create the array of indexes of selected items (checked checkboxes).
  $restricted_roles = $form_state->getValue('restricted_user_roles_'.$content_type->id());
  $restricted_roles = array_values($restricted_roles);
  foreach (array_keys($restricted_roles, 0, true) as $key) {
    unset($restricted_roles[$key]);
  }

  $this->config('ctarpr.settings')->set('restricted_user_roles_'.$content_type->id(), $restricted_roles);
  $this->config('ctarpr.settings')->save();
}
parent::submitForm($form, $form_state);
}

```
> 0 votes

---
Tags: forms, 9
---


# Question
Title: How can I import the configuration on a different site?
I have this error when I try to import the config of an another site:

> The staged configuration cannot be imported, because it originates from a different site than this site. You can only synchronize configuration between cloned instances of this site.

I have 10 customers, and I need to sync my site configuration with 10 different websites.
The site UUID is a problem for sharing a configuration with a different website. Is there a solution?

# Answer
> 19 votes
## Using Drupal Console

You can override your current site's UUID with the value present in the configuration you want to import.

You can achieve this with Drupal Console by overriding the *uuid* key for *system.site*.

```
drupal config:override

```

Then enter *system.site* for the configuration name, *uuid* for the configuration, and the UUID value, when prompted for each of them.

# Answer
> 99 votes
Youu can get the UUID with `drush config-get "system.site" uuid`.
You can change it with `drush config-set "system.site" uuid [uuid]`.

# Answer
> 26 votes
The Configuration Management only allow sync configuration between same site or project to avoid issues importing configuration from site a.com to b.com, to accomplish this validation Drupal 8 generate a UUID for each site.

You cat get your current site UUID executing the following command:

```
drush cget system.site

```

The command above we will have a similar output to next listing:

```
uuid: 236fa77c-d83e-42de-8a03-03c574c00160
name: Drupal 8
mail: user@example.com
slogan: ''
page:
  403: ''
  404: ''
  front: node
admin_compact_mode: false
weight_select_max: 100
langcode: en

```

The config import has a different UUID, you can confirm the UUID with the following command

```
cat sites/default/config/staging/system.site.yml

```

For that reason you need to change the value of Site UUID using the following Drush command:

```
drush cedit system.site

```

The command above enable you to use your favorite text editor to set the same UUID present in staging config files.

```
cat sites/default/config/staging/system.site.yml

```

After change the UUID and change the permissions, if you visit again the page example.com/admin/config/development/configuration you will see all changes, deletions, renames, and additions.

source: http://enzolutions.com/articles/2014/08/27/understanding-configuration-management-in-drupal-8/

# Answer
> 11 votes
**You can get the site UUID without access to the site or database.**

If you don't have access to the original site/database, you can still sync from provided config files. The config will contain your site's UUID, so you need to set that first.

1. Find your config/sync directory: If it's moved, you can find where it was set in `settings.php`. Look for: `$config_directories['sync']`, which will list the path.
2. Go to that config path, and look for the file: `system.site.yml` In that file, look for `uuid: 86b376c5-385e-4d13-bf00-e5e5443540e3` (you will have a different value, obviously). Copy that value.
3. In drush, set your site to the same site uuid that we just discovered: `drush cset system.site uuid 86b376c5-385e-4d13-bf00-e5e5443540e3`
4. Sync the config using drush `drush cim -y`
5. If you get errors, *read them*. I had:

* a missing module (which I had to download and enable)
    * content from the shortcuts module, which I had to delete first, at:
    * admin \> config \> User Interfact \> Shortcuts

Once I did that, I reran the cim, and everything worked like a charm!

I had installed a local D8 instance before trying to restore from the provided config.

# Answer
> 6 votes
You can change the UUID for the destination site using drush cset and drush cget.

First get the source UUID:

```
$ cd ~/Sites/sourcesite <-- your drupal site root
$ drush cget system.site uuid
This will return something like:
'system.site:uuid': 86b376c5-385e-4d13-bf00-e5e5443540e3

```

Replace the destination UUID

```
cd ~/Sites/destinationsite <-- your drupal site root
$ drush cset system.site uuid 86b376c5-385e-4d13-bf00-e5e5443540e3

```

Now you can:

1. Navigate to the destination site in your browser at admin/config/development/configuration/full/import
2. select the configuration archive and select upload
3. You will see a list of all the configuration items
4. Scroll down to the bottom and click the import all button

# Answer
> 2 votes
## How to automate the setting of the system.site uuid before config import

For people getting tired of doing this all over again. I finally got a fix on how to do this automatically. You would have to add a pre-command for config:import with drush to set the uuid. Read all about it here: https://stefvanlooveren.me/blog/fixing-systemsite-uuid-config-import-problem-drupal-8

# Answer
> 2 votes
Using the solution given by apaderno, I was able to import my config from another site which is an easy way to copy content types from a project to another for instance.

1. Copy UUID from another site. You can find it in system.site.yml or get it with

`drush config-get "system.site" uuid`
2. Change the UUID with

`drush config-set "system.site" uuid [uuid]`

Of course troubles are to be expected if you try this on sites using different versions of Drupal.

If anyone think this is a bad idea, please let me know why.

# Answer
> 0 votes
If you follow the instructions in Gucho Ca's answer, and still have the problem, be sure to check that you have write permissions in your sync config directory. It will give you this same error message, even if your uuids are the same, but your sytem doesn't have write permissions.

A good way to check is to click on the Import Tab of the Synchronize section. If you don't have the correct file permissions it will tell you there.

# Answer
> 0 votes
The Above answers used to work for me until Drupal 9.2.3, but they are no longer working on Drupal 9.2.4 and Drush 10.6.0.

I was able to fix this issue by applying the patch given in "Site UUID in source storage does not match the target storage." when importing a config with empty system.site UUID.

---
Tags: 8, configuration
---


# Question
Title: Remember the order facets where selected
The search API stores facets with a key and the URL is usually something like

`?f[0]="facet_0&f[1]="facet_1"&f[2]="facet_2"`

Unfortunately, this array is rebuilt on each page load and the order is not preserved. I need to know the order the user selected the facets.

I am thinking about trying to ensure this filter array preserves the order but I might have to instead add a new key called 'facet\_order' that does this if I can't modify the original filter key.

I have not been able to find a way to do either of these though. Is there a form alter or preprocess function that would allow me to change this behavior?

# Answer
> 0 votes
If anyone else ever needs to know how to do this here is how I got it to work. My URLs could become quite long if many filters are selected but I think that is okay for what I am doing.

I welcome any alternative recommendations or suggestions if you have any.

```
function my_theme_preprocess_facets_item_list__links(&$variables) {

  $ordered_key = 'fo';

  $facets_ordered = \Drupal::request()->query->get($ordered_key, []);

  foreach ($facet->getResults() as $facet_item) {
    $curr_url = $facet_item->getUrl();
    $curr_fo = $facets_ordered;
    $node_value = $facet_item->getRawValue();
    if($facet_item->isActive()) {
      if (($key = array_search($node_value, $curr_fo)) !== false) {
        // Remove this facet option from the current list
        unset($curr_fo[$key]);
        $curr_fo = array_values($curr_fo); // Reset the array values to be numerically sequential
      }
    } else {
      // Add the new filter the beginning of the ordered filter array so that the latest filter is always at pos 0
      array_unshift($curr_fo, $node_value);
    }
    $query_options = $curr_url->getOption('query');
    $query_options['fo'] = $curr_fo;
    $curr_url->setOption('query',$query_options);
  }
}

```

As a note, if you have sort filters then you will need to add this as a hidden form field like is done in the `search_api.module` in the function `search_api_form_views_exposed_form_alter` in the preserve filters if statement.

As an additional note, if you are using the facet summary module, you will also need to add a similar code snippet like above in `my_theme_preprocess_facets_summary_item_list`

I didn't need mine to work in Ajax and so I have not tested it with that.

---
Tags: search
---


# Question
Title: How to Auto Publish nodes based on set interval?
I have nodes being generated from a Feeds import on a periodic basis, however when they are imported I would like them to be queued to be published on an hourly basis (or x minutes)

I have looked at Scheduler and also Publish Queue. But those modules require input. I want this done automatically, so that as soon as nodes are created via feeds they are put into a queue to be published over a set interval of time.

How can I make this happen? Maybe I can just code this myself if there is no option out there. Something along those lines might work:

* Get oldest node unpublished node
* Publish node
* Run this code once every cron run

Any suggestions?

# Answer
> 0 votes
The Rules module is your friend. But if that's too much overhead and you don't need the flexibility, I would suggest coding it on your own.

Also see this question for executing rules on cron.

# Answer
> 0 votes
You could use a combination of the Views, Rules and Views Rules modules to get this to work. Some details about the Views Rules module (from its project page):

> Provides Views directly as Rules actions and loops to seamlessly use view result data.

If you're not familiar with Rules (yet), the previous quote may seem a bit cryptic (it may make you think like "so what, how can this help me?"). Therefor some more details about how to move forward using these modules:

1. Create a view (using Views) so that you have (at max) 1 Views result (row) for each of your nodes contained in your "*queue to be published*" (as in your question), whereas that view has just a few fields (columns) that you'll need later on to publish it (possibly only the node id is all you'd need). Important: use a Views display type of "Rules", which you can do if you have Views Rules enabled. Refer to my answer to "How to create a rule which after several updates in 5 minutes of a node sends 1 message?" for way more details about creating such Views display.
2. Create a custom rule in which you use the Views Rules module to iterate over each of these Views results in a Rules action, using the Rules technique known as a "Rules Loop". If you limit the Views result to only 1, this iteration is also limited to 1 of course (which is what you want).
3. For each iteration step in your Rules loop (there should only be 1 in your case ...), perform a Rules Action to simply publish the node being processed. At that point you'll have all data from each column of your Views results available as so called Rules Parameters. But in your case you probably only need the node's ID.
4. The only remaining thing is to decide about the Rules Event to use for this rule to be triggered. Obvious, in your case you should use Rules Event *Cron maintenance tasks are performed*.

With the above in place, the only thing left is to decide about the "*set interval*" (as in your question). For that, all that's needed is to review the scheduling of your cron jobs: each time cron runs, there will be 1 such node that gets published (provided there is one at least at the moment cron runs).

***Easy, no?***

# Answer
> 0 votes
You can check Scheduler & Scheduled Publish Module.

**Scheduler**

> Scheduler gives content editors the ability to schedule nodes to be published and unpublished at specified dates and times in the future.
>
> Dates can be entered either as plain text or with calendar popups. To use calendar popups in Drupal 7 you need to install the Date Popup module, which is part of the Date module. In Drupal 8 this is built into Core.

**Scheduled Publish**

This module contains a field type for nodes and medias to update the moderation state of some contents via a cronjob.

---
Tags: 7, nodes, feeds, importing-exporting
---