# Question
Title: Media Library: How can I pre-fill the caption when an image is inserted into a text area?
If I use Media Library to insert an image into a text area, the image's caption is empty and hidden.

Instead I want the caption displayed by default, pre-filled with text in the format: \[Image entity name\], by \[username\], eg '1960s street scene, by David'

(I'm migrating a site that uses D7 + the Scald module to D9 + core Media, and I want to replicate the old site's behaviour in the new site.)

Is there any way to customise Media Library's behaviour to do this?

If there isn't, then in D7 I'd ask for a new hook that will let me change what gets written into the text area when the user inserts an image. Is that still the right approach in D9?

# Answer
> 0 votes
I found a solution, and have written it up at: https://www.drupal.org/project/drupal/issues/3225834#comment-14341085

---
Tags: media
---


# Question
Title: Can you install exported site config as part of a kernel test?
I am using the Configuration Sync module to export config specific to my site out into a config directory that lives outside my main Drupal directory.

When writing kernel tests I know that you can use `$this->installConfig()` and specify a module(s) to install default config from, but how can I specify certain (or all) config files from that directory to be installed inside of a kernel test?

# Answer
> 1 votes
If you need to install some separately, determine which you would like to install together and place them in a new module together. Then you can install different combinations by specifying which modules to install.

---
Tags: configuration, 9, testing
---


title: Getting issue on views import?

text:
# Question
Title: Getting issue on views import?
Accidentally I have deleted the views relationship field. After that I am getting error when try to open views configuration page.

To fix the issue I have exported that view from site configuration single item and change in yml file. But when I import the changes getting below error.

> Configuration block.block.test\_local\_tasks depends on the test theme that will not be installed after import.

> Configuration block.block.test\_main\_menu depends on the test theme that will not be installed after import.

> Configuration block.block.test\_messages depends on the test theme that will not be installed after import.

> Configuration block.block.test\_powered depends on the test theme that will not be installed after import.

Please suggest.

# Answer
> 1 votes
Now I am able to fix it by deleting the old(not in use) block present in config table.

```
DELETE FROM config WHERE name IN ( 'block.block.batra_uae_local_tasks', 'block.block.batra_uae_main_menu', 'block.block.batra_uae_messages', 'block.block.batra_uae_powered' );

```

Get help from https://www.drupal.org/project/drupal/issues/2694895 page.

---
Tags: 8, views, importing-exporting
---


# Question
Title: How do I add fields and hide them from client?
I added fields to a Client profile using Profile2, such as first name and last name. But I added another fields, let's call it "Assigned Consultant".

But the "Assigned Consultant" field...

* I don't want it to be available on registration
* I don't want it to be available on the Client view user profile page
* I don't want it to be available on the Client edit user profile page

I just want the "Assigned Consultant" field to be available to Administrator users.

How can I do that?

# Answer
> 0 votes
Field permissions module would probably be the way. https://drupal.org/project/field\_permissions

"The Field Permissions module allows site administrators to set field-level permissions to edit, view and create fields on any entity."

Check the issue queue though, for example: https://drupal.org/node/2069281, "Profile2 field is empty after profile is saved"

# Answer
> 0 votes
To prevent display on the view user profile page, you should be able to field display options and move the field to hidden.

For the registration page, I'm sure there are some options in Profile2 to control if it appears on the registration page.

To hide it on the edit page for non-administrators, you can use the `#access` key on the form array.

You change this using hook\_form\_alter.

For example, in a custom module or your theme:

```
function my_module_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'id_of_the_edit_form') {
    // Get the user role.
    $roles = \Drupal::currentUser()->getRoles();

    // If the role does not include administrator.
    if(!in_array('administrator', $roles)) {
      // Set the field access to FALSE.
      $form['field_assigned_consultant']['#access'] = FALSE;
    }
  }
}

```

---
Tags: entities, users
---


# Question
Title: Programmatically get the results of a view
Using the group module in D8, I have the below view with machine name: `group_members_per_group`

**Machine Name of**:

* (Member account) User: Full Name is: `field_user_full_name`
* (Member account) User: Phone Number is: `field_user_phone_number`

**The above view has the below results:**

On cron run, and while Looping through all rows of the view results, I want to get `for each` row the `field_user_phone_number` value so I can use it with other code.

**So I wrote:**

```
function my_module_cron() {

// Get and loop through the View `group_members_per_group`
//$args = [$gid];
$view = \Drupal\views\Views::getView('group_members_per_group');
//$view->setArguments($args);
$view->setDisplay('default');
$view->execute();

// Get the results of the view.
$view_result = $view->result;

// Check if the view is not empty and return results.
if (!empty($view_result)) {

// If the view returns results...
foreach ($view->result as $row) {

// Get the full name value.
$name = $row->field_user_full_name;

// check the result output for testing only.
\Drupal::messenger()->addMessage(t($name));
  }
 }
}

```

However, on cron run, I am receiving the below error:

> Notice: Undefined property: Drupal\views\ResultRow::$field\_user\_full\_name in my\_module\_cron() (line 103 of modules\custom\my\_module\my\_module.module). my\_module\_cron(Object) call\_user\_func('my\_module\_cron', Object) (Line: 316) Drupal\ultimate\_cron\Entity\CronJob-\>invokeCallback() (Line: 459) Drupal\ultimate\_cron\Entity\CronJob-\>run(Object) (Line: 24) Drupal\ultimate\_cron\Controller\JobController-\>runCronJob(Object) call\_user\_func\_array(Array, Array) (Line: 123) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>Drupal\Core\EventSubscriber{closure}() (Line: 582) … …

Line 103 in the error is:

```
$name = $row->field_user_full_name;

```

# Answer
You can not get the value of field directly from row result.
You can get it by accessing to the entity like the following:
**Option1**

```
  foreach ($view->result as $id => $result) {
    $node = $result->_entity;
    // Get the full name value.
    $name = $node->get('field_user_full_name')->value;
    // check the result output for testing only.
    \Drupal::messenger()->addMessage(t($name));
  }

```

Or by loop through the fields like the following:
**Option2:**

```
foreach ($view->result as $id => $row) {
      foreach ($view->field as $fid => $field) {
        if ($fid == 'field_user_full_name') {
          //Get the full name value.
          $name = $field->getValue($row);
          // check the result output for testing only.
          \Drupal::messenger()->addMessage(t($name));
        }
      }
    }

```
> 7 votes

# Answer
In my case, the '$result-\>\_entity' was empty, so I had to get the value from the '$result-\>\_object' :

```
function YOUR_THEME_preprocess_views_view__YOUR_VIEW_ID(array &$variables): void {
  foreach ($variables['view']->result as $result) {
    $node = $result->_object->getEntity();
    $title = $node->get('title')->getValue()[0]['value'];
    $body = $node->get('body')->getValue()[0]['value'];
  }
}

```
> 4 votes

# Answer
I had to re-ask this question to be more clear here: How to get a rendered views field value programmatically?

@4k4 pointed me towards the right solution for getting a value from a field in a view:

```
foreach ($view->result as $rid => $row) {
  $type[$row->nid] = $view->field['my_views_field']->advancedRender($row)->__toString();
}

```
> 2 votes

---
Tags: views, 8, users, cron, group
---


# Question
Title: Is it bad practice to use the same hook twice?
I'm working a quite a big project and I use `hook_entity_update()` in three of my modules. I do this to keep my project structured and have different functions of my site in different modules.

* Is it bad performance wise to have this hook called multiple times from different modules?
* Since this way of working makes the number of custom modules grow, does the number of modules affect the performance of the site or is it only the code inside that can give performance issues?

# Answer
> 4 votes
Of course you would have to benchmark your modules to get an exact answer, but generally speaking, the benefits of breaking up complex code into multiple modules separated by function is the way to go.

The performance impact of calling the hook is minimal; the larger performance impact will be whatever code the hook runs.

The number of modules does not matter nearly as much as the code that the modules are running.

Evidence: Moving from Drupal 7 to Drupal 8/9, many major Drupal modules have gone from "minimize the number of modules" to "provide many more function-specific modules that can be enabled as needed":

* AdvAgg
* Commerce
* Metatag
* Webform

TLDR: The actual code that you run in hooks/modules is way more important for performance than the fact that you are calling hooks multiple times in modules.

However, one thing you have to keep aware of is that if you organize your modules poorly, you can end up adding custom code to the same hook in multiple modules that could result in bugs, such as if you are changing the same field in `hook_entity_update()`. So make sure you organize your code in a way that makes it clear which modules are responsible for which functions.

As a developer, it is definitely easier to maintain custom modules when they are separated by function, especially in the case that you end up having to use some but not all of the functions/modules on multiple sites.

# Answer
> 3 votes
The number of installed modules may influence performance. That's why, for example, Drupal core keeps in cache the name of the implemented hooks.
Given what Drupal core does, increasing the number of installed modules would have a lower impact on performance.

The aim for developers should not be reducing the number of modules/sub-modules, but writing modules that implement a specific feature. Clearly, if implementing a feature requires few lines, probably the module should be merged with another module, especially if that module is a sub-module.

To make an example, instead of the *Node* and *User* modules, there could be a single module (called, for example, *Base Content*). Since those modules are normally required from the installation profile, it would reduce the number of installed modules. It could also reduce the number of implemented hooks, since (for example) `node_user_predelete()` could be merged with a class method or another function.
Anyway, doing so, two modules with different purposes would be merged together; the hooks could be reduced, but in some cases the code could now need to first check some conditions are met; probably more services should be lazy-loaded, which means that there would be two classes instead of one (the proxy class and the class implementing the service). Those classes would need to be synchronized with each other: Any change on the service class needs to be done on the proxy class too. (There is a script for doing that, but it works only on installed modules, which means the developer would need a local server running Drupal and remember to run the script for every lazy-loaded service.)

It's not just a matter of implemented hooks: In Drupal 9, a module that is complex enough implements many classes, some of which are service or plugin implementations. Even modules that are simple enough to just need a single route implement code in at least a class.

---
Tags: hooks, 9
---


# Question
Title: Combine Aggregation with Pivot Table in Drupal Views
I have some views that use pivot tables. Their purpose is to display an attribute (for example, the gender) and a year value (for example, the birth year), using a third field named ID. The gender is used as pivot row and the birth year as pivot column. ID has the Aggregation type "Count". Additionally, we have a *Total* column for the row aggregate (*number of values* in Pivot settings) that counts how many people have a specific gender.

In this table, it's possible for a listed person to have an unknown year of birth. Therefore, I set the *No results behavior* for *Birth year* to *unknown*. That value is correctly shown as just another column.

Now I have a problem: Drupal doesn't count the row with *unknown* as birth year. It seems that it puts *1* inside the cell for *female* \+ *unknown* if there is one or more people with *female* as gender and *unknown* as birth year (no results behavior), but it doesn't count them.

Anyone has any hint on where I can determine how Drupal pivot tables work with No results behavior?

Edit @apaderno: In my opinion, this is not a request for documentation, but a question about a possible bug or at least bug-like behavior in the Drupal GUI. The phrasing "Anybody has any hint" may seem vague, but I had some positive experiences with that on other Stackexchange sites in the network, as it encouraged users to add their knowledge to the thread, even if it wasn't a complete answer to the question. I got some valuable hints this way in the past.

Edit2: When I change the Aggregation setting of the ID field to "Count Distinct", the No results behavior is counted correctly, but the row aggregate (as well as column aggregate) stops working correctly.

# Answer
It seems that this problem didn't occur only with *No Results Behavior* but with any value above 1 (being reduced to 1).

I solved the problem by adding the ID field as a Sort Criteria in the Drupal view. (The other fields stay without Aggregation, that is, the default value "Group Results By". In the Pivot settings, I kept the Row Aggregate of the ID field being "number of values".)

I have no idea how/why the Sort Criteria could possibly effect the counting results of the Pivot table, but they did.
> 0 votes

---
Tags: views
---


# Question
Title: Node form ajax dependent dropdown fields issue
I am using Drupal 9. I know how to change single dropdown list using another one. Here is my scenario:

I have three dropdowns, in node form - company, protocol and investigator. What I like to do, when some one select a value in company dropdown, other two dropdown list which change based on selection.

I have written some code, I see the list is updating but its not refreshing.

```
function hook_form_alter() {
    ....

    case 'node_tsr_form':
    case 'node_tsr_edit_form':
      $form['field_tsr_pi']['#prefix'] = '<div id="my-module-principal-investigator-wrapper">';
      $form['field_tsr_pi']['#suffix'] = '</div>';
      $form['field_protocol']['#prefix'] = '<div id="my-module-tsr-protocol-wrapper">';
      $form['field_protocol']['#suffix'] = '</div>';

      $form['field_company']['widget']['#ajax'] = [
        'callback' => 'my_module_ajax_callback_tsr_pi_and_protocol',
        'event' => 'change',
        'progress' => [
          'type' => 'throbber',
          'message' => t('loading ...'),
        ],
      ];
      $company_val = $form_state->getValue('field_company');
      if (isset($company_val[0]['target_id'])) {
        $company_id = $company_val[0]['target_id'];
      }

      if (!empty($company_id)) {
        $form['field_protocol']['widget']['#options'] = my_module_get_protocols($company_id);
        $form['field_pi']['widget']['#options'] = my_module_get_investigator($company_id);
      }
      else {
        $form['field_protocol']['widget']['#options'] = ['_none' => '- None -'];
        $form['field_pi']['widget']['#options'] = ['_none' => '- None -'];
      }
    ...

/**
 * Called via Ajax callback.
 */
function my_module_ajax_callback_tsr_pi_and_protocol(array &$form, FormStateInterface $form_state) {

  $company_val = $form_state->getValue('field_company');

  if (isset($company_val[0]['target_id'])) {
    $company_id = $company_val[0]['target_id'];
  }
  if (!empty($company_id)) {
    $form['field_protocol']['widget']['#options'] = my_module_get_approved_aup_options($company_id);
    $form['field_tsr_pi']['widget']['#options'] = my_module_get_acitve_user_options($company_id);
  }
  else {
    $form['field_protocol']['widget']['#options'] = ['_none' => '- None -'];
    $form['field_tsr_pi']['widget']['#options'] = ['_none' => '- None -'];
  }

  $response = new AjaxResponse();
  $response->addCommand(new ReplaceCommand('#my-module-tsr-protocol-wrapper',$form['field_protocol']));
  $response->addCommand(new ReplaceCommand('#my-module-principal-investigator-wrapper', $form['field_tsr_pi']));

  return $response;
}

```

If anyone can help me out, will be really great!!!

# Answer
This actually fix my issue:

```
function hook_form_alter() {
    ....

    case 'node_tsr_form':
    case 'node_tsr_edit_form':
      $form['field_tsr_pi']['#prefix'] = '<div id="my-module-principal-investigator-wrapper">';
      $form['field_tsr_pi']['#suffix'] = '</div>';
      $form['field_protocol']['#prefix'] = '<div id="my-module-tsr-protocol-wrapper">';
      $form['field_protocol']['#suffix'] = '</div>';

      $form['field_company']['widget']['#ajax'] = [
        'callback' => 'my_module_ajax_callback_tsr_pi_and_protocol',
        'event' => 'change',
        'method' => 'html',
        'progress' => [
          'type' => 'throbber',
          'message' => t('loading ...'),
        ],
      ];
      $form['field_protocol']['widget']['#validated'] = TRUE;
      $form['field_tsr_strain']['widget']['#validated'] = TRUE;
    ...

/**
 * Called via Ajax callback.
 */
function my_module_ajax_callback_tsr_pi_and_protocol(array &$form, FormStateInterface $form_state) {
  $company_val = $form_state->getValue('field_company');

  if (isset($company_val[0]['target_id'])) {
    $company_id = $company_val[0]['target_id'];
  }

  // Update Member(s) to notify options.
  $protocols = '';
  $pis = '';
  if (!empty($company_id)) {
    $protocol_data = vivarium_get_approved_aup_options($company_id);
    foreach ($protocol_data as $key => $value) {
      $protocols .= "<option value='".$key."'>".$value."</option>";
    }

    $pis_list = vivarium_get_acitve_user_options($company_id);
    foreach ($pis_list as $key => $value) {
      $pis .= "<option value='".$key."'>".$value."</option>";
    }
  }
  else {
    $protocols = "<option value='_none>- None -</option>";
    $pis = "<option value='_none>- None -</option>";
  }

  $response = new AjaxResponse();
  $response->addCommand(new HtmlCommand("#my-module-tsr-protocol-wrapper select", $protocols));
  $response->addCommand(new HtmlCommand("#my-module-principal-investigator-wrapper select", $pis));

  return $response;
}

```
> 0 votes

---
Tags: nodes, hooks, ajax
---


title: get the file URI of an ImageItem

text:
# Question
Title: get the file URI of an ImageItem
How can I get the file URI of a `Drupal\image\Plugin\Field\FieldType\ImageItem` instance?

I get the field value with `$node_entity->get('field_image')[0]` but I don't know how to get the file URI.

# Answer
> 4 votes
You can use

```
$image_item->entity->getFileUri()

```

---
Tags: 8, files
---


# Question
Title: Content type field to include both media entities and links
I'm new to Drupal and I'm creating a new content type. I know there's two separate fields for media and links, but is there a field that include both? For example, the field is called "News Releases", a user can upload a document and/or include a link. Or would I need to create two separate fields and have one called "News Releases" and "News Releases 2" for media and links?

# Answer
Your best option is probably to use the paragraphs module and create a paragraph type of "News release" that contains the media field and the link field, then create an instance of that paragraph field on your content type.
> 0 votes

---
Tags: 8, nodes, media
---


# Question
Title: How can I disable products so they are unpurchase-able and also display in a view?
I have a view of published products. I want to also create a view of unpublished products, so users can see previous products that were available, but there shouldn't be an *Add to cart* button on these products.

I've unpublished the products and created a view. Administrator users can see the view; when they click on one on the products, the *Add to cart* button is still there.

How can I avoid products can be purchased and displayed in a view?

# Answer
What you do is somewhat dependent on your product architecture, specifically which fields you have at the Product level and which at the ProductVariation level. If all the fields you use in your product displays are at the Product level, you can simply disable the ProductVariation and leave the Product published. There will no longer be an Add to Cart form on the display, and everything else will remain the same.

Use a little trial and error to see what works for you. You may need some additional site building or theming in the case that your displays are dependent on fields injected from the ProductVariation into the Product display.
> 2 votes

---
Tags: views, commerce
---


# Question
Title: How do I sanitize the uploaded files name for sending safely as email attachments?
I have create a form that upload a file. This file is send as email attachment

```
 ..
     $form['cv'] = [
          '#type' => 'managed_file',
          '#title' => 'Votre CV',
          '#required' => true,
          '#upload_validators' => [
            'file_validate_extensions' => ['pdf doc docx odt odf'],
            'file_validate_size' => 4000,
          ],
        ];
..

```

on form submit

```
..
    $cv_id = $form_state->getValue('cv')[0];
    $cv_entity = File::load($cv_id);
    $attachments = [
      $cv_entity,
    ];
    ..
    $result = $this->mailManager->mail($module, $key, $to, $language_code, $params, $reply, $send);
    if ($result['result'] == true) {
      $this->messenger()
        ->addMessage('Your application has been sent.');
..

 function hook_mail($key, &$message, $params) {
       $options = [
    'langcode' => $message['langcode'],
  ];

  switch ($key) {
    // Send a simple message from the contact form.
    case 'beetween_postulate':
      $from = \Drupal::config('system.site')->get('name');
      $message['subject'] = t('E-mail envoyé depuis le site @site-name', ['@site-name' => $from], $options);
      // Note that the message body is an array, not a string.
      $params = $message['params'];
      $mime_id = md5(uniqid(time() . rand(), 1));
      $headers = &$message['headers'];
      $message_content_type = $headers['Content-Type'];
      $headers['Content-Type'] = "multipart/mixed; boundary=\"$mime_id\"";
      $body = "This is a multi-part message in MIME format.\r\n";
      $body .= "--$mime_id\r\n";
      $body .= "Content-Type: $message_content_type \r\n\r\n";
      $body .= $params['body'] . "\r\n\r\n";
      if (!empty($params['attachments'])) {
        $fs_service = \Drupal::service('file_system');
        $fmtg_service = \Drupal::service('file.mime_type.guesser');
        foreach ($params['attachments'] as $file) {
          // Here we add the attachment to the message body.
          $file_name = $fs_service->basename($file);
          $mime_type = $fmtg_service->guess($file);
          $file_content = file_get_contents($file);
          $base64 = chunk_split(base64_encode($file_content));
          $body .= "--$mime_id\r\n";
          $body .= "Content-Transfer-Encoding: base64\r\n";
          $body .= "Content-Type: $mime_type;
 name=$file_name\r\n";
          $body .= "Content-Disposition: attachment;
 filename=$file_name\r\n\r\n";
          $body .= $base64 . "\r\n\r\n";
        }
      }
      $body .= '--' . $mime_id . '--';
      $message['body'] = [$body];

      break;
  }
}

```

it does work for most case but it does not work for some file names , although the

> mailManager-\>mail

returns true, the email is not sent

for examples:

> AMU - Réglement INDEED pour diffusion des offres d'emplois AMU.pdf

> CV.dupond.pdf

How can i convert these files names to a correct format / or return a validator error on upload ?

Is this not a bug of the mail-\>manager method to return true in that case ?

# Answer
> 3 votes
If you write your own code to generate a multi-part message in MIME format, then it's up to you and you alone to ensure that all the headers conform to the RFCs for Mime Mail. There are a LOT of RFCs that apply. So consider using one of the many email modules hosted on drupal.org which will do this for you. And if the one you use doesn't do it quite correctly, open an issue and get that fixed for everyone.

That said, you can UTF-8 encode your filename in the Content-Type and Content-Disposition headers if your filename contains any characters not allowed by the RFCs (generally only some ASCII characters are allowed, and no spaces). A full explanation may be found at https://stackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http

# Answer
> 0 votes
rather than trying to sanitize the file name the best way , i have found a safe option for my case :

```
// Safer to leave the email service give default names rather than trying to sanitize it
...
 foreach ($params['attachments'] as $file) {
    $file_name = null;
...

```

Another option i have tried was to apply that method :

```
$file_name =sanitize_file_name($file_name);

function sanitize_file_name($file_name) {
 // case of multiple dots
  $explode_file_name =explode('.', $file_name);
  $extension =array_pop($explode_file_name);
  $file_name_without_ext=substr($file_name, 0, strrpos( $file_name, '.') );
  // replace special characters
  $file_name_without_ext = preg_quote($file_name_without_ext);
  $file_name_without_ext = preg_replace('/[^a-zA-Z0-9\\_]/', '_', $file_name_without_ext);
  $file_name=$file_name_without_ext . '.' . $extension;
  return $file_name;
}

```

but i found one case where it does not work

---
Tags: forms, emails, 9
---


# Question
Title: non-existent service, yet cache is cleared and module is enabled
I'm trying to access a Drupal service for normalizing content, yet the service is non-existent, even though the module "hal" is enabled and the service is defined. How can I get the service "serializer.normalizer.entity.hal"?

```
root@0968b6d03cdb:/var/www/html# drush cr
 [success] Cache rebuild complete.

root@0968b6d03cdb:/var/www/html# drush pml|grep hal
  Web services                      HAL (hal)                                               Enabled    9.3.0

root@0968b6d03cdb:/var/www/html# drush ev "\Drupal::service('serializer.normalizer.entity.hal');"

In Container.php line 156:

  You have requested a non-existent service "serializer.normalizer.entity.hal".

root@0968b6d03cdb:/var/www/html# cat core/modules/hal/hal.services.yml
services:
  serializer.normalizer.entity_reference_item.hal:
    class: Drupal\hal\Normalizer\EntityReferenceItemNormalizer
    arguments: ['@hal.link_manager', '@serializer.entity_resolver', '@entity_type.manager']
    tags:
      - { name: normalizer, priority: 10 }
  serializer.normalizer.field_item.hal:
    class: Drupal\hal\Normalizer\FieldItemNormalizer
    tags:
      - { name: normalizer, priority: 10 }
  serializer.normalizer.field.hal:
    class: Drupal\hal\Normalizer\FieldNormalizer
    tags:
      - { name: normalizer, priority: 10 }
  serializer.normalizer.file_entity.hal:
    class: Drupal\hal\Normalizer\FileEntityNormalizer
    arguments: ['@entity_type.manager', '@hal.link_manager', '@module_handler', '@config.factory', '@entity_type.repository', '@entity_field.manager']
    tags:
      - { name: normalizer, priority: 20 }
  serializer.normalizer.timestamp_item.hal:
   class: Drupal\hal\Normalizer\TimestampItemNormalizer
   tags:
     # Priority must be higher than serializer.normalizer.field_item.hal.
     - { name: normalizer, priority: 20 }
  serializer.normalizer.entity.hal:
    class: Drupal\hal\Normalizer\ContentEntityNormalizer
    arguments: ['@hal.link_manager', '@entity_type.manager', '@module_handler', '@entity_type.repository', '@entity_field.manager']
    tags:
      - { name: normalizer, priority: 10 }
  serializer.encoder.hal:
    class: Drupal\hal\Encoder\JsonEncoder
    tags:
      - { name: encoder, priority: 10, format: hal_json }

  # Link managers.
  hal.link_manager:
    class: Drupal\hal\LinkManager\LinkManager
    arguments: ['@hal.link_manager.type', '@hal.link_manager.relation']
  hal.link_manager.type:
    class: Drupal\hal\LinkManager\TypeLinkManager
    arguments: ['@cache.default', '@module_handler', '@config.factory', '@request_stack', '@entity_type.bundle.info', '@entity_type.manager']
  hal.link_manager.relation:
    class: Drupal\hal\LinkManager\RelationLinkManager
    arguments: ['@cache.default', '@entity_type.manager', '@module_handler', '@config.factory', '@request_stack', '@entity_type.bundle.info', '@entity_field.manager']

```

I can get other services, just not the "hal" one I want. For example,  `drush ev '\Drupal::service("node.node_route_context");'` works fine.

# Answer
> 6 votes
You can't get it directly because normalizer services are private since Drupal 8.6, see https://www.drupal.org/node/2936397:

> Using encoder/normalizer services directly is not supported, one must use the @serializer service, which will then call the appropriate encoder/normalizer services. Services that have the normalizer or encoder tag really are internal/private implementation details to culminate in an operational @serializer service. These never were APIs. They implement Symfony's "Serializer component" API.

This is also why the service is not listed when looking at all available services:

```
/var/www/html# drupal debug:container | grep 'hal'
hal.link_manager             Drupal\hal\LinkManager\LinkManager
hal.link_manager.relation    Drupal\hal\LinkManager\RelationLinkManager
hal.link_manager.type        Drupal\hal\LinkManager\TypeLinkManager

```

As you can see, none of the services from `core/modules/hal/hal.services.yml`, that are tagged as `normalizer` are listed.

---
Tags: symfony-services
---


# Question
Title: Get the time a custom block was last edited
I have seen lots of answers for getting when a node was last edited, but I can't seem to apply any of these methods to blocks. Basically, I have a block that I only want to display if it has been updated in the last week. When I view blocks in the admin, I see that the admin view shows you when a block was last edited.

I can get my block in hook\_preprocess\_block, and get things like $block-\>label(), but any variation of `$block->getChangedTime();` or `$block->changed;` fails for me.

And really, I need this value in my html template, not the block. So I need to get the specific block by ID, in hook\_preprocess\_html, get the time it was last updated as a unix timestamp, and this would give me the value I need for my twig template.

# Answer
This is a method of content entities implementing the EntityChangedInterface, like for example `node` and `block_content`. In a block template, which is a template of the configured block, you find it in the content array:

```
if (isset($variables['elements']['content']['#block_content'])) {
  $changed_time = $variables['elements']['content']['#block_content']->getChangedTime();
}

```

If you want to load the block content entity outside of the block template, see How to get a field value of custom block?
> 2 votes

# Answer
`$block->updated` should do the trick.
> 1 votes

---
Tags: blocks
---


title: Connect field with Taxonomy Term

text:
# Question
Title: Connect field with Taxonomy Term
I have taxonomy `Brand` and different fields like `RAM`, `Monitor`, 'CPU' under content-type `Hardware`.

While adding a new Hardware how can I add RAM, CPU or other fields with Brands? e.g.

```
RAM = 16 GB, Brand = Corsair
Monitor = 24", Brand = Dell
...

```

I can allow `Brand` taxonomy to unlimited and can add multiple, but is that possible to connect with particular fields? Or is there any better approach?

### Update:

Other solution I was thinking was to add multiple `Brand` fields like `RAM Brand`, `Monitor Brand` etc. Is this the only approach?

# Answer
Let me make sure I understand what you are asking:

**Brand** is a taxonomy vocabulary.

**Hardware** is a node content type.

**Hardware** has fields:

* RAM
* CPU

Now, the question is, how do you specify different brands for RAM and CPU?

There are a couple ways to do this.

**Create multiple Brand taxonomy term reference fields.**

In this approach, you will add a taxonomy term reference field for each field on hardware that you want to set a brand for.

For example:

* RAM
* RAM brand (taxonomy term reference field)
* CPU
* CPU brand (taxonomy term reference field)

However, this is a bad approach if many pieces of hardware have RAM with the same capacity and brand (for example, you have 10 pieces of hardware with Corsair 32 GB).

**The Drupal way: Create more content types**

The most "Drupal" way to do this is to create content types for each "thing" you are trying to model and then combine them.

So, you would create:

* RAM content type with fields **capacity** and **brand** ("brand" taxonomy term entity reference)
* CPU content type with fields **speed** and **brand** ("brand" taxonomy term entity reference)
* Hardware content type with fields **RAM** ("RAM" node entity reference) and **CPU** ("CPU" node entity reference)

This is the most flexible approach, although it takes a little more time to set up.
> 1 votes

---
Tags: entities, taxonomy-terms
---


# Question
Title: How do I add <tr> tag in a table using ajax_command_replace()?
I am using `ajax_command_replace()` in an AJAX callback. It works fine to remove the full `<table>` markup, but I only need to add a row to the table after a form is submitted, when data exist.

What is the correct code to achieve this?

# Answer
The HTML wrapper you will be replacing sounds like it includes the whole table, so when you return the markup for the new table row, it will replace all the content in that selector/wrapper. You need to include the markup for your whole table including the newly added row, not just the new row.
> 0 votes

# Answer
`ajax_command_replace()` is the function to replace elements from HTML markup. The first argument it accepts is the selector for the elements to replace, which means that if that selector is also for a `<table>` element, that element will be replaced.

To add a row into a table, you need either `ajax_command_append()` or `ajax_command_prepend()`. For example, given the following markup, `ajax_command_append('#contacts', $row)` would add `$row` at the table bottom, and `ajax_command_prepend('#contacts', $row)` would add `$row` at the top. (The example markup has been taken from HTML Tables, on the W3Schools site.)

```
 <table id="contacts">
  <tr>
    <th>Company</th>
    <th>Contact</th>
    <th>Country</th>
  </tr>
  <tr>
    <td>Alfreds Futterkiste</td>
    <td>Maria Anders</td>
    <td>Germany</td>
  </tr>
  <tr>
    <td>Centro comercial Moctezuma</td>
    <td>Francisco Chang</td>
    <td>Mexico</td>
  </tr>
</table>

```
> 0 votes

---
Tags: 7, ajax
---


# Question
Title: How do I hide the tab menu link when a view is empty?
I have a view with a menu tab link and an attachment, which displays rows of other nodes, depending on the contextual filter.

This view has a custom path(*/node/%node/view-custom-path*).

How do I show the menu link only when the following conditions are met?

* The node has some taxonomy terms
* The view attachment is empty

I have already set the needed term as filter criteria, but the link ignores it and it's shown everywhere. I can display an empty message and send 404 headers when the view is empty, but how can I hide the link as well?

I tried using basic validation in contextual filters and setting *Hide view* or *Show page not found*, but that didn't help.

# Answer
First, get the route name of the view. Then, alter that route, giving it a custom access callback that checks required conditions. Deny access if they are not met. Tabs are only shown if/when the user has access to the route.
> 0 votes

---
Tags: views, 9
---


title: Allow SVG in Views Rewrite Results

text:
# Question
Title: Allow SVG in Views Rewrite Results
I am rewriting the results of a field in a View and depending on the value of a field, I want to display an SVG icon. I can use TWIG to do the conditional logic and that works great, but it won't let me use the SVG tag. There is help text below that says:

```
You may include Twig or the following allowed HTML tags: <a> <abbr> <acronym> <address> <article> <aside> <b> <bdi> <bdo> <big> <blockquote> <br> <caption> <cite> <code> <col> <colgroup> <command> <dd> <del> <details> <dfn> <div> <dl> <dt> <em> <figcaption> <figure> <footer> <h1> <h2> <h3> <h4> <h5> <h6> <header> <hgroup> <hr> <i> <img> <ins> <kbd> <li> <mark> <menu> <meter> <nav> <ol> <output> <p> <pre> <progress> <q> <rp> <rt> <ruby> <s> <samp> <section> <small> <span> <strong> <sub> <summary> <sup> <table> <tbody> <td> <tfoot> <th> <thead> <time> <tr> <tt> <u> <ul> <var> <wbr>

```

So as you can see, SVG is not there. Is there a way to make it allowable?

# Answer
> 4 votes
You can get around it by doing the overriding via template file rather than views config.

If you would like to allow it on views config and as long as you feel comfortable that non of your admins will do any evil XSS using `svg` to seek higher admin power and take over the world site, you could patch https://github.com/drupal/core/blob/9.3.x/lib/Drupal/Component/Utility/Xss.php#L21.

---
Tags: views
---


# Question
Title: Enable image resizer for all images in the ckeditor
I'm using Drupal 9.2.9,

I have some migrated content that comes from an external source. there are some `<img` tags,

the Ckeditor image resizer is working for the images I insert into the editor the upload icon but for the images that come from the content migration, the resizer is not enabled.

I even tried to add `height` manually to the `<img` tag but nothing appear.

the question is that, how can I enable image resizer for all images within the ckeditor?

# Answer
I figure out the resizer plugin works if the image has the following attributes:

* data-entity-type="file"
* data-entity-uuid=

So what I did, I create a batch process and go through all the content and find the image, then based on the image I load their `uuid` and file replaced it.

something like the following code may helps people which have similar requirement:

```
if (preg_match_all('~<img.*?src=["\']+(.*?)["\']+~', $node->body->value, $matches)) {
            $URIS = array_unique($matches[1]);
            foreach ($URIS as $imgUri) {
              $imgUriDecoded = urldecode($imgUri);
              $node->body->value = str_replace($imgUri, $imgUriDecoded, $node->body->value);
              $fileData = self::getFileDataByUrl($imgUriDecoded);
              $fileUuid = "xxx-just-for-resize";
              if ($fileData) {
                $fileUuid = $fileData->get('uuid')->value ?? "xxx-just-for-resize";
              }
              // skip Danger.jpg
              if ($fileUuid == "4f6db862-2c5d-4fb1-8d5b-830b89514af4") {
                continue;
              }
              $replacement = sprintf('<img data-entity-type="file" data-entity-uuid="%s"', $fileUuid);
              $node->body->value = str_replace("<img ", $replacement, $node->body->value);
              \Drupal::messenger()->addStatus($node->id());
            }
          }
      $node->setSyncing(TRUE);
      $node->save();
    }

```

The following file helps to get file by fileURI:

```
  static function getFileDataByUrl($fileURI) {
    $file_name = \Drupal::service('file_system')->basename($fileURI);
    $target_file = \Drupal::entityTypeManager()
      ->getStorage('file')
      ->loadByProperties(['filename' => $file_name]);
    $file_data = reset($target_file);
    if ($file_data) {
      return ($file_data);
    }
    else {
      return FALSE;
    }
  }

```
> 0 votes

---
Tags: 9, wysiwyg
---


# Question
Title: Webform HTML Email Fine on localhost with MailHog, Just Text on Server
I Developed a webform on my localhost, testing the Email using Mailhog. Everything looks fine, nicely formatted html emails. When I moved it to my test server at A2Hosting, the emails all show as text. Using Drupal 9.2.7, Webform 6.1.2. I am not using any additional mail modules, just what comes with Drupal and Webform.

To move to my A2Hosting site, I just made a tarball, extracted, reloaded the database and got the site running. I do not know if Mailhog is just a poor choice for local email testing, if it is a problem at A2Hosting, or if I need some other module to make this work on the hosting site. It works fine on my local machine. The email header does seem very complex and I have included it below.

Note that EMClient says the email is formatted as html, but it show the html text.

Any idea what I need to do to get html email delivered from my hosting site?

```
Delivered-To: hummingbirdretreats@gmail.com
Received: by 2002:a67:e1de:0:0:0:0:0 with SMTP id p30csp745012vsl; Sun, 19 Dec
 2021 13:09:16 -0800 (PST)
X-Google-Smtp-Source: ABdhPJyMretpmTYP0W8WnE73MwAJmqWAs/sJzQf+2GGRxXLUNWB+ZTToY4dcwopzcjQX9LYHiRka
X-Received: by 2002:a17:903:2404:b0:148:db27:981a with SMTP id
 e4-20020a170903240400b00148db27981amr13552440plo.31.1639948156683; Sun, 19
 Dec 2021 13:09:16 -0800 (PST)
ARC-Seal: i=1; a=rsa-sha256; t=1639948156; cv=none; d=google.com;
 s=arc-20160816;
 b=nvnaX1XfnDvqdSZFi3oE8WHzEaA+58ovq9ABMbkwMZBXTGrEDONZktnFqbpIA29lsQ
 jnOes6zRpHNeqV+801eH9iJUx4OPG0GfiCFnY4EtKtMCqlTF40K1o3Pdt46rqOmX+oZT
 AvOpIhvE3RJcg6q4+6I32PCrha6ReIRyxaa77QUZ+6zuqEFxsgyksuYk8qZmBFXW4k2D
 dJ82XXO6AjeSE6+79dP8yWnKFUug7g066D9v6ZryB/mlLU94rfsf+g9mLVMiXlrXspi+
 vO98zo0mcylMN9hF6+KbM+BUWty4puvpbqfyMtSN4QQ0F/AUNrjWPyb472wfTz2vxIIs syWA==
ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com;
 s=arc-20160816;
 h=date:from:message-id:mime-version:subject:to:dkim-signature;
 bh=CyxsiqnaEZFERiXIhFvUgPo5A/uykwhLvxMvB5XFUqY=;
 b=nZIUHh1Ax6I7+2VPsHtxEJMhZeEDx9EzHx19ry2b4ZORdpLLIPpazKuVNPq+XAp5U3
 0nQFEbl9pDbV4irgvGIqCNNHPr+JtjlZ7YX03hx4zNFpfDeKxGBl5ackl91K2zzbzg4X
 DmXGyQpHywwgFK/zNlpTvpyAbq5wXi5/us4ZyE5ytzY5vzlrku1KApoM8tvrhzhEtLmT
 /gGaWIt1cFZFT3K1zZUOeExKgNt2MyL0FEfNrM62JnYL1yl3jcA+XdeHD090uQx17GLV
 zPxqQXsywU9VRJz9eMffllNvP4LoTdtGUTiRKGNF5rzQGaqIj8KKgi597MnwkAPhwYmD Ckiw==
ARC-Authentication-Results: i=1; mx.google.com; dkim=pass
 header.i=@hummingbirdhealingcenter.org header.s=default header.b=VLU1Jaup;
 spf=pass (google.com: domain of info@hummingbirdhealingcenter.org designates
 23.83.209.51 as permitted sender)
 smtp.mailfrom=info@hummingbirdhealingcenter.org
Return-Path: <info@hummingbirdhealingcenter.org>
Received: from dragonfly.birch.relay.mailchannels.net
 (dragonfly.birch.relay.mailchannels.net. [23.83.209.51]) by mx.google.com
 with ESMTPS id a22si8442075pff.212.2021.12.19.13.09.16 for
 <hummingbirdretreats@gmail.com> (version=TLS1_2
 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 19 Dec 2021 13:09:16
 -0800 (PST)
Received-SPF: pass (google.com: domain of info@hummingbirdhealingcenter.org
 designates 23.83.209.51 as permitted sender) client-ip=23.83.209.51;
Authentication-Results: mx.google.com; dkim=pass
 header.i=@hummingbirdhealingcenter.org header.s=default header.b=VLU1Jaup;
 spf=pass (google.com: domain of info@hummingbirdhealingcenter.org designates
 23.83.209.51 as permitted sender)
 smtp.mailfrom=info@hummingbirdhealingcenter.org
X-Sender-Id: a2hosting|x-authuser|humming7@mi3-ts4.a2hosting.com
Received: from relay.mailchannels.net (localhost [127.0.0.1]) by
 relay.mailchannels.net (Postfix) with ESMTP id E6FCE881065 for
 <hummingbirdretreats@gmail.com>; Sun, 19 Dec 2021 21:09:15 +0000 (UTC)
Received: from mi3-ts4.a2hosting.com (unknown [127.0.0.6]) (Authenticated
 sender: a2hosting) by relay.mailchannels.net (Postfix) with ESMTPA id
 5FF62880BEC for <hummingbirdretreats@gmail.com>; Sun, 19 Dec 2021 21:09:15
 +0000 (UTC)
X-Sender-Id: a2hosting|x-authuser|humming7@mi3-ts4.a2hosting.com
Received: from mi3-ts4.a2hosting.com (mi3-ts4.a2hosting.com [70.32.23.71])
 (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384) by 100.97.65.154
 (trex/6.4.3); Sun, 19 Dec 2021 21:09:15 +0000
X-MC-Relay: Neutral
X-MailChannels-SenderId: a2hosting|x-authuser|humming7@mi3-ts4.a2hosting.com
X-MailChannels-Auth-Id: a2hosting
X-Wipe-Ski: 4c75bb0d555c23f2_1639948155748_4128232018
X-MC-Loop-Signature: 1639948155748:545827072
X-MC-Ingress-Time: 1639948155748
DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed;
 d=hummingbirdhealingcenter.org; s=default; h=Date:From:Message-Id:
 MIME-Version:Subject:To:Sender:Reply-To:Cc:Content-Type:
 Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date:
 Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:
 References:List-Id:List-Help:List-Unsubscribe:List-Subscribe:List-Post:
 List-Owner:List-Archive; bh=CyxsiqnaEZFERiXIhFvUgPo5A/uykwhLvxMvB5XFUqY=; b=V
 LU1Jauph2/wQjuiTs5ipSo6SMxn1AXD+B2JwT78QmstmyHDidi09umiRfXPcYJrI8+uYai0yMFhHk
 o3V4jTjgZ4vGAKHtiPYE+Pv0x6CYipWp5gwdrPNOuVCUb7q9MhvjhEgfs0zydC8GX8A6dBm6EyOH8
 jFeMrlzjQIKcBZ17lw6nMFze1CYswIjGvgK+98ilRTXAE9QoGvry9vPv0Wv8E2/LoVuXKesN/DTnI
 PQtjiHC/RcHFUGflr/z/YRpGaAJQsVLx/QUOBLoQf/iYN6Yc7l8p6qtaM7sZCaXo6yPCRDm0ahQtt
 OhfDuyn8/MmFEyK6BFXcbJTCUVTloWMFw==;
Received: from humming7 by mi3-ts4.a2hosting.com with local (Exim 4.94.2)
 (envelope-from <info@hummingbirdhealingcenter.org>) id 1mz3Qg-000x6T-BR for
 hummingbirdretreats@gmail.com; Sun, 19 Dec 2021 16:09:14 -0500
To: hummingbirdretreats@gmail.com
Subject: Booking Form for Loremipsum
MIME-Version: 1.0 Content-Type: text/html; charset=UTF-8; format=flowed
 Content-Transfer-Encoding: 8Bit X-Mailer: Drupal Sender:
 info@hummingbirdhealingcenter.org From: HHC Booking Form
 <info@hummingbirdhealingcenter.org> Reply-to: HHC Booking Form
 <info@hummingbirdhealingcenter.org>
Message-Id: <E1mz3Qg-000x6T-BR@mi3-ts4.a2hosting.com>
From: info@hummingbirdhealingcenter.org
Date: Sun, 19 Dec 2021 16:09:14 -0500
X-AuthUser: humming7@mi3-ts4.a2hosting.com

<html>
<head>

```

# Answer
> 0 votes
Haven't you posted this somewhere else recently? I'm sure I answered this already. The problem is here:

```
MIME-Version: 1.0 Content-Type: text/html; charset=UTF-8; format=flowed
 Content-Transfer-Encoding: 8Bit X-Mailer: Drupal Sender:
 info@hummingbirdhealingcenter.org From: HHC Booking Form
 <info@hummingbirdhealingcenter.org> Reply-to: HHC Booking Form
 <info@hummingbirdhealingcenter.org>

```

That is all on one long line. That is wrong. There should be a \r\n before each header field name. With everything wrapped like that, the mail client receiving the mail doesn't see those headers and thus doesn't know it's an HTML formatted email. It should look like this:

```
MIME-Version: 1.0
Content-Type: text/html; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8Bit
X-Mailer: Drupal
Sender: info@hummingbirdhealingcenter.org
From: HHC Booking Form <info@hummingbirdhealingcenter.org>
Reply-to: HHC Booking Form <info@hummingbirdhealingcenter.org>

```

The reason this is happening probably has something to do with your server email software or your mail module. The RFC mandates that \r\n be used as line terminators for mail headers, but historically this is something a lot of people get wrong - they tend to use the operating system's native line terminator instead. That is wrong.

This was probably caused by this Drupal Core bug. All supported releases now have this fixed.

---
Tags: webforms, emails
---


# Question
Title: How know if user is visitor or logged member?
How can I determine programatically whether the current user is anonymous or authenticated?

# Answer
> 69 votes
For the sake of more robust and descriptive code, you can make use of the handy `User::isAnonymous()` method, e.g.

```
if (\Drupal::currentUser()->isAnonymous()) {
  // Anonymous user...
}

```

# Answer
> 7 votes
```
  $current= \Drupal::currentUser();
  if (!$current->id()) {
    // is visitor
  }
  else {
    // is logged
  }

```

# Answer
> 4 votes
`isAnonymous()` holds the danger of not working when a site is saving data (for example in forms) in `PrivateTempStore`. Therefore, i prefer the following:

```
if (\Drupal::currentUser()->isAuthenticated()) {
  // This user is logged in.
} else {
  // This user is anonymous.
}

```

# Answer
> 1 votes
Methods that you can use in Drupal 8 to check:

Use the **isAuthenticated()** method on the user. For example, use the following code to determine the state of the current user:

```
$logged_in = \Drupal::currentUser()->isAuthenticated();

```

Use **isAnonymous()** to determine if the user is anonymous:

```
$anynomous_user = \Drupal::currentUser()->isAnonymous();

```

# Answer
> -5 votes
U can use this code::

```
global $user;
if ($user->uid == 0) {
  //user is not logged in
}else{
  //user is logged in
}

```

---
Tags: users, 8
---


# Question
Title: Changing a user object property that is loaded from the users table
In a module I developed, I need to change `$user->language` for those users who don't have the "change own user language" permission, a permission the module itself defines. The module is actually doing two things:

* Hiding the language selector in the user edit form for those users who don't have the permission to set a language by setting its #access property to `FALSE`
* Loading the default language for those users

The first part works. For the second part, I was first using hook\_user\_load() but due to the following warning shown in the documentation page, I changed the code to use `hook_init()`.

> Due to the static cache in `user_load_multiple()` you should not use this hook to modify the user properties returned by the {users} table itself since this may result in unreliable results when loading from cache.

The problem is that with `hook_init()` I am not doing anything when a module loads a user object, sets that as current user, does something, and then changes back the global `$user`.
I know I could load the language in a custom property, but I should still need to change the `$user->language` property before Drupal or any module uses it.

How can I change a user object property that is loaded from the users table?

# Answer
> 0 votes
To always be able to set the default language for the loaded accounts, I implemented `hook_entity_info_alter()` using the following code.

```
function mymodule_entity_info_alter(&$entity_info) {
  // Disable the static cache for users.
  if (!empty($entity_info['user']))
    $entity_info['user']['static cache'] = FALSE;
  }
}

```

The alternative would be to implement `hook_entity_info_alter()` to change the language callback, which is used from `entity_language()`, a function introduced from Drupal 7.15 which uses the following code.

```
// Invoke the callback to get the language. If there is no callback, try to
// get it from a property of the entity, otherwise NULL.
if (isset($info['language callback']) && function_exists($info['language callback'])) {
  $langcode = $info['language callback']($entity_type, $entity);
}
elseif (!empty($info['entity keys']['language']) && isset($entity->{$info['entity keys']['language']})) {
  $langcode = $entity->{$info['entity keys']['language']};
}

```

For example, the following functions would achieve what I wanted. In this case, the code is specific for changing the language associated to the user account; to change from  `hook_user_load()` any value Drupal loads from the *users* table, the first approach works for any value loaded from that database table.

```
function mymodule_entity_info_alter(&$entity_info) {
  // Add the language callback for users.
  if (!empty($entity_info['user']))
    $entity_info['user']['language callback'] = 'mymodule_user_language';
  }
}

function mymodule_user_language($entity_type, $entity) {
  if ($entity_type == 'user' && !user_access('change own user language', $entity)) {
    $entity->language = language_default('language');
  }
}

```

In both the cases, there could be a conflict between two modules implementing the same hook. In the first case, the conflict would create less disruption.

### References

---
Tags: 7, users
---


title: Show taxonomy field in View

text:
# Question
Title: Show taxonomy field in View
I have taxonomy called `Hardware Type` and it has field `Short Code`. Now content-type `Hardware's` has this taxonomy and I have a page which lists all `Hardware`. I want to show Hardware type's `short code` field but option is not available under fields.

What are the possible solutions to this?

# Answer
> 0 votes
NVM, I figured it out that relations can be added from `Advanced` menu, like below screenshot.

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


# Question
Title: Custom reference field saving empty values
I've created a custom field based on entity reference field but the target\_id it saves comes from an external system.

I have the field type, field widget and autocomplete element defined and working and the correct values are being saved to the associated database table for valid values.

The bit I'm stuck on is that if the field is left blank it still saves a record to the database but with an empty target\_id. How should I stop it doing that?

Here's my implementation of isEmpty(), which I cribbed from the EntityReference field definition. I'm guessing this is the culprit but I'm not sure how to fix it:

```
  /**
   * {@inheritdoc}
   */
  public function isEmpty() {
    $target_id = isset($this->target_id) ? $this->target_id : NULL;
    if ($target_id !== NULL) {
      return FALSE;
    }
    return TRUE;
  }

```

# Answer
> 0 votes
`isEmpty()` was the culprit here, for some reason that I don't fully understand `$this->target_id` was set to an empty string instead of NULL, so changing `if ($target_id !== NULL)` to just `if ($target_id)` fixed it.

Thanks @Clive for the clue.

---
Tags: entities, 9
---


title: Number field type for specific format

text:
# Question
Title: Number field type for specific format
I have to store number data into database in format xx-xxxxxx-xx for example I have xml data in format: ISBN="10-000000-701" ISBN="11-000000-002" ISBN="11-000000-004"

and I need to store that number in db field but I don't know what field type to use. Any help?

# Answer
You can create a 'simple text' field. Then you can add a constraint to that field to ensure that it is in the correct format.
> 3 votes

---
Tags: 8, entities
---


# Question
Title: How can I make my brand new module dependent on a minimal core version that's required for it to work OK?
I am developing a brand new module (there isn't any site using it yet). It requires a specific Drupal version, as it uses the `hook_taxonomy_term_view()` hook that was introduced in Drupal core version 7.17.

I want to avoid my module being enabled on a site using, for example, Drupal 7.16 or any earlier versions of Drupal core. Higher versions of Drupal, above 7.17, should be fine.

**My Question**: How can I make my module dependent on that Drupal 7.17 version, which is a minimum for my module?

Note: I don't need (have to worry about) a solution for sites where the module is already installed. So there is no need for it to be disabled somehow in such pre-7.17 Drupal versions.

# Answer
The trick, apparently, is to add the System module as dependency for the module.

```
dependencies[] = system (>=7.17)

```
> 11 votes

# Answer
`hook_requirements()` exists for exactly that sort of purpose.

> Check installation requirements and do status reporting.

You can check the `$phase` parameter to determine if the module is being installed, check the current Drupal version against your required version, and return a severity of `REQUIREMENT_ERROR`. That will prevent the module from being installed until the requirement is met.

The documentation is pretty thorough, the one thing worth mentioning here is that the hook needs to be implemented in the module's .install file.
> 7 votes

# Answer
You could use the hook\_enabled

This would fire after the module is installed. You can check the version of the drupal installed and if it is not the correct version then use module\_disable and give the required error message.
> 2 votes

# Answer
With Drupal 8.x, it's still possible to add the System module as dependency of a module, to require a specific Drupal core version. Drupal 8.x uses YAML for the .info file (which now has a .info.yml extension), so the dependencies are declared with code similar to the following one.

```
dependencies:
  - drupal:serialization
  - drupal:system (>=8.2.x)

```

Since Drupal 8.8.0, it's possible to require a more specific Drupal core version using `core_version_requirement`.

```
core_version_requirement: ^8.8 || ^9

```

Using that line, which cannot be used together a line that sets `core`, the module is requiring at least Drupal 8.8.x or Drupal 9.x; any different Drupal version would mark the module as not compatible with the Drupal version used from the site.

As side note, the dependencies in Drupal 8 are namespaced. They require first the project machine name (for example, *drupal* for Drupal core) and then the module machine name (for example, *system* for the System module), separated from a colon. In this way, there isn't any ambiguity on which module is required.

### Reference
> 0 votes

---
Tags: hooks
---


title: How can I debug entity queries?

text:
# Question
Title: How can I debug entity queries?
Is there an out-of-the-box solution for printing the query of an entity query in Drupal 8?

Right now I'm using kind of a hack, adding:

```
->addTag('debug')

```

and then in a custom module:

```
function mymodule_query_alter($query) {
  if ($query->hasTag('debug')) {
    mymodule_query_debug($query);
  }
}

```

and then the debug function:

```
function mymodule_query_debug($query) {

  $sql = (string) $query;
  $quoted = array();
  foreach ((array) $query->arguments() as $key => $val) {
    if (is_array($val)) {
      $val = implode(', ',$val);
    }
    $quoted[$key] = \Drupal::database()->quote($val);
  }
  $sql = strtr($sql, $quoted);
  $sql = str_replace('}', '', $sql);
  $sql = str_replace('{', '', $sql);
  print_r($sql);
  die();
}

```

# Answer
> 6 votes
For Drupal 8, there is the Devel module and the Web Profiler module. The latter module, once enabled, installs a toolbar at the bottom of the page for users with the appropriate permissions. The database button within this toolbar takes you to a inspection page that shows all database queries executed during the last request.

If you're able to trigger the entity query through any browser request, you should be able to inspect the list of DB queries for the specific entity query you're looking to debug.

# Answer
> 0 votes
To examine the SQL query that the query object uses at a particular point in its lifecycle, print the query object. To examine the arguments, look at the Array returned by the arguments() method:

```
echo $query;
print_r($query->__toString());
print_r($query->arguments());

```

More about dynamic queries at https://www.drupal.org/docs/8/api/database-api/dynamic-queries/introduction-to-dynamic-queries

---
Tags: 8, database
---


title: Programmatic list of Webform elements?

text:
# Question
Title: Programmatic list of Webform elements?
I am building a D8 module that, for configuration, needs a list of webforms and their fields (just the entity reference fields, but I am not picky)

I can get the webforms with this:

```
  $webforms = \Drupal::entityTypeManager()->getStorage('webform')->loadMultiple(null);

```

But once I get the returned elements `(Drupal\webform\Entity\Webform::__set_state)`, how can I fetch the elements in the webform referenced?

# Answer
By trawling through the code, I found this handy function in the Entity code, and it works perfectly:

```
 $elements = $webform->getElementsDecodedAndFlattened();

```

This gives a nice array of the elements in the webform itself.

If you want the results of a submission, grab that entity and use:

```
$data = $entity->getData();

```

I hope this helps
> 9 votes

# Answer
The complete code for fetching the webform elements are listed below:

```
  $webform = Webform::load('webform_id'); //replace webform_id with the webform id
  if ($webform) {
    $view_builder = \Drupal::entityTypeManager()->getViewBuilder('webform');
    $elements = $webform->getElementsDecodedAndFlattened();
  }

```
> 1 votes

---
Tags: 8, webforms
---


# Question
Title: Import CSV, row by row, into custom table
I have a Drupal 7 submit method for updating CSV row by row to a custom table which I found under this link. I have tried to update it so that it works in Drupal 8 to no avail. How do I to modify it to work in Drupal 8?

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

    $file = $form_state['values']['csv_upload_file'];
    $file->status = FILE_STATUS_PERMANENT;
    $file->filename = str_replace(' ', '_', $file->filename);
    file_save($file);

    $csv_file = file_load($file->fid);
    $file = fopen($csv_file->uri, "r");

    while(! feof($file))
    {
        $customer = fgetcsv($file));
        db_insert('your_db_table')
            ->fields(array(
                'column1' => $customer[0],
                'column2' => $customer[1]
            ))
            ->execute();
    }

    fclose($file);

    drupal_set_message('CSV data added to the database');
}

```

The Drupal 8 code that I am trying to use is as below:

```
public function submitForm(array &$form, FormStateInterface $form_state)
{
    $file = $form_state->getValue('csv_upload');
    $file->status = FILE_STATUS_PERMANENT;
    $file->filename = str_replace(' ', '_', $file->filename);
    file_save_data($file);

    $csv_file = \Drupal\file\Entity\File::load($file->fid);
    $file = fopen($csv_file->getFileUri(), "r");

    while (!feof($file)) {
        $customer = fgetcsv($file);
        \Drupal::database()->insert('your_db_table')
            ->fields(array(
                'column1' => $customer[0],
                'column2' => $customer[1]
            ))
            ->execute();
    }

    fclose($file);

    drupal_set_message('CSV data added to the database');
}

```

Errors include:

1. Fatal error: Call to a member function getFileUri() on null in /home/annuities/public\_html/modules/custom\_module/src/Form/CustomForm.php on line 90.

Line 90: `$file = fopen($csv_file->getFileUri(), "r");`

2. Warning: Creating default object from empty value in Drupal\custom\_module\Form\CustomForm-\>submitForm() (line 85 of modules/custom\_module/src/Form/CustomForm.php).

Line 85: `$file->status = FILE_STATUS_PERMANENT;`

3. Notice: Undefined property: stdClass::$filename in Drupal\custom\_module\Form\CustomForm-\>submitForm() (line 86 of modules/custom\_module/src/Form/CustomForm.php).

Line 86: `$file->filename = str_replace(' ', '_', $file->filename);`

4. The file could not be created. Notice: Undefined property: stdClass::$fid in Drupal\custom\_module\Form\CustomForm-\>submitForm() (line 89 of modules/custom\_module/src/Form/CustomForm.php).

Line 89: `$csv_file = \Drupal\file\Entity\File::load($file->fid);`

5. Warning: array\_flip(): Can only flip STRING and INTEGER values! in Drupal\Core\Entity\EntityStorageBase-\>loadMultiple() (line 227 of core/lib/Drupal/Core/Entity/EntityStorageBase.php).

# Answer
> 2 votes
I used the code below;

```
public function submitForm(array &$form, FormStateInterface $form_state)
{

    $file = $form_state->getValue('csv_upload_file');

    $destination = $file[0]->toArray()['uri'][0]['value'];

    $file = fopen($destination, "r");

    while (!feof($file)) {
        $customer = fgetcsv($file);
        \Drupal::database()->insert('your_db_table')
            ->fields(array(
                'column1' => $customer[0],
                'column2' => $customer[1]
            ))
            ->execute();
    }

    fclose($file);

    drupal_set_message('CSV data added to the database');
}

```

# Answer
> 0 votes
see this article.it says how you can have full control over each excel cell value and insert data into a custom table.

# Answer
> 0 votes
$file = $form\_state-\>getValue('csv\_upload\_file');

It will return just file ids. You need to load file I think.

---
Tags: 8, forms, importing-exporting
---


# Question
Title: How to copy fields from an entity to another for same type entities?
I have 2 entities of the same type & bundle but used in 2 different cases (linked differently to different entities). Upon publishing the second entity, I want to get the new data and put it into the 'main' entity since all logic is built based on the main entity and interacts with other sorts of things.

What I have so far:

```
 $fields_to_exclude = [
  'id',
  'uuid',
  'vid',
];

foreach ($second_entity->getFields() ?: [] as $name => $field) {
  if (!in_array($name, $fields_to_exclude)) {
    $main_entity->set($name, $field->getValue());
  }
}
$main_entity->save();

```

There are around 120 fields and I need to exclude only 5-10. My problem is that I want to get only fields created in the interface such as 'field\_country\_name', 'field\_category' etc. The function above returns all entity fields (such as ID, UID, etc.) and there are too many to take into consideration. Is there any way to get only the 'custom created fields' ? I could not find anything in the Drupal API.

# Answer
Apparently you can just check if the field name contains the word 'field' since it is specific to only 'created from the interface' fields.

```
strpos($name, 'field') !== FALSE

```
> 0 votes

---
Tags: entities
---


# Question
Title: Can't import sql dump file from the live site (trying to create a development site)
I am trying to create a development site which I can work on. So far, I have done:

1. creating a backup.sql using **drush sql-dump \> backup.sql**
2. coping and pasting the live site folder for the development site folder
3. in the new project folder (dev site one) I copied, I changed the db name,username, and password, then tried to import the database dump file by **drush sql-query --file=backup.sql**

From step 3, after running the command, I am getting **\[error\] File(s) not found: backup.sql** , even after trying to clear the cache by **drush cr**, I get **SQLSATE\[HY000\] \[1045\] ACCESS DENIED FOR user ''@'localhost' (using password: YES)**

It's really frustrating me because I have been trying to debug this for all day today. Would anyone be able to help me? I even changed the permission of the backup.sql and still cannot figure out why.

Thank you in advance.

# Answer
> 2 votes
That error almost always means your connection information for your database is incorrect. check the database username, password, and database name in settings.php.

---
Tags: database
---


# Question
Title: Extending contrib module filelog service class displays PSR implementation error
I wanted to override the logger.filelog service from filelog module to make use of my own parser.

An error occurred through `drush cim` and `drush cr` when the new custom module that overrides the service is enabled.

```
The website encountered an unexpected error. Please try again later.
Symfony\Component\DependencyInjection\Exception\LogicException: Service 'logger.filelog' for consumer 'logger.factory' does not implement Psr\Log\LoggerInterface. in Drupal\Core\DependencyInjection\Compiler\TaggedHandlersPass->processServiceCollectorPass() (line 182 of /app/docroot/core/lib/Drupal/Core/DependencyInjection/Compiler/TaggedHandlersPass.php).

```

My custom modules structure looks like this

```
custom_module
  - src
    - Logger
      - TestFilelog.php
    CustomModuleServiceProvider.php
  custom_module.info.yml
  custom_module.module

```

Currently the service provider class has implemented `ServiceModifierInterface` and altered the original logger.filelog service by setting its class to `Drupal\custom_module\Logger\TestFilelog`.

```
/**
 * Class to override contrib module logger.filelog service.
 */
class CustomModuleServiceProvider implements ServiceModifierInterface {

  /**
   * {@inheritdoc}
   */
  public function alter(ContainerBuilder $container) {
    if ($container->has('logger.filelog')) {
      $definition = $container->getDefinition('logger.filelog');
      $definition->setClass('Drupal\custom_module\Logger\TestFilelog');
    }
  }

}

```

`TestFilelog.php`

```
namespace Drupal\custom_module\Logger;

use Drupal\filelog\Logger\FileLog;

/**
 * File-based logger.
 */
class TestFileLog extends FileLog {

  /**
   * Renders a message to a string.
   *
   * @param mixed $level
   *   Severity level of the log message.
   * @param string $message
   *   Content of the log message.
   * @param array $context
   *   Context of the log message.
   *
   * @return string
   *   The formatted message.
   */
  protected function render($level, $message, array $context = []): string {

    $plainString = parent::render($level, $message, $context);

    $custom_channel = [
      'filter_custom_channel'
    ];

    if (in_array($context['channel'], $custom_channel)) {
      $plainString = $this->parseStrMasking($plainString);
    }
    return $plainString;
  }

  /**
   * Mask personal details from strings to logs.
   *
   * @param string $pureString
   *   The string to be parsed.
   *
   * @return string
   *   The string that has been masked.
   */
  protected function parseStrMasking(string $pureString) {
    // Default to return finalString.
    $finalString = $pureString;

    // Custom parsing goes here.

    return $finalString;
  }

}

```

I see that `Drupal\filelog\Logger\FileLog;` has `use RfcLoggerTrait;` which does implement the `Psr\Log\LoggerInterface`, what am I missing here??

# Answer
> 2 votes
As pointed out by @Clive in the comment above, I had a discrepancy in the casing of `TestFilelog` and `TestFileLog`. Thanks again!

This should make a difference on why the implementation of interface wasn't read by Drupal on service handling.

On the other hand, I discovered another approach to override `filelog` module's service, which I took instead.

1. I deleted the `CustomModuleServiceProvider.php` file
2. Created `custom_module.services.yml`
3. service machine name should be the same as the overridden service. (e.g. logger.filelog)
Check `docroot/modules/contrib/filelog/filelog.services.yml`

Content of `custom_module.services.yml`

```
services:
  logger.filelog:
    class: Drupal\custom_module\Logger\TestFileLog
    arguments:
      - '@config.factory'
      - '@state'
      - '@token'
      - '@datetime.time'
      - '@logger.log_message_parser'
      - '@filelog.file_manager'
    tags:
      - { name: logger }

```

**Ref:**

1. How to decorate Services - Symfony
2. Altering existing services - Drupal
3. Overriding services in Drupal - PreviousNext

---
Tags: 9, log-messages, symfony-services
---


# Question
Title: Show links for all the views in the administrator menu
With the admin toolbar enabled, one of the things I miss from Drupal 7 is hovering through the administrator menu on *Structure \>\> Views* and seeing a list of all views and being able to click on one to edit it.

See this screenshot for the current behavior.

>

Is there a way to provide this feature from a custom module? I know I can get a list of all views with `Views::getAllViews()` but I am not sure how to add them programmatically. If I use a custom module, and use `hook_update_n()` to add to the menu, what happens when a new view is added? Would it automatically be updated with the added view, or just list the ones that were present when the module was installed? If not, how can this be done to always show the current views list?

# Answer
> 2 votes
You can add them yourself in a custom module.

`[MODULE].links.menu.yml`:

```
[MODULE].views.list:
  deriver: 'Drupal\[MODULE]\Plugin\Derivative\ViewMenuLinks'

```

`[MODULE]/src/Plugin/Derivative/ViewMenuLinks.php`:

```
<?php

namespace Drupal\[MODULE]\Plugin\Derivative;

use Drupal\Component\Plugin\Derivative\DeriverBase;
use Drupal\Core\Plugin\Discovery\ContainerDeriverInterface;
use Drupal\views\Views;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides menu links for individual views.
 */
class ViewMenuLinks extends DeriverBase implements ContainerDeriverInterface {

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, $base_plugin_id) {
    return new static();
  }

  /**
   * {@inheritdoc}
   */
  public function getDerivativeDefinitions($base_plugin_definition) {
    $this->derivatives = [];

    foreach (Views::getAllViews() as $view_id => $view) {
      $url = $view->toUrl();
      $this->derivatives['views_ui.views.list.' . $view_id] = [
        'route_name' => $url->getRouteName(),
        'route_parameters' => $url->getRouteParameters(),
        'title' => $view->label(),
        'parent' => 'entity.view.collection',
      ];
    }

    foreach ($this->derivatives as &$entry) {
      $entry += $base_plugin_definition;
    }

    return $this->derivatives;
  }

}

```

Note that you'll need to replace all instances of `[MODULE]` with the actual module name of your module.

---
Tags: navigation, 9, toolbar
---


title: Load The database schema in PostgreSQL

text:
# Question
Title: Load The database schema in PostgreSQL
I am following Install Drupal with PostgreSQL to install Drupal 7 with PostgreSQL.

I'm stuck with the steps that says to use a script called database.pgsql which should be found the Drupal files.

I can't find that file. The directory that should contain it has the following content.

>

What should I do to install Drupal 7?

# Answer
> 0 votes
There are two extensions for using PostgreSQL with PHP: the *pgsql* extension and the *pdo\_pgsql* externsion. The first is required by Drupal 6, while the latter is required by Drupal 7.

I enabled it in the php.ini file and Drupal can now use the PostgreSQL database during installation.

# Answer
> 0 votes
I am not sure this tutorial is up-to-date. You don't need to load database scheme, you can just choose to use PostgreSQL when running the installer at /path/to/drupal/install.php

# Answer
> 0 votes
The tutorial hasn't been updated and it contains instructions that are for Drupal 4.7.x, since it's Drupal 4.7.x to come with a database.pgsql file. Drupal 5.x doesn't have that file and its installation instructions don't include that step; the installation.txt file also says:

> As of Drupal 5.0 installation has been automated by an install script. It is no longer necessary to manually edit the "settings.php" file, and database tables are created automatically.

In Drupal 5 and successive versions, it's enough to have the required extensions to access the database installed and enabled.

---
Tags: 7, installation, database
---


# Question
Title: How to remove addtoany js for a particular node page?
I need to unset addtoany module js for a particular node.

For that I have implemented

```
 function theme_name_js_alter(&$javascript) {
    if(\Drupal::service('path.matcher')->isFrontPage()) {
            unset($javascript['https://static.addtoany.com/menu/page.js']);
            unset($javascript['modules/contrib/addtoany/js/addtoany.js']);
            unset($javascript['themes/test/js/index.js']);
            unset($javascript['themes/test/js/custom.js']);
        }
    }

```

Above code unset *index.js* & *custom.js* but not works for *addtoany.js* and *page.js*.

Thanks for your suggestion.

# Answer
> 1 votes
Implements **hook\_page\_attachments\_alter()** to resolve it.

```
function theme_name_page_attachments_alter(array &$attachments) {
    foreach ($attachments['#attached']['library'] as $key => $library) {
        if ($library == 'addtoany/addtoany') {
          unset($attachments['#attached']['library'][$key]);
        }
    }
}

```

---
Tags: 8, javascript
---


title: Reference private file?

text:
# Question
Title: Reference private file?
I'm making migration plugin which I'm using in first migration and it is creating private file like this:

```
if ($final_destination) {
  // Create a file entity.
  $file = File::create([
    'uri' => $final_destination,
    'uid' => $uid,
    'status' => FILE_STATUS_PERMANENT,
  ]);

  $uri = $file->getFileUri();

  $stream = new S3fsStream();
  $stream->writeUriToCache($uri);

  if ($stream->waitUntilFileExists($uri)) {
    $file->save();
    return $file->getFileUri();
  }
}

```

Then, second migration should create media entities, by using those files (with migration lookup plugin).

However, when I run second migration I get error message:

> media: field\_image.0=You do not have access to the referenced entity file: 46

If file is public then it works, but how can I reference private files? The error is triggered in ReferenceAccessConstraintValidator.php.

```
  // We check that the current user had access to view any newly added
  // referenced entity.
  if ($check_permission && !$referenced_entity->access('view')) {
    $type = $value->getFieldDefinition()->getSetting('target_type');
    $this->context->addViolation($constraint->message, ['%type' => $type, '%id' => $id]);
  }

```

# Answer
Found out that this was the known issue and is fixed in Drupal 9.3. With previous versions patch should be applied:

https://www.drupal.org/project/drupal/issues/3134470
> 0 votes

---
Tags: media, files
---


title: Search and Replace URL in database?

text:
# Question
Title: Search and Replace URL in database?
I need to move a Drupal 9 website to a different server and a lot of links have the old server URL. Normally for Word Press I use this tool - https://github.com/interconnectit/Search-Replace-DB https://interconnectit.com/search-and-replace-for-wordpress-databases/

You upload that to the server and it runs a script to search for your string and replace it with the new string.

I tried to do a regular search and replace in VS Code with -

Search //old.url.com Replace with //new.url.com

It found all the //old.url.com but after I imported the database there are still some links that do not redirect to the new url, one of these is /user. If I go to new.url.com/user it redirects to old.url.com/user

Is there a way to do a search and replace on the database to replace the old URL?

# Answer
> 0 votes
You can use HeidiSQL utility Select search -\> Replace text ...

---
Tags: database, 9
---


# Question
Title: Custom validator for checking if fields match
I have two fields, `value` and `copy` that I'm trying to do some custom validation on to make sure they roughly match each other.

So far in my module I have this:

```
function HOOK_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle)
{
    if(!empty($fields['field_value']) && !empty($fields['field_copy']))
    {
        $fields['field_copy']->addConstraint('CopyMatchesValue');
        $fields['field_value']->addConstraint('CopyMatchesValue');
    }
}

```

A constraint

```
<?php

namespace Drupal\MODULE\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;

/**
 * Checks that value matches copy
 *
 * @Constraint(
 *   id = "CopyMatchesValue",
 *   label = @Translation("Copy Matches Value", context = "Validation"),
 * )
 */
class CopyMatchesValue extends Constraint
{
    // The message that will be shown if the format is incorrect.
    public $copyValueMismatch = 'The value does not look like it matches the copy.';
}

```

And a validator

```
<?php

namespace Drupal\MODULE\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Validates the CopyMatchesValue constraint.
 */
class CopyMatchesValueValidator extends ConstraintValidator
{
  /**
   * {@inheritdoc}
   */
  public function validate($items, Constraint $constraint)
  {

      foreach ($items as $key => $item) {
          var_dump($item->value);
      }
      exit;

      // do some processing to make sure they match

      $this->context->addViolation();
    }
  }
}

```

I was expecting `$items` to have both fields I added the constraint to, but that doesn't seem to be the case.

How can I pass two fields to one validator so that I can validate them against each other?

# Answer
I'm not sure if constraints is the best way to go when you need access to two fields. In your form alter, could you add a custom validation method? That way you would have access to `array &$form, FormStateInterface $form_state` giving you access to all fields.

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

```

And then your validation function...

```
/**
 * {@inheritdoc}
 */
function my_test_validate(array &$form, FormStateInterface $form_state) {
  // Do what you need to do here...
}

```
> 0 votes

# Answer
In your case, in validate() you should get an entity before. So your code should be like this:

```
<?php

namespace Drupal\MODULE\Plugin\Validation\Constraint;

use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;

/**
 * Validates the CopyMatchesValue constraint.
 */
class CopyMatchesValueValidator extends ConstraintValidator {

  /**
   * {@inheritdoc}
   */
  public function validate($entity, Constraint $constraint) {
    $entity = $entity->getEntity();
    $field_first = $entity->get('field_first')->getString();
    $field_second = $entity->get('field_second')->getString();
    if ($some_logic) {
      $this->context->addViolation($constraint->message);
    }
  }
}

```

This one example how I made a similar custom validator for checking the field depending on the value of another field.
> 1 votes

# Answer
In order to compare and validate two fields of an entity you need to add the validation to the entity itself instead of validating individual fields.

If you have a custom entity you built yourself, add the constraint to the annotation:

```
/**
 *[...]
 * @MyEntityType(
 *  id = "myentity",
 *  [...]
 *  constraints = {
 *    "MyConstraintName" = {},
 *  },
 * )
 */

```

If you are altering an entity that you haven't created, you can still add the constraint using `hook_entity_type_alter` or to alter only one bundle of the entity use `hook_entity_bundle_info_alter`

Once you have the constraint set up, you can compare and validate the fields in your constraint validator class "validate" method:

```
  public function validate(array $value, Constraint $constraint) {
   $entity = $this->context->getRoot()->getValue();
   // Do your comparisons here.
   if ($entity->get('yourFirstField')->value !== $entity->get('yourSecondField')->value)) {
     $this->context->addViolation($constraint->fieldsDontMatchMessage);
   }
  }

```
> 0 votes

---
Tags: 8, entities
---


# Question
Title: Entity autocomplete form API field with ViewsSelection handler
I'm trying to get an implementation of the Entity Autocomplete Form API field with a view selection handler working in Drupal 9.

I have seen some examples in New 'entity\_autocomplete' form element added, but it shows how to use a default selection handler and they only appear to work in Drupal 8. Specifically it was possible to pass the `view_name` and `display_name` via the `#selection_settings`:

```
$form['user'] = [
  '#type' => 'entity_autocomplete',
  '#target_type' => 'user',
  '#selection_handler' => 'views',
  '#selection_settings' => [
    'view' => [
      'view_name' => 'users_view',
      'display_name' => 'users',
      'arguments' => []
    ],
    'match_operator' => 'CONTAINS'
  ],
];

```

Starting with Drupal 9.x as per this Entity reference selection handlers should extend a base class change record, I noticed that the `ViewsSelection::initializeView()` method no longer does a lookup from `$config['handler_settings']`, but here isn't any reference to what the alternative is in Drupal 9 going forward and whether the `ViewsSelection` plugin was intended to support `#selection_settings`.

# Answer
> 2 votes
It's still possible to pass the options exactly as you have - a lookup from `$config['handler_settings']` isn't needed in `ViewsSelection::initializeView()`.

The `#selection_settings` are merged into the `$configuration` array provided to the plugin when it's initialised in `EntityAutocomplete::validateEntityAutocomplete()`

Using your code verbatim I can see the settings you're passing where expected:

---
Tags: 9
---


# Question
Title: Theming a EntityListBuilder.php table using drupal/examples/content_entity_example as base
Any idea how I could to use my own custom module twig file to theme my table?

I'm using drupal/examples -\> content\_entity\_example as a starting point:

in content\_entity\_example.module implementing hook\_theme I would like to return all fields like:

```

/**
 * @file
 * Contains Drupal\content_entity_example\content_entity_example.module.
 */

/**
 * @defgroup content_entity_example Example: Content Entity
 * @ingroup examples
 * @{
 * Implement a content entity.
 *
 * This module demonstrates implementing a content entity.
 *
 * Entity API is the API that stores pieces of content and configuration for
 * Drupal core. For instance, if you've encountered node content types, you've
 * encountered entities of type 'node.'
 *
 * This example implements the Entity API so that we have an entity type usable
 * by the user which you might think of as specialized nodes, but which are
 * different from nodes. These entities are called Contact, and are known
 * internally by the machine name content_entity_example_contact.
 *
 * Contact is a fieldable content entity used to hold structured information
 * without the overhead of using a node content type. 'Fieldable' means you can
 * attach fields to it, like you can with nodes. It is defined programmatically
 * (completely in code). We will show the main techniques to handle and expose
 * the contents of this entity type.
 *
 * The Contact entity will demonstrate the main tasks for an entity:
 * - define
 * - save
 * - load
 * - view
 * - edit
 * - delete
 * - control access
 *
 * Where ever possible, we use the amazing tools built into D8 natively.
 *
 * @see Drupal\content_entity_example\Entity\Contact
 * @see config_entity_example
 * }
 */

/**
 * Implements hook_theme(). Register a module or theme's theme implementations.
 */

function content_entity_example_theme() {
  return [
    'content_entity_example_table' => [
      'variables' => [
        'header' => NULL,
        'rows' => NULL,
        'footer' => NULL,
        'attributes' => [],
        'caption' => NULL,
        'colgroups' => [],
        'sticky' => FALSE,
        'responsive' => TRUE,
        'empty' => ''
      ],
    ],
  ];
}

```

And in src/Entity/Controller/ContactListBuilder.php I would like to pickup my template ( '#template' ...)

So I would like to tell render() to user my template

```
  /**
   * {@inheritdoc}
   *
   * We override ::render() so that we can add our own content above the table.
   * parent::render() is where EntityListBuilder creates the table using our
   * buildHeader() and buildRow() implementations.
   */
  public function render() {
    $build['description'] = [
      '#markup' => $this->t('Content Entity Example implements a Contacts model. These contacts are fieldable entities. You can manage the fields on the <a href="@adminlink">Contacts admin page</a>.', [
        '@adminlink' => $this->urlGenerator->generateFromRoute('content_entity_example.contact_settings'),
      ]),
    ];
    $build['table'] = parent::render();

// TODO add template reference

    return $build;
  }

```

and as such use my template file in /templates/content-entity-example.html.twig which is going to be changed in a later phase. (just need to get it loaded)

```
{#
/**
 * @file
 * Theme override to display a table.
 *
 * Available variables:
 * - attributes: HTML attributes to apply to the <table> tag.
 * - caption: A localized string for the <caption> tag.
 * - colgroups: Column groups. Each group contains the following properties:
 *   - attributes: HTML attributes to apply to the <col> tag.
 *     Note: Drupal currently supports only one table header row, see
 *     https://www.drupal.org/node/893530 and
 *     http://api.drupal.org/api/drupal/includes!theme.inc/function/theme_table/7#comment-5109.
 * - header: Table header cells. Each cell contains the following properties:
 *   - tag: The HTML tag name to use; either 'th' or 'td'.
 *   - attributes: HTML attributes to apply to the tag.
 *   - content: A localized string for the title of the column.
 *   - field: Field name (required for column sorting).
 *   - sort: Default sort order for this column ("asc" or "desc").
 * - sticky: A flag indicating whether to use a "sticky" table header.
 * - rows: Table rows. Each row contains the following properties:
 *   - attributes: HTML attributes to apply to the <tr> tag.
 *   - data: Table cells.
 *   - no_striping: A flag indicating that the row should receive no
 *     'even / odd' styling. Defaults to FALSE.
 *   - cells: Table cells of the row. Each cell contains the following keys:
 *     - tag: The HTML tag name to use; either 'th' or 'td'.
 *     - attributes: Any HTML attributes, such as "colspan", to apply to the
 *       table cell.
 *     - content: The string to display in the table cell.
 *     - active_table_sort: A boolean indicating whether the cell is the active
         table sort.
 * - footer: Table footer rows, in the same format as the rows variable.
 * - empty: The message to display in an extra row if table does not have
 *   any rows.
 * - no_striping: A boolean indicating that the row should receive no striping.
 * - header_columns: The number of columns in the header.
 *
 * @see template_preprocess_table()
 */
#}
<table{{ attributes }}>
  {% if caption %}
    <caption>{{ caption }}</caption>
  {% endif %}

  {% for colgroup in colgroups %}
    {% if colgroup.cols %}
      <colgroup{{ colgroup.attributes }}>
        {% for col in colgroup.cols %}
          <col{{ col.attributes }} />
        {% endfor %}
      </colgroup>
    {% else %}
      <colgroup{{ colgroup.attributes }} />
    {% endif %}
  {% endfor %}

  {% if header %}
    <thead>
    <tr>
      {% for cell in header %}
      {%
        set cell_classes = [
        cell.active_table_sort ? 'is-active',
      ]
      %}
      <{{ cell.tag }}{{ cell.attributes.addClass(cell_classes) }}>
      {{- cell.content -}}
    </{{ cell.tag }}>
    {% endfor %}
    </tr>
    </thead>
  {% endif %}

  {% if rows %}
    <tbody>
    {% for row in rows %}
      {%
        set row_classes = [
        not no_striping ? cycle(['odd', 'even'], loop.index0),
      ]
      %}
    <tr{{ row.attributes.addClass(row_classes) }}>
      {% for cell in row.cells %}
        <{{ cell.tag }}{{ cell.attributes }}>
        {{- cell.content -}}
        </{{ cell.tag }}>
      {% endfor %}
      </tr>
    {% endfor %}
    </tbody>
  {% elseif empty %}
    <tbody>
    <tr class="odd">
      <td colspan="{{ header_columns }}" class="empty message">{{ empty }}</td>
    </tr>
    </tbody>
  {% endif %}
  {% if footer %}
    <tfoot>
    {% for row in footer %}
    <tr{{ row.attributes }}>
      {% for cell in row.cells %}
        <{{ cell.tag }}{{ cell.attributes }}>
        {{- cell.content -}}
        </{{ cell.tag }}>
      {% endfor %}
      </tr>
    {% endfor %}
    </tfoot>
  {% endif %}
</table>

```

content\_entity\_example works great but I can't load my own template.

# Answer
> 0 votes
It should be as simple as setting the `#theme` on the table that `parent::render()` returns:

```
$build = parent::render();
$build['table']['#theme'] = 'content_entity_example_table';

```

---
Tags: theming, entities, 9
---


# Question
Title: Preview template for node with custom template?
I have a custom content type, 'Article with Header' for which I have a custom twig template, 'page--article-with-header.html.twig', which manages the layout for this content type. When I preview the node before publishing, the template used is page.html.twig. I would like to have the same layout for previewing as for when the node is published, but I don't see any options for doing this. The template suggestions that come up in preview mode (page--node--preview.html, for example) would affect every content type.

Is there a naming convention for preview mode twig templates for custom content types that I'm missing? Is there a preprocessing function I can implement that will force the preview mode for this content type to use the correct template?

# Answer
> 1 votes
The naming convention *should* be:

* page--node--preview--\[type\].html.twig
* page--node--preview--\[type\]--\[viewmode\].html.twig

Unfortunately, this is currently missing from core. To get that working, you would need to add the following to your theme\_name.theme file:

```
function THEMENAME_theme_suggestions_page_alter(array &$suggestions, array $variables) {
  $routeMatch = \Drupal::routeMatch();
  $node_preview = $routeMatch->getParameter('node_preview');
  if ($node_preview instanceof NodeInterface) {
    $suggestions[] = 'page__node__preview__' . $node_preview->bundle();
    if ($view_mode_id = $routeMatch->getParameter('view_mode_id')) {
      $suggestions[] = 'page__node__preview__' . $node_preview->bundle() . '__' . $view_mode_id;
    }
  }
}

```

# Answer
> 0 votes
You can use the `template_preprocess_html(&$variables)` in **THEME\_NAME.theme** and in this we use the **Drupal services** `\Drupal::routeMatch()->getParameter('node_preview');` so it show preview same as a node view.

---
Tags: 8, theming
---


# Question
Title: How do I use {{file_url()}} to get image field URLs in views-view-fields.html.twig?
I tried to use the following code in views-view-fields.

```
{{ file_url(fields.field_featured_image.content.0['#item'].entity.uri.value) }}

```

When I use that code, I get this error.

> TypeError: Argument 1 passed to Drupal\Core\File\FileUrlGenerator::generateString() must be of the type string, null given, called in /home/vito/Desktop/D9-fabco-v2/fabco-v2/vendor/twig/twig/src/Environment.php(418): eval()'d code on line 45 in Drupal\Core\File\FileUrlGenerator-\>generateString() (line 58 of core/lib/Drupal/Core/File/FileUrlGenerator.php).

What's the correct way to use `{{ file_url() }}`?

# Answer
I have solved that in other way:

In created views and in there have the image filed

Than changed the image formatter

Than in views-view-fields.html.twig

```
<div class="image" style="background-image:url({{fields.field_featured_image.content|striptags|raw}});"></div>

```

be-careful with quotation marks and spaces that can cause why your image not displayed.

If you have better solution please do not hesitate post it here in comments
> 0 votes

---
Tags: views, 9
---


# Question
Title: ConfigNameException: Missing namespace in Config object name xxx
Drupal\Core\Config\ConfigNameException: Missing namespace in Config object name media\_entity\_file\_replace. in Drupal\Core\Config\ConfigBase::validateName() (line 97 of core/lib/Drupal/Core/Config/ConfigBase.php).

i don't quite get what i have done wrong in my config form

media\_entity\_file\_replace/src/Form/MediaEntityFileReplaceSettingsForm.php

```
namespace Drupal\media_entity_file_replace\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;

/**
 * Configure media_entity_file_replace settings for this site.
 */
class MediaEntityFileReplaceSettingsForm extends ConfigFormBase {

```

# Answer
> 4 votes
The error comes from `Drupal\Core\Config\ConfigBase`:

```
public static function validateName($name) {
  // The name must be namespaced by owner.
  if (strpos($name, '.') === FALSE) {
    throw new ConfigNameException("Missing namespace in Config object name {$name}.");
  }
...

```

Do you reference a configuration object somewhere in your form without a period? For example:

```
$config = \Drupal::config('config_with_no_namespace');

```

---
Tags: configuration
---


# Question
Title: Unable to use SameSite=none with secure attribute, using Symfony\Component\HttpFoundation\Cookie to create the cookie
I am trying to create a cookie in Drupal 8.9 with `SameSite=none` with secure attribute, using the `Symfony\Component\HttpFoundation\Cookie` class but I am unable to do so as the class doesn't allow the secure attribute along with none.

Also, I tried setting the Cookie's secure parameter to `TRUE` but it results in infinite redirects in my site. I don't want to implement the solution on site level as it will affect other cookies capabilities. I just want to do this for one particular cookie I am creating.

```
$cookie = new Cookie(self::SIGMACOOKIENAME, TRUE, 0, '/', NULL, TRUE, FALSE, TRUE, self::SAMESITE_NONE);

```

# Answer
If you're setting `SameSite=None`, you'll need to set the `Secure` attribute for HTTPS.

> If `SameSite=None` is set, the cookie `Secure` attribute must also be set (or the cookie will be blocked). https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#none
> 1 votes

---
Tags: 8, cookies
---