# Question
Title: Making images go to external sites in Slick carousel
I have a custom content type which collects one image and one URL per node. I have the Slick module along with Views set up to cycle through these images on the home page. I haven't been able to make the carousel images link to the external URLs. In Views I have this:

In the Global: Custom text field, I have this:

`<a href="{{ field_library_homepage }}">{{ field_library_photo }}</a>`

It's not using that markup. What's most confusing is that the images are displaying in the carousel. I have the photo field hidden and Drupal isn't using the custom text so I don't know how those images are being accessed.

What step have I missed to make this work? Thanks!

# Answer
> 1 votes
I found the solution. In the Slick settings, I set the Link to the custom text field. For most of the time I've been working on this that field did not show up in the Link dropdown. But suddenly it did.

At first it's misleading because the Views preview shows the original image with the smaller linked image overlaid. However, if you go back to where the block is placed, the images will appear correctly. Whew!

---
Tags: views
---


title: Filter with additional form element

text:
# Question
Title: Filter with additional form element
I have a custom views filter extending `Drupal\user\Plugin\views\filter\Name` that I am trying to add an additional form element. The existing filter is an autocomplete field that I need to add a checkbox element. I've tried updating `::valueForm`.

```
// Working code that creates the autocomplete field.

$existingElement = $form['value'];

$form['value'] = [
  '#tree' => TRUE,
  'existing_element' => $existingElement,
  'new_element' => [
    '#type' => 'checkbox',
    '#title' => t('Checkbox'),
    '#default_value' => FALSE,
  ],
];

```

It throws this error.

> Error: Cannot create references to/from string offsets in Drupal\Component\Utility\NestedArray::setValue() (line 155 of core/lib/Drupal/Component/Utility/NestedArray.php).

It seems to be related to the form state, but I have troubles in figuring out exactly what is missing.

# Answer
> 0 votes
You probably need to override the `valueValidate` method to tell it about the new structure:

```
protected function valueValidate($form, FormStateInterface $form_state) {
  $uids = [];
  if ($values = $form_state->getValue(['options', 'value', 'existing_element'])) {
    foreach ($values as $value) {
      $uids[] = $value['target_id'];
    }
    sort($uids);
  }

  $checkbox_value = $form_state->getValue(['options', 'value', 'new_element']);
  // Do something with $checkbox_value here as you're going to lose it

  $form_state->setValue(['options', 'value'], $uids);
}

```

---
Tags: 8, views, forms
---


# Question
Title: How can I preprocess pager links for a view display?
I've created a custom Drupal 7 block view that uses a mini pager. I need to display the *pager-previous* and *pager-next* links as images, and replace the *pager-current* link with some text. Do I need to create templates for these three links? Do I need preprocess functions for each of them? What are the naming conventions for these templates and functions? They would be tied to a particular block display.

# Answer
For the mini pager, the Views module uses its own theme function, `theme_views_mini_pager()`, which uses the more generic theme functions for the previous, next, and current links. There isn't a template file for that theme function, as the theme function itself is returning the markup.

With `hook_preprocess_views_pager()`, you could change the values contained in `$vars['tags'][1]` and `$vars['tags'][3]`, which by default are the `'‹‹'` and `'››'`, but those are passed to a theme function, which means you are someway limited in what you can do.

```
$li_previous = theme('pager_previous', array(
  'text' => isset($tags[1]) ? $tags[1] : t('‹‹'),
  'element' => $element,
  'interval' => 1,
  'parameters' => $parameters,
));
if (empty($li_previous)) {
  $li_previous = " ";
}
$li_next = theme('pager_next', array(
  'text' => isset($tags[3]) ? $tags[3] : t('››'),
  'element' => $element,
  'interval' => 1,
  'parameters' => $parameters,
));
if (empty($li_next)) {
  $li_next = " ";
}
$items[] = array(
  'class' => array(
    'pager-previous',
  ),
  'data' => $li_previous,
);
$items[] = array(
  'class' => array(
    'pager-current',
  ),
  'data' => t('@current of @max', array(
    '@current' => $pager_current,
    '@max' => $pager_max,
  )),
);
$items[] = array(
  'class' => array(
    'pager-next',
  ),
  'data' => $li_next,
);

```

You can implement `hook_theme_registry_alter()` to replace that theme function with your own. In this case, you have complete control over the output; you could even tell Drupal to use a template file.

Keep in mind that `theme_views_mini_pager()` is used for mini pager of every view. For what I can see, there isn't any value passed in `$vars` that makes understand for which view the mini pager is output.
Given the lack of documentation on the values passed in `$vars`, I would check what is passed in `$vars`. It may be that one of those values is the view ID, or machine name. The values documented in the theme functions for the previous, next, and current links are the following.

* element: An optional integer to distinguish between multiple pagers on one page
* interval: The number of pages to move backward when the link is clicked
* parameters: An associative array of query string parameters to append to the pager links
> 2 votes

---
Tags: 7, views
---


title: How To Display YouTube Channel On Page

text:
# Question
Title: How To Display YouTube Channel On Page
I'm attempting my first Drupal site and would like to show a simple listing of the 5 most recent YouTube videos submitted (http://gdata.youtube.com/feeds/api/standardfeeds/most\_recent?max-results=5). I've been struggling with this for almost a week now and cannot get what I want.

I've tried Feeds and the YouTube parser and I've tried the Media Module as described here. I can get the 5 most recent videos imported as separate nodes, but I want to just be able to list them, embedded, on the single page.

Any help would be greatly appreciated. I'm new to Drupal and really looking for a walk-through at this point. I'm using Drupal 7.19.

Thanks!

# Answer
> 0 votes
Did you try Aggregator? It's the first one listed on the modules page then on the configuration page it's call Feed Aggregator.

I then use Views to style my results.

Hope this helps!

# Answer
> 0 votes
Come to think of it, if you can get the videos to show as nodes you should be able to create a view of those nodes so they are all on one page.

# Answer
> 0 votes
Did you import the URL to embed? If so, you just need to theme the imported entities outputting that URL in the right format. If using the Field UI to customize the view modes of these entities, modules such as Link iframe formatter may help.

# Answer
> 0 votes
From your Dashboard, navigate to Appearance » Widgets. Then, under Available Widgets, click on the YouTube Feed widget. Choose which area you'd like to display it on, and click on Add Widget to save your choice. After doing this, check out your website and see your channel feed nicely displayed on your sidebar.

---
Tags: nodes, files
---


# Question
Title: What does the 'version' keyword mean in .libraries.yml?
In `theme.libraries.yml`, libraries have a version key. It appears to be optional, but Drupal core libraries (`core.libraries.yml`) set the version key value as `version`. What does this keyword mean?

so :

* Why we use the version keyword ?
* When should I change the version keyword?

# Answer
> 4 votes
> Why should I use it?

It is used as an identifier for your libraries. Just like any project/package is tagged in different versions. For eg: jQuery 3.5.1 is slightly different from 3.0.0. The difference could be anything, from API change, new features, bug fixes, etc. Thus we need a way to identify the changes that happened to our library we created. So that we can make some conscious decisions. Another example. Suppose there is a 3rd party js that is having issues with another library of a specific version. So during the install, we can check if the other library has library greater than required.

> When should I change its value?

Ideally after every deployment if any change to the library has occurred. So what Drupal does is, it happens the version number to each file in that library when attaching that library to any page. For example: if my library has a css file called custom.css and the version number is say 1.0.0. So, the way it will get attached to the page will be like `/path/to/theme/css/custom.css?v=1.0.0`. This is so far ok. But ideally on prod environments there are reverse proxies which caches these files. Suppose if we make any new changes to these files and even if we clear the cache, the files will still be served from CDN, thus we also need to make sure if any change has happened on these files, it makes sense to also increase the library version number. Just as you would do with creating a new tag for a new release for any project.

If we give the version as `VERSION`. Then drupal sets its version = `\Drupal::VERSION` the current drupal core version.

---
Tags: 8
---


# Question
Title: How to change sender email Id using hook_mail_alter
How to change the sender email id for some emails, using hook\_mail\_alter. The default SMTP configured email ID is 'test@myfirstdomain.com'

The subject gets altered correctly using the hook\_mail\_alter, however, the email which I receive is still from the default configured email 'test@myfirstdomain.com'.

```
function test_mail_alter(&$message) {
 switch ($message['key']) {
  case 'activation':

    $from = "test@myseconddomain.com" ;
    $message['from'] = $from;
    $message['headers']['From'] = $from;
    $message['headers']['Sender'] = $from;
    $message['headers']['Return-Path'] = $from;
    $message['subject'] = 123;
    break;
}

```

}

# Answer
> -4 votes
According to the documentation:

```
/**
 * Alter an email message created with MailManagerInterface->mail().
 *
 * Hook hook_mail_alter() allows modification of email messages created and sent
 * with MailManagerInterface->mail(). Usage examples include adding and/or
 * changing message text, message fields, and message headers.
 *
 * Email messages sent using functions other than MailManagerInterface->mail()
 * will not invoke hook_mail_alter(). For example, a contributed module directly
 * calling the MailInterface->mail() or PHP mail() function will not invoke
 * this hook. All core modules use MailManagerInterface->mail() for messaging,
 * it is best practice but not mandatory in contributed modules.
...

```

Can we check if the mail is sent `MailManagerInterface->mail()` like this and not any other way.

---
Tags: 8, hooks, emails
---


# Question
Title: How can I have node pages with Fivestar or comment fields cached properly?
I was struggling with high page load time for my node pages when I realized that the problem was due to content pages not being cached (html render cache). The page is rebuilt after every single request. With some hit and trial, I realized that fields that have form elements, in my case, Fivestar widget and also the comment form at the bottom of the page prevent page from getting cached. Either of these fields cause this problem.

When I remove those two fields, page starts to get cached.

Has anyone else dealt with a similar issue? What is the best recommended approach to make sure the page continues to get cached?

# Answer
I realized this was an issue because I was using the Honeypot module. Honeypot disables caching on all pages where there is a form. I updated the setting in the module to exclude node pages and it fixed the issue.
> 0 votes

---
Tags: 8, caching
---


# Question
Title: Get image file values in $form_state in media entity form
I am trying to get the values from an uploaded image inside a media entity during form submit.

Where my approach doesn't work:

1. When first uploading an image in the `media_image_add_form` form.
2. When editing an existing media entity and removing, then uploading a new image and trying to save.

My validation only works when editing and submitting an existing media entity (without changing the uploaded image file).

Here is my entire code for brevity, though it may be long, `MYMODULE.module`:

```
/**
 * Implements hook_form_alter().
 */
function MYMODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {

  if ($form_id == 'media_image_add_form' || $form_id == 'media_image_edit_form') {

    if ($form_state->getFormObject()->getEntity()->get("field_media_image")->entity) {

      $form['#validate'][] = '_MYMODULE_validate';
    }
  }
}

/**
 * Validates submission values in the FORM_ID() form.
 */
function _MYMODULE_validate(array &$form, FormStateInterface $form_state) {

  // $imageEntity = File::load($form_state->getValues()['field_media_image'][0]['fids'][0]); // Tried File::load here as well.
  $imageField = $form_state->getFormObject()->getEntity()->get("field_media_image");
  $imageEntity = $imageField->entity;
  $imageFileSize = $imageEntity->getSize();
  $imageFileMime = $imageEntity->getMimeType();
  $imageFileName = $imageEntity->getFilename();
  $isIssue = FALSE;
  $showConditionalMessage = FALSE;
  $ciuMessage = "";
  $ignoreWarnings = $form_state->getValues()['field_ignore_warnings']['value']; // Field set on media image entity type.

  // Conditional issue.
  if ($ignoreWarnings === 0 && $imageFileMime === "image/jpeg" && $imageFileSize / 1000 > 150) {
    $isIssue = TRUE;
    $showConditionalMessage = TRUE;
    $ciuMessage .= "<p>Conditional: This JPG file size is larger than 150kb, have you optimized this JPG image?</p>";
  }

  // Conditional issue.
  if ($ignoreWarnings === 0 && $imageFileMime === "image/png" && $imageFileSize / 1000 > 200) {
    $isIssue = TRUE;
    $showConditionalMessage = TRUE;
    $ciuMessage .= "<p>Conditional: This PNG file size is larger than 200kb, have you optimized this PNG image?</p>";
  }

  // Non-conditional issue.
  if (strpos($imageFileName, ' ') !== false) {
    $isIssue = TRUE;
    $ciuMessage .= "<p>Filenames cannot contain spaces.</p>";
  }

  // Non-conditional issue.
  if (strtolower($imageFileName) !== $imageFileName) {
    $isIssue = TRUE;
    $ciuMessage .= "<p>Filenames need to be in all lowercase.</p>";
  }

  if ($isIssue) {
    if ($showConditionalMessage) {
      $ciuMessage .= '<small>To ignore conditional errors, check the "Ignore conditional errors" checkbox below.</small>';
    }
    $form_state->setErrorByName('title', new FormattableMarkup($ciuMessage, []));
  }
}

```

One caveat for using `hook_form_alter()` is that some of the errors are conditional, and I would like to provide a field on the media entity type to allow ignoring some of the errors.

How can I get the uploaded file/values in `$form_state` when adding an image to a new media entity, or adding a new image to an existing media entity?

# Answer
Normally you use a ConstraintValidator for validating entities. In this case core invokes a hook so that you can add your own error messages to the existing file validation process:

```
function hook_file_validate(Drupal\file\FileInterface $file) {
  $errors = [];

  if (!$file->getFilename()) {
    $errors[] = t("The file's name is empty. Please give a name to the file.");
  }
  if (strlen($file->getFilename()) > 255) {
    $errors[] = t("The file's name exceeds the 255 characters limit. Please rename the file and try again.");
  }

  return $errors;
}

```

About the caveat for using form alter. You can add custom `#upload_validators`to the image widget. Add settings if necessary:

```
$element['#upload_validators']['my_custom_file_validator'] = [$my_setting];

```
> 1 votes

---
Tags: 8, forms
---


title: Migrating user accounts to Okta

text:
# Question
Title: Migrating user accounts to Okta
I'm trying to migrate users exported from Drupal into Okta using the /api/v1/users API (specifically \[creating users with import hash\]\[1\]), and am stuck, and desperate for help as I'm late on a project now because I haven't cracked this issue.

FYI

1. I posted this to both Okta forum: https://devforum.okta.com/t/migrating-users-from-drupal-7-to-okta/13103
2. and Drupal forum: https://www.drupal.org/forum/support/post-installation/2021-02-27/migrating-users-from-drupal-7-to-okta
3. I also contacted support@okta.com who weren't able to offer any further advice
4. And pestered a bunch folk in various places on Slack and Discord.

I think the core issue is that I'm not getting the 'right' value for the hash from the Drupal pass string.

Here's an example of a user:

{ "name" : "m.nick", "first": "Nick", "last" : "M", "mail" : "m.nick@gmail.com", "pass" : "$S$D9./psEr4CRGa61wFXVVxPA4sdxK4IRWPuWJMbbkOHBQNnIoUwOb", }

I believe the $S$ means SHA-512 was used by Drupal, the D means 15 rounds of hashing were performed, character 4-12 are the salt and the rest of the string is the hash?

Here's how I get the settings, salt and hash from the Drupal `pass`:

const hashType = pass.substring(0,3) const rounds = pass.substring(3,4) const salt = pass.substring(4,12) const hash = pass.substring(12)

I'm then calling `/api/v1/users?activate=true` with

profile: { firstName: first, lastName: last, email: mail, login: username }, credentials: { password: { hash: { algorithm: 'SHA-512', salt: salt, saltOrder: 'PREFIX', value: hash }}}

Which successfully creates the user, but on attempting sign in with the username: m.nick and the password that works on the old system, gets rejected with INVALID\_CREDENTIALS.

I've tried:

1. Switching the saltOrder to POSTFIX
2. base64 decoding the hash
3. base64 decoding and encoding the hash
4. Concat'ing the salt and the hash together
5. Every combination of the above

Please help, as I don't know what else to try, and I can't find any examples of Drupal user accounts being imported into Okta.

I'd be grateful for any advice you can offer. I assume that someone has previously migrated users from Drupal, and so I'm missing something.

# Answer
> 0 votes
The number of iterations is wrong. The stored value is the power of 2, encoded using a Base64 alphabet. `D` means 32768 iterations (215).
The other issue you have is that the hash and salt values are Base64 encoded, but using the same alphabet used by `cript()` (the POSIX function also part of the BSD Library). The PHP code Drupal uses to encode is the following one. It may be helpful to write the JavaScript code you need.

```
function _password_base64_encode($input, $count) {
  $output = '';
  $i = 0;
  $itoa64 = _password_itoa64();
  do {
    $value = ord($input[$i++]);
    $output .= $itoa64[$value & 0x3f];
    if ($i < $count) {
      $value |= ord($input[$i]) << 8;
    }
    $output .= $itoa64[$value >> 6 & 0x3f];
    if ($i++ >= $count) {
      break;
    }
    if ($i < $count) {
      $value |= ord($input[$i]) << 16;
    }
    $output .= $itoa64[$value >> 12 & 0x3f];
    if ($i++ >= $count) {
      break;
    }
    $output .= $itoa64[$value >> 18 & 0x3f];
  } while ($i < $count);
  return $output;
}

function _password_itoa64() {
  return './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
}

```

The full code used from Drupal 7 to hash passwords is contained in the password.inc file. In particular check the following functions:

I cannot say what should be used for `saltOrder`, since that isn't used from Drupal code and it's specific for the platform to which you are migrating the users.

---
Tags: 7, users
---


# Question
Title: Count of nodes filter in views for a taxonomy with depth
sorry for my English.

In views, Drupal 8/9, is it possible to have the count of nodes for a taxonomy-term with depth? I would like to have it for the filters in views.

I can't find any modules to get this information. Maybe I don't know how to look or a complex module gives this possibility but I couldn't find it.

Aggregation doesn't really help me. Performance is not a problem.

# Answer
> 0 votes
We have to write a module, something like this

/modules/childs\_count/childs\_count.views.inc

```
function childs_count_views_data()
{

  $data['taxonomy_term_field_data']['childs_count'] = array(
    'title' => t('Childs count'),
    'help' => t('Get the number of childs in taxo.'),
    'field' => array(
      'id' => 'childs_count'
    ),
    'filter' => [
      'id' => 'childs_count_filter',
    ],
  );

  return $data;

}

```

/modules/childs\_count/childs\_count.module

```
//to do add limit and type..
function childs_count_query($depth = 5)
{
  if ($depth < 1) {
    $depth = 1;
  }
  $sql = "(
  SELECT COUNT(nid) FROM node_field_data WHERE node_field_data.nid IN (
    SELECT tn.nid AS nid FROM taxonomy_index tn
            LEFT JOIN taxonomy_term__parent th ON th.entity_id = tn.tid
            LEFT JOIN taxonomy_term__parent th1 ON th.parent_target_id = th1.entity_id";
  foreach (range(1, $depth - 1) as $level) {
    $sql .= "\n\tLEFT JOIN taxonomy_term__parent th" . ($level + 1) . " ON th" . $level . ".parent_target_id = th" . ($level + 1) . ".entity_id\n";
  }

  $sql .= "WHERE (tn.tid = taxonomy_term_field_data.tid)";
  foreach (range(1, $depth) as $level) {
    $sql .= "\nOR (th$level.entity_id = taxonomy_term_field_data.tid)";
  }
  $sql .= ")\n)\n";

  return $sql;
}

```

/modules/childs\_count/src/Plugin/views/field/fieldChildsCount.php

```
namespace Drupal\childs_count\Plugin\views\field;

use Drupal\views\Plugin\views\field\NumericField;

/**
 * Field handler for search snippet.
 *
 * @ingroup views_field_handlers
 *
 * @ViewsField("childs_count")
 */
class ChildsCount extends NumericField
{

  public function query()
  {

    $this->field_alias="comptage";
    $this->query->addField(NULL, childs_count_query(), $this->field_alias);

  }

}

```

/modules/childs\_count/src/Plugin/views/filter/ChildsCountFilter.php

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

use Drupal\Core\Form\FormStateInterface;
use Drupal\views\Plugin\views\filter\NumericFilter;

/**
 * Defines a filter for filtering on numeric values.
 *
 * @ingroup views_filter_handlers
 *
 * @ViewsFilter("childs_count_filter")
 */
class ChildsCountFilter extends NumericFilter
{

  public function query()
  {
    $this->ensureMyTable();
    $where = $this->operator . ' ' . $this->value['value'];
    $this->query->addWhereExpression($this->options['group'], childs_count_query() . " $where");
  }

  /**
   * {@inheritdoc}
   */
  public function operators()
  {
    $operators = parent::operators();
    unset($operators['regular_expression']);
    unset($operators['between']);
    unset($operators['not between']);
    return $operators;
  }

  protected function valueForm(&$form, FormStateInterface $form_state)
  {
    parent::valueForm($form, $form_state);
    unset($form['value']['min']);
    unset($form['value']['max']);
  }
}

```

I will do it. it's not good for server performance, but it suits me. Thanks for your help.

# Answer
> 1 votes
There are several ways to do it, based on how you are going to manage your content.
But for your problem I guess the solution can be this:

```
1. In Fileds: add Taxonomy term: Name
2. In Relationships, add a Taxonomy term: Content with term
3. Add a contextual filter for Taxonomy term: Name
    3a. Choose 'Display a summary'
    3b. Choose 'Display Record count with link'.

```

***Here is several resources that can help:***
Views and node count for taxonomy terms
How to display number of nodes with current term?
Showing how many nodes are associated with a term
Display node count per node reference field

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


# Question
Title: Fatal error: Class 'Drush\Log\Logger' not found
Hi I'm getting this Drush error no matter which command I try.

> Fatal error: Class 'Drush\Log\Logger' not found

How can I fix it?

I haven't been able to find other users reporting the same issue. I'm using Drush 8.

# Answer
> 9 votes
I had the exact same problem after updating core with drush (installed with composer). This is not something you should do if drupal is installed in the root directory, I've now learned. Reinstalling drush fixed the issue for me.

```
composer require drush/drush

```

Next step, I guess if we want to avoid this in the future, is to either move drupal to a subdirectory (as a dependency) or uninstall drush as a composer package and install it globally instead (the old fashioned way).

# Answer
> 0 votes
This is causing due to latest drush 10.2.2 and Drupal 8.8.5, I installed drush9 on my project composer require drush/drush:^9 And it fixes my issue.

# Answer
> 0 votes
I faced this problem recently on Acquia Cloud running Drush 10.4.0 and Drupal 8.9.13. The solution was to SSH into the application and run `drush cr`.

You need to follow the instructions here to ensure the `--root` option is specified correctly: https://docs.acquia.com/cloud-platform/manage/ssh/drush/

---
Tags: drush
---


title: PostCreate/Hook on User Registration

text:
# Question
Title: PostCreate/Hook on User Registration
I want to hook into user registration but there doesn't seem to be any hook for it anymore. This is what I see from Drupal 8.8:

*hook\_user\_cancel
hook\_user\_cancel\_methods\_alter
hook\_user\_format\_name\_alter
hook\_user\_login
hook\_user\_logout*

Furthermore I can't find any events for it neither.

So how can I hook into user registration?

# Answer
> 4 votes
It depends from what exactly the code needs to achieve. `hook_form_alter()` and `hook_form_FORM_ID_alter()` are still used from Drupal 9, and they can be used to hook into account registration before users can enter values for the account to create. They should not be used to add an entity field, or add a validation handler for an entity, for which `hook_entity_base_field_info()` and `hook_entity_bundle_field_info()` (to add entity fields to an entity) or `hook_entity_type_alter()` (to add constrains to validate an entity) are preferable.

If you are instead looking for the Drupal 9 equivalent of Drupal 7 `hook_user_insert()`, `hook_user_update()`, and `hook_user_presave()`, which are invoked after the users entered the account data (and they should not be used to invalidate the entered data), they are still used, but they are documented under `hook_ENTITY_TYPE_insert()`, `hook_ENTITY_TYPE_update()`, and `hook_ENTITY_TYPE_presave()`. When you implement those hooks, you replace *ENTITY\_TYPE* with *user*, for the User entity. This means that the name of the function implementing those hooks for the User entity doesn't change respect of the function name used in Drupal 7; it's just a matter of documentation.

Note also that the generic hooks, invoked for every entity implemented in Drupal, for example `hook_entity_insert()` are still used in Drupal 9. (See `hook_entity_insert()`.) The documentation page for that hook for Drupal 9 contains a reference to the equivalent hook invoked for a single entity type (*See also `hook_ENTITY_TYPE_insert()`*, written on two lines).

### Further reading

# Answer
> 3 votes
Users are entities in Drupal 8/9. So you have hook\_entity\_insert and hook\_entity\_presave.

Just replace `entity` with `user`.

Also, note that `hook_entity_presave` is called on every entity save, so if you want to do preprocessing before saving a user on registration, you need to check if the user is new:

```
function MYMODULE_user_presave(UserInterface $user) {
  if ($user->isNew()) {
    // Do stuff for newly registered users.
  }

```

---
Tags: users, 9
---


# Question
Title: Get the value of a field from an entity reference
I have a content type (*Actuality*) with an entity reference field to another content type (*Event*). In the referenced content type, I have a *field\_date* field I want to print in the *node--actuality.html.twig* template file. I tried using `{{ node.field_event_associated.field_date }}`, but it doesn't work.

How can I print the field value of a referenced entity?

# Answer
With a *field\_event\_associated* node field, you can get its value with `{{ node.field_event_associated.value }}`. That doesn't work for entity reference fields, for which you need to use `{{ node.field_event_associated.entity.field_date.value }}`.
> 16 votes

# Answer
If you want to **render a properly formatted single field of a referenced entity** you'll simply have to use the **|view** filter on the desired field of the referenced node.

Let's say the `field_customer` on my parent node references a customer content type entity that holds the customer's address in `field_address`.

```
{{ node.field_customer.entity.field_address|view }}

```

Use the referenced entity's display settings to define the format of the field you want to render.

Example on drupal.org
> 9 votes

# Answer
The value you're mostly looking for would be the title value:

```
{{ node.field_organisation_reference.entity.title.value }}

```
> 2 votes

# Answer
Output entity reference field value and create url on twig.

entity reference value : {{ node.field\_name.entity.title.value }}

entity reference url : {{ url('entity.node.canonical', {'node': node.field\_name.target\_id}) }}
> 1 votes

---
Tags: 8, entities
---


# Question
Title: Decoupled login: How do I get the session cookie via JavaScript?
In the Medium app, if you go to the settings tab, you can change some of the settings inside the app. But, if you try to change your email notification settings, it opens up a web browser inside the app and automatically logs you in to the Medium website so that you can change your settings there.

I want to do the same thing in my Ionic React app that talks to a Drupal 8.9 server.

My Drupal site is fully functional and offers some complicated forms; my Ionic app is more limited and I don't want to re-implement everything. So if the user needs a rare or unusual feature, I want to let them open up my website (and automatically log them in) from within the app.

I use JSON:API to query the database, and Simple OAuth (OAuth2 to handle logging in.

So, I somehow need to get the Drupal session cookie when the user logs in to my site via OAuth through the Ionic app (mobile app on Android + iOS).

How can I get a session cookie to log the user in to the actual Drupal site when logging in from a decoupled app?

**Desired flow**

1. User logs in inside the Ionic app.
2. User does stuff inside the app.
3. User sometimes clicks a link to my Drupal site and is still logged in to the site because I am using a Drupal session token.

The problem with OAuth is that if I click a link to a page on my Drupal site (outside my app), then I am not logged in on that page.

In my case, I really need to be able to easily redirect from inside my app to the Drupal site and stay logged in, so I want to use the Drupal session cookie for this.

Where I'm stuck is how do I get the session cookie from Drupal using Javascript?

The jsonapi documentation gives this example:

```
`curl --header "Content-Type: application/json" -c cookie.txt
--request POST "https://example.com/user/login?_format=json"
--data '{"mail": "test@example.com", "pass":"password"}'`

```

When I do this, here's the content of **cookie.txt**

```
 Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.

#HttpOnly_.example.com      TRUE    /       TRUE   1615666425      SESSf6f36d8c129ea800a6658d30964d3887    PTgk_Lgm9yLwQ3NhYtdexnexuKSJ-TItAWSkxPiUPoU

```

Cool, this is the drupal session cookie.

However, I only have access to Javascript, not curl, in React. Also, I'm thinking that I may be over-thinking this and there is a really simple way to get the session cookie that I have overlooked.

So, **how do I get the login session cookie via Javascript?**

I tried to do this with the Fetch API:

```
  async function login(email: string, password: string): Promise<void> {
    const loginPost = {
      mail: email,
      pass: password,
    };
    await fetch('https://www.example.com/user/login?_format=json', {
      method: 'POST',
      headers: new Headers({
        Accept: 'application/json',
      });
      body: JSON.stringify(loginPost),
      credentials: 'same-origin',
    })
      .then(handleErrors)
      .then((response) => response.json())
      .then((data) => {
        const expireLate = 'Thu Nov 26 2049 15:44:38';
        document.cookie = 'myJsonObject=' + JSON.stringify(data) + ';expires=' + expireLate;
      })
      .catch((error) => Promise.reject(new Error(error)));
  }

```

Here's the content of the fetched cookie as shown in Chrome Dev Tools:

Name: `myJsonObject`

Value:

`{"current_user":{"uid":"152","mail":"test@example.com"},"csrf_token":"bjaJpsNSEutjQW1BKZXxZbwaofuygF8M8vUitVvAJGo","logout_token":"27poFxhzClLA5WmYbDgql9n5v82Vc6CZBDNEztmBvb0"}`

This is completely different from the session cookie I expected and that is retrieved by curl. How do I get the Drupal session cookie in a way that I can log in to my site when it is opened up in a browser from the app?

When I enter the header and request info in Postman, I get the json cookie returned by fetch api as the output, but I also get the session cookie automatically somehow. This automatic saving of the Drupal session cookie is what I want in my Ionic login form, but I don't understand enough about how Drupal handles cookies to determine how to save/retrieve the session cookie.

**Background**

I understand that the best practice is "use OAuth 2 or JWT; they are more secure."

In fact, the Simple Oauth module has good documentation and I managed to set this up on my site using the Drupalize.me react tutorial.

# Answer
Here's one way to do it, but the conditions are pretty specific:

1. The app is built using Ionic.
2. The Ionic webapp is being hosted by the Drupal server.
3. The session cookie is only needed in the webapp (this will not work for mobile Ionic apps).

In my case, this was fine, because I wanted to redirect to my Commerce store on the webapp, but the mobile apps use IAP so they don't need that.

Here's the code:

```
  async function login(email: string, password: string): Promise<void> {
    const loginPost = {
      mail: email,
      pass: password,
    };
    const formData = new FormData();
    formData.append('grant_type', 'email_registration');
    formData.append('client_id', updatedConfig.client_id);
    formData.append('client_secret', updatedConfig.client_secret);
    formData.append('scope', updatedConfig.scope);
    formData.append('mail', email);
    formData.append('password', password);
    await fetch(`${baseUrl}/oauth/token`, {
      method: 'POST',
      headers: basicHeaders,
      body: formData,
    })
      .then(handleErrors)
      .then((response) => response.json())
      .then((data) => saveToken(data))
      .catch((error) => Promise.reject(new Error(error)));
    // If we are in the web browser, make an additional log in request to get the session cookie.
    if (isPlatform('desktop') || (isPlatform('mobileweb'))) {
      await fetch(`${baseUrl}/user/login?_format=json`, {
        method: 'POST',
        headers: basicHeaders,
        body: JSON.stringify(loginPost),
        credentials: 'same-origin',
      });
    }
  }

```

Basically, it works like this:

1. Log in with Oauth2.
2. Check the platform (Ionic function). If we are using the webapp, post a login request to Drupal, which will return the session cookie.

Then you need to make sure you delete the session cookie on logout:

```
  function logout(): Promise<boolean> {
    localStorage.removeItem(updatedConfig.token_name);
    if (isPlatform('desktop') || (isPlatform('mobileweb'))) {
      fetch(`${baseUrl}/user/logout?_format=json`, {
        method: 'GET',
        headers: basicHeaders,
        credentials: 'same-origin',
      });
    }
    return Promise.resolve(true);
  }

```

I'm still working on improving this, but it's a starting point at least.
> 0 votes

---
Tags: 8, javascript, authentication-authorization
---


title: Why doesn't file load by URI?

text:
# Question
Title: Why doesn't file load by URI?
I have a file URI something like private://somefolder/myfile.pdf. Certain users don't have access to the file so I am trying to change that using hook\_file\_download($uri). In that code I need to load the file and the examples I have seen suggest:

```
  $files = \Drupal::entityTypeManager()
    ->getStorage('file')
    ->loadByProperties(['uri' => $uri]);

```

but when I do this, $files is empty.

The file is there, and as an admin I can open the file. Also, if I use this code:

```
  $files = \Drupal::entityTypeManager()
    ->getStorage('file')
    ->loadByProperties(['fid' => 12345]);

```

it does load the file.

Also, if I strip off the private://somefolder/ and loadBy filename, it also works.

What am I missing here?

Possible answer and bug in core? Although the $uri which is passed to hook\_file\_download($uri) is in the format mentioned above (which does not work); if I try to load by uri using this:

```
private://somefolder\myfile.pdf (note last last slash in Windows format)

```

then it does work.

# Answer
I ended up with this:

```
  $uri = preg_replace("~\/(?!.*\/)~", DIRECTORY_SEPARATOR, $uri);
  /* @var \Drupal\file\FileInterface[] $files */
  $files = \Drupal::entityTypeManager()
    ->getStorage('file')
    ->loadByProperties(['uri' => $uri]);

```

but pretty sure this is a bug in core.
> -1 votes

---
Tags: 8, files
---


# Question
Title: Do i need write access to the files directory to migrate d7_file?
I'm migrating a site from drupal 7 to 8. It has many many media files. Something like 6TB worth. And adding daily. So i want to do the db migration on my machine (not the webserver), work out kinks and modify custom code to work w/ d8, then do the real thing on the live machine over a slow weekend when i have all the steps worked out.

In the migration process, i've gotten to drush migrate-upgrade d7\_node, and it (on initial run, with only a token few files in /sites/default/files) created a handful of db entries in file\_managed. So i sshfs mounted the live files directory read only from my machine and re-ran migrate-upgrade d7\_node from the restored db. Now it doesn't create anything in the file\_managed table, so i suspect it's not working, but it gives no errors, and some grepping doesn't readily yield the code that does this work. I wouldn't mind hacking for this part only.

Hence the question. And what can i do alternatively to avoid copying 6TB of files for the preparatory migration?

Thanks.

# Answer
> 0 votes
Ok, i figured this one out. The magic lines are in /core/modules/migrate/src/Plugin/migrate/process/FileCopy.php

First, make sure source\_base\_path is correct in your config: Check drush mmsg d7\_file after migrate-upgrade d7\_node --limit=1 to see whether it is correctly finding the files. Use drush config:export and config:import to modify it til that works. Alter settings.php to put config/sync somewhere other than /sites/default/files

Second, mount the live site's public files dir read-only at /sites/default/files.

Third, modify /core/modules/migrate/src/Plugin/migrate/process/FileCopy.php around line 149 to comment out the action. Make it look like this:

    if (!is_dir($dir) || !is_writable($dir)) {
      if (!$this->fileSystem->prepareDirectory($dir, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS)) {
        throw new MigrateException("Could not create or write to directory '$dir'");
      }
    }

    $final_destination = $this->writeFile($source, $destination, $this->configuration['file_exists']);
    if ($final_destination) {
      return $final_destination;
    }
*/
      return $destination;```

Last, run drush migrate-upgrade d7_file

Enjoy.

---
Tags: 8, migrations
---


# Question
Title: View - show predetermined result set prior to exposed filter
**Standard behavior:** I have a view that has some filters exposed to the user. When the user first visits the page, the exposed filters are empty and the view just shows everything. When the user modifies a filter, the view shows a subset of the results based on their query.

**Ideal behavior:** When the user first visits the page, and have not performed a search using the exposed filters yet, I'd like the view to show a predetermined set of results... like a group of highlighted\* items that I'd want the user to see. Then they perform a search, and the view acts normally.

Is this possible?

---

**These "highlighted" items would be determined by a field in the node.*

# Answer
> 0 votes
All you need to do is:

1. Create a Boolean field to mark highlights (Let's say `field_highlights`)
2. Add a views filter for `field_highlight` with the following detail:

2.1. Not exposed

2.2. Operation: Is one of

2.3. Options: Select both 'On' and 'Off'
3. Write a bit of magic code which:

3.1. Checks if the user has not used the exposed filters yet

3.2. Alters the options for our filter to only show 'On' values

Last part sounds difficult? Actually it's not:

```
    <?php

    /**
     * Implements hook_views_pre_view().
     *
     * Applys a custom filter if there is no filter applyed by user
     *
     */
    function YOURMODULE_views_pre_view(&$view, &$display_id, &$args) {
        // Make sure we are altering the right view
        if ($view->name == 'YOUR_VIEW_NAME') {
            // Get the user input for exposed filters
            $user_input = $view->get_exposed_input();
            // Check if there is no user input
            if (empty($user_input)) {
                // The filter name for selecting highlighted items
                $filter_name = 'field_highlighted_value'; // Figure the filter name by looking at the exported views
                // Getting the filter array
                $filter = $view->get_item($view->current_display, 'filter', $filter_name);
                // Setting the value to TRUE
                $filter['value'] = array(1=>'1');
                // Saving the changes to the filter
                $view->set_item($view->current_display, 'filter', $filter_name, $filter);
            }
        }
    }

```

# Answer
> 0 votes
## Use jQuery

Or you could create a simple jQuery script that is only loaded on this View which hides your results and shows an EVA or a block or mini panel, or whatever where your highlighted nodes are showing. Give your blocks etc the right classes and then look for when the user actually keys in values, selects an option or ticks a box. Once that happens, with jQuery hide the highlighted nodes and reveal the search results or better, let the results page slide in so that the highlighted nodes stay visible below the search results. I'll try it myself and let you know how it went.

---
Tags: views
---


# Question
Title: Display members with same taxonomy using Views
Users have a "school" term reference field. When user visits his own user page, I want him to see his classmates listed.

For example, imagine that I have 3 students from the same school. When student A `id:4` visits `user/4`, I want all student B and student C listed.

I can do this on term's page, `term/10`, but I could not figure out how to do it on user's page.

I believe it would have to be configured through contextual filter but I could not find a way yet.

Any help will be greatly appreciated!!

# Answer
1. Create a view block of users and show all the required fields.
2. Add a contextual filter for school.
3. Now here ideally we need some way to dynamically get the school id of the current logged in user. But we only get these kinds of values:
4. So in order to dynamically get the term id of the user's field. we can either write a custom hook `hook_views_pre_view` See its documentation and modify the correct `$arg` by loading the current user and getting the user's selected term for school. or
5. Create a custom views argument plugin, or use this module : https://www.drupal.org/project/user\_field\_value
> 0 votes

# Answer
This is a common request to list sibling nodes in Views. You can search to find other examples.

In your case:

1. Create Views listing all Users with Page or Block Display
2. Add a Relationship **Content referenced from field\_school** (or however it's called in your particular case), you can require it, this introduces the School into the Views.
3. Add another Relationship **Content using field\_school**, set it to **use the Relationship from the previous step**, you can require it. This is the reverse direction, pointing to all children that are pointing to this parent (School).
4. Add the Contextual Filter **User ID** and configure it:
Relationship **field\_school** (the second one)
`When the filter value is NOT available`
**Provide default value**
**User ID from route context**
`When the filter value IS available or a default is provided`
**Specify validation criteria**
**User ID**
5. If this is a Block Display place it on Child nodes and it will show other children that relate to the same Section. Don't forget to configure both the Block Visibility and Contextual settings.

If you're using a Page Display change your **Path** setting to `user/%user/[schoolmates]` (change the brackets to what you like) and **Menu** to `Menu tab` "\[Your tab name\]". This will add a Drupal tab on the user profile pages that shows this Views, listing content that is related to the terms chosen by the user in their profile settings.
6. To remove the current user from the list add another Contextual filter **User ID** and configure it with these options:
`When the filter value is NOT available`
**Provide default value**
**User ID from route context**
`More`
**Exlude**

To check the Contextual filter with Views Preview, enter the ID of the Users you want to simulate, and enter it for each Contextual filter.

If you have both the contextual filter that identifies siblings and the one that excludes the current user from the list (and the Child ID is 24) enter `24/24`.

If you want to see all the results, unaffected by Contextual filters enter `all/all`.
> 0 votes

---
Tags: 8, views
---


# Question
Title: What is the correct way to rename an uploaded file using tokens?
I am building a webform. I have a *Name* field that uses first and last name. I have an image upload field where I want to rename the image to *lastname-firstname.jpg*.

In the properties for the file upload, I selected *Rename files* for the pattern *\[webform:element:name:last\__title\]-\[webform:element:name:first\__title\]*.

When I test this using John Smith, the file is getting renamed, but it is being renamed to *last-name-first-name.png* instead of *smith-john.jpg*.

I'm guessing I'm doing something wrong with the pattern, but I don't know what.

This is the field definition.

```
name:
  '#type': name
  '#title': Name
  '#title__access': false
  '#first__title': 'First Name'
  '#middle__access': false
  '#last__title': 'Last Name'
  '#suffix__access': false
  '#degree__access': false

```

# Answer
> 1 votes
I had the same issue. The answer was buried way down in *Browse available tokens*.

I wanted to rename an uploaded file based on the responses to the *last\_name* and *first\_name* fields. The pattern that worked was *\[webform\_submission:values:last\_name\]\_\[webform\_submission:values:first\_name\]*.

---
Tags: webforms, tokens
---


title: Using TableSort without doing a query

text:
# Question
Title: Using TableSort without doing a query
Drupal core has the `Drupal\Core\Utility\TableSort` class which can be used to create tables with sortable columns. All examples in core however are based on `Drupal\Core\Database\Query\TableSortExtender` which providers table sorting for data coming from a database query.

I am looking to display data that is generated by custom code and is not originating from a query. How can I use the `TableSort` code directly in my controller?

This is the Drupal 8 version of the same question for Drupal 7. See the answers there for additional insights.

# Answer
`TableSort` has methods to retrieve the sorting order and the field being sorted directly from the query arguments. You can use the values returned by `::getSort()` and `::getOrder()` to do a custom sorting of your data.

In your render array you can use some (undocumented) options in the `#header` declaration to control the way the table is initially sorted:

* `field`: the name to use in the query arguments to indicate that the table should be sorted by this column.
* `sort`: one (and only one) of the columns can be given this option (with value either `asc` or `desc`). This will be the column that is sorted by default.
* `initial_click_sort`: this can be set to `desc` if the data should be sorted in descending order if the column header is initially clicked. This defaults to `asc` but for some data you want to show larger numbers at the top by default.

Here is an example of a controller using data from a custom array:

```
<?php

declare(strict_types = 1);

namespace Drupal\my_project\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Utility\TableSort;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;

/**
 * Demo of a table with sortable columns using data from a custom source.
 */
class SortableTableDemoController extends ControllerBase {

  /**
   * The Symfony request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * Constructs a new SortableTableDemoController.
   *
   * @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
   *   The request stack.
   */
  public function __construct(RequestStack $requestStack) {
    $this->requestStack = $requestStack;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container): self {
    return new static(
      $container->get('request_stack')
    );
  }

  /**
   * Returns a render array containing data about Linux distributions.
   *
   * @return array
   *   The render array.
   */
  public function linuxDistributionsTable(): array {
    $headers = [
      // The distribution label has the 'sort' option, making it the default.
      [
        'data' => $this->t('Distribution'),
        'field' => 'label',
        'sort' => 'asc',
      ],
      [
        'data' => $this->t('Initial release'),
        'field' => 'year',
      ],
      // Sorted from highest to lowest on initial click.
      [
        'data' => $this->t('Packages'),
        'field' => 'packages',
        'initial_click_sort' => 'desc',
      ],
    ];

    $data = [
      ['label' => 'Arch Linux', 'year' => 2002, 'packages' => 77264],
      ['label' => 'Debian', 'year' => 1993, 'packages' => 118326],
      ['label' => 'Red Hat', 'year' => 2002, 'packages' => 12155],
      ['label' => 'Gentoo Linux', 'year' => 2002, 'packages' => 29092],
      ['label' => 'OpenSUSE', 'year' => 2006, 'packages' => 76236],
      ['label' => 'Ubuntu', 'year' => 2004, 'packages' => 89403],
    ];

    // Sort the table according to the options passed in the query arguments.
    $request = $this->requestStack->getCurrentRequest();
    $sort = TableSort::getSort($headers, $request);
    $order_by = TableSort::getOrder($headers, $request)['sql'];

    usort($data, function (array $a, array $b) use ($sort, $order_by): int {
      $result = $a[$order_by] <=> $b[$order_by];
      return $sort === 'asc' ? $result : -$result;
    });

    return [
      'table' => [
        '#type' => 'table',
        '#header' => $headers,
        '#rows' => $data,
      ],
    ];
  }

}

```
> 6 votes

---
Tags: 8
---


# Question
Title: Basic kernel test fails with Type of Drupal\KernelTests\Core\Entity\EntityKernelTestBase::$modules must be array
Trying to port a Drupal 7 module to 9 with accompanying test and getting this error immediately when running it:

```
PHP Fatal error:  Type of Drupal\KernelTests\Core\Entity\EntityKernelTestBase::$modules must be array (as in class Drupal\KernelTests\KernelTestBase) in /var/www/html/docroot/core/tests/Drupal/KernelTests/Core/Entity/EntityKernelTestBase.php on line 12

```

The test:

```
class MyModuleTest extends EntityKernelTestBase {

  use NodeCreationTrait;

  /**
   * @var \Drupal\mymodule\Query\YearsQuery
   */
  protected $query;

  /**
   * @var array $modules
   */
  protected static $modules = [
    'node',
    'mymodule',
    'mymodule_test',
  ];

  /**
   * {@inheritdoc}
   */
  protected function setUp() : void {
    parent::setUp();
    ...

```

I checked around some of the core classes - the $modules declaration looks the same. Note that I am using PHPUnit 9.

# Answer
From KernelTestBase:

```
 /**
  * Modules to enable.
  *
  * The test runner will merge the $modules lists from this class, the class
  * it extends, and so on up the class hierarchy. It is not necessary to
  * include modules in your list that a parent class has already declared.
  *
  * @see \Drupal\Tests\KernelTestBase::enableModules()
  * @see \Drupal\Tests\KernelTestBase::bootKernel()
  *
  * @var array
  */
 protected static $modules = [];

```

You'll need to match this declaration in your own code (though you can add to the array).
> 0 votes

# Answer
Looks like my problem stemmed entirely from using the wrong KernelTestBase include. My IDE suggested KernelTestBase as I was typing, and I did not look at the path:

```
use Drupal\Tests\token\Kernel\KernelTestBase;

```

vs

```
use Drupal\KernelTests\KernelTestBase;

```

send coffee.
> 0 votes

---
Tags: testing, 9
---


# Question
Title: How to unpublish nodes which are missing in migration source?
I have a CSV file with two rows. I executed the migration and two nodes are imported.

Now I deleted one row from the CSV and execute the migration again.

I now want to unpublish the node which is missing in the CSV.

Is it possible? How will I do that?

# Answer
> 4 votes
I have used an EventSubscriber for this. Here is my code.

```
/**
 * {@inheritdoc}
 */
public static function getSubscribedEvents() {
  $events = [];
  $events[MigrateEvents::PRE_IMPORT][] = ['archiveMissingNodes'];
  return $events;
}

/**
 * Archives the missing contact persons.
 *
 * @param \Drupal\migrate\Event\MigrateImportEvent $event
 *   The migration import event.
 *
 * @throws \Drupal\Core\Entity\EntityStorageException
 */
public function archiveMissingNodes(MigrateImportEvent $event) {
  $migration = $event->getMigration();

  if ($migration->id() === 'my_migration_id') {
    $id_map = $migration->getIdMap();
    $id_map->prepareUpdate();

    // Clone so that any generators aren't initialized prematurely.
    $source = clone $migration->getSourcePlugin();
    $source->rewind();
    $source_id_values = [];

    while ($source->valid()) {
      $source_id_values[] = $source->current()->getSourceIdValues();
      $source->next();
    }
    $id_map->rewind();

    while ($id_map->valid()) {
      $map_source_id = $id_map->currentSource();

      $destination_ids = $id_map->currentDestination();

      if (!empty($destination_ids['nid'])) {
        $node = $this->nodeStorage->load($destination_ids['nid']);

        if ($node instanceof NodeInterface) {
          if (!in_array($map_source_id, $source_id_values, TRUE) && $node->get('moderation_state')->getString() !== 'archived') {
            $node->setNewRevision(TRUE);
            $node->set('moderation_state', 'archived');
            $node->set('revision_log', '');
            $node->setRevisionCreationTime($this->time->getRequestTime());
            $node->setRevisionUserId($this->currentUser->id());
            $node->setRevisionTranslationAffected(TRUE);
            $node->save();
          }
        }
      }

      $id_map->next();
    }
  }
}

```

# Answer
> -1 votes
Follow these steps

1. modify your migration code
2. first of all - run a select query to fetch all the nids of that content type or bundle for which you are migrating the data
3. next, run migration
4. identify the nodes which are not part of migration but exist in your select query
5. in while loop, load these nodes
6. mark them as unpublished
7. save these nodes

done!

---
Tags: 8, migrations
---


# Question
Title: How to display a field when a media is uploaded to the media library field?
I have block settings form where I have a media library field.

```
 public function blockForm($form, FormStateInterface $form_state) {
    $form = parent::blockForm($form, $form_state);
    $user_input = $form_state->getUserInput();
    $my_field = $user_input['settings']['my_field'] ?? $this->configuration['my_field'] ?? NULL;

    $form['my_field'] = [
      '#type' => 'media_library',
      '#allowed_bundles' => ['my_bundle'],
      '#title' => $this->t('Upload'),
      '#default_value' => $this->configuration['my_field'] ?? '',
      '#required' => TRUE,
      '#ajax' => [
        'callback' => [$this, 'ajaxCallback'],
        'event' => 'updateMediaLibrarySelection'
        'wrapper' => 'test-field',
      ],
    ];

    $form['test'] = [
      '#type' => 'textfield',
      '#title' => 'test',
      '#prefix' => '<div id="test-field">',
      '#suffix' => '</div>',
    ];

    if (empty($my_field)) {
      $form['test']['#wrapper_attributes']['class'][] = 'visually-hidden';
    }

    return $form;
  }

public function ajaxCallback(array &$form, FormStateInterface $form_state): array {
    return $form['settings']['test'];
  }

```

but my ajaxCallback method never called and the test field is always hidden.

# Answer
I did with javascript because the field type `media_library` is not an actual input field.

I overrided the `setMediaUploadFieldValue` jQuery function of the `media_library_form_element` module.

```
(($, Drupal) => {
  Drupal.behaviors.VideoComponent = {
    attach: () => {
      $.fn.setMediaUploadFieldValue = (data, element) => {
        const mediaElement = document.querySelector(element);
        const currentValue = mediaElement.value;

        mediaElement.value = `${currentValue}${
          currentValue === "" ? "" : ","
        }${data}`;

        try {
          fetch(`${my_url}`)
            .then(response => response.json())
            .then(result => {
              if (result) {
                // Do something
              }
            });
        } catch (error) {
          return false;
        }
      };
    }
  };
})(jQuery, Drupal);

```
> 0 votes

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


# Question
Title: How to translate content of the composite element settings?
I have created a composite element where I added a custom textarea field in the element settings.

I have added that element in a webform, filled that textarea and saved the webform.

Now I want to translate the webform, But when I go the webform translations, I am unable to translate the value of that text area.

Is there any way to translate the value of that text area?

```
/**
 * Provides a booking element.
 *
 * @WebformElement(
 *   id = "my_element",
 *   label = @Translation("My element"),
 *   category = @Translation("Composite elements"),
 *   multiline = TRUE,
 *   composite = TRUE,
 *   states_wrapper = TRUE,
 * )
 */
class Myelement extends WebformCompositeBase {
  public function form(array $form, FormStateInterface $form_state): array {
    $form = parent::form($form, $form_state);

    $form['element']['booking_email'] = [
      '#type' => 'textarea',
      '#title' => $this->t('some content'),
      '#weight' => '0',
    ];

    return $form;
  }
}

```

Here is the backend of the element settings.

And here is the webform translation interface. I can't see my textarea field so that I can translate its content. I only see the composite element key and title.

# Answer
> 0 votes
You need to create a schema config file to make them translatable.

I have done it like this by creating `my_module.plugin.handler.schema.yml` file in my `my_module/config/schema` directory.

```
webform.handler.my_element:
  type: mapping
  label: Booking email
  mapping:
    booking_email:
      label: 'Something'
      type: text

```

---
Tags: 8, webforms
---


# Question
Title: How do I update the section component configuration?
How to update a component in the node's layout builder? I have used the following code.

```
$node = \Drupal\node\Entity\Node::load($nid);
$layout = $node->get('layout_builder__layout');
$sections = $layout->getSections();
foreach ($sections as $key => $section) {
      $components = $section->getComponents();
      foreach ($components as $component) {
        if ($component instanceof SectionComponent && $component->getPluginId() === 'myplugin_id') {
          $configurations = $component->get('configuration');
          $configurations['label_display'] = "0";
          $component->setConfiguration($configurations);
        }
      }
}

```

But now I don't know how to update the section and layout of the node.

Because `$section->setComponent($component)` is a protected method.

# Answer
I have done it like this.

```
$node = \Drupal\node\Entity\Node::load($nid);
$layout = $node->get('layout_builder__layout')->getValue();
$sections = $layout->getSections();

foreach ($sections as $key => $section) {
  $components = $section->getComponents();
  foreach ($components as $component) {
    if ($component instanceof SectionComponent && $component->getPluginId() === 'myplugin_id') {
       $configurations = $component->get('configuration');
       $configurations['label_display'] = "0";
       $component->setConfiguration($configurations);
    }
  }
}

$node->set('layout_builder__layout', $layout);
$node->save();

```

For Drupal 9 (Other way around):

```
$nid = 1;
$node = Node::load($nid);
$layout = $node->get('layout_builder__layout')->getValue();

if (!empty($layout)) {
  foreach ($layout as $section) {
    if (isset($section['section']) && $section['section']->getLayoutId() == 'mylayout_id') {
      $components = $section['section']->getComponents();
      foreach ($components as $component) {
        if ($component instanceof SectionComponent && $component->getPluginId() === 'myplugin_id') {
          $configurations = $component->get('configuration');
          $configurations['label_display'] = "0";
          $component->setConfiguration($configurations);
        }
      }
    }
  }
}

$node->set('layout_builder__layout', $layout);
$node->save();

```
> 2 votes

---
Tags: 8, nodes, configuration, layout-builder
---


# Question
Title: Module getting "$entity" argument error with hook_entity_presave()
I am trying to create a module in Drupal 8 (8.9.11) and this module uses the function hook\_entity\_presave in order to update a node / entity programmatically. I've tried the answers from hook\_entity\_presave() doesn't work, I was able to add those in my code.

### sno.routing.yml

```
sno.content:
  path: /node/add/issuances
  defaults:
    _controller: Drupal\sno\Controller\SnoController::sno_entity_presave
  requirements:
    _permission: 'access content'

```

### src/Controller/SnoController.php

namespace Drupal\sno\Controller;

use Drupal\Core\Entity\EntityInterface; use Drupal\node\NodeInterface;

```
class SnoController {

  public function sno_entity_presave(\Drupal\Core\Entity\EntityInterface $entity) {
    if ($entity->getEntityType()->id() == 'issuances') {
      $entity->set('field_s', ', s. ');
    }
  }

}

```

When I got into adding a content of content type issuance (/node/add/issuances), I am getting the following error.

> The website encountered an unexpected error. Please try again later.
>
> RuntimeException: Controller "Drupal\sno\Controller\SnoController::sno\_entity\_presave()" requires that you provide a value for the "$entity" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one. in Symfony\Component\HttpKernel\Controller\ArgumentResolver-\>getArguments() (line 78 of /var/www/senate-library/vendor/symfony/http-kernel/Controller/ArgumentResolver.php).

# Answer
The exception you get (*Controller "Drupal\sno\Controller\SnoController::sno\_entity\_presave()" requires that you provide a value for the "$entity" argument*) is caused from the fact the controller's method associated to the *sno.content* route you define doesn't get any `$entity` argument, which is instead listed as its parameters.

That is a route, anyway, not a hook. If you want to implement `hook_entity_presave()`, you don't need to define a route for that. If the module isn't defining other routes, the *sno.routing,yml* file isn't even necessary.

As Jaypan already said, hooks aren't methods implemented in a class. They are plain PHP functions with a specific name.
In your case, it should be the following function. I corrected the function code because:

* In a path like /node/add/issuances, *issuances* is the content type, or node bundle, not the entity type. As the code should act on a node whose bundle is *issuances*, the code needs to check the value returned from `$entity->bundle()`.
* Since `hook_entity_presave()` is invoked for every entity Drupal saves, it's necessary to check which entity is being saved, by checking the value returned from `$entity->getEntityTypeId()`, not just its bundle. This handles the case where two different entities have a bundle with the same name.

I took the module machine name from the namespace used in the question code and from the name of the routing file. If those are correct, also the module machine name should be correct.

```
// Put the following line on the top of the sno.module file.
use \Drupal\Core\Entity\EntityInterface;

/**
 * Implements hook_entity_presave().
 */
function sno_entity_presave(EntityInterface $entity) {
  if ($entity->getEntityTypeId() == 'node' && $entity->bundle() == 'issuances') {
     $entity->set('field_s', '<value to assign to the field>');
  }
}

```

Alternatively, if the module only has code for a single entity type, `hook_ENTITY_TYPE_presave()` can be instead used. In this case, it's not necessary to check the entity type, as the hook is only invoked for a single entity type. (In this case, the entity type is *Node*.)

```
// Put the following line on the top of the sno.module file.
use \Drupal\Core\Entity\EntityInterface;

/**
 * Implements hook_ENTITY_TYPE_presave().
 */
function sno_node_presave(EntityInterface $entity) {
  if ($entity->bundle() == 'issuances') {
     $entity->set('field_s', '<value to assign to the field>');
  }
}

```

As for the field, it's usually *field\_s* for a field added via UI. If it's defined from code, the field is simply *s*. You need to verify the correct way to reference that field, as that isn't clear from the code shown in the code.

As side note, if you edit the code of a module that is installed, you need to install or uninstall a module, to make Drupal notice you added a hook into that installed module, as Drupal caches the list of hooks implemented by modules, and clears it when a module is installed or uninstalled.
> 1 votes

# Answer
Hooks are not part of classes. Hooks go into the .module file, and `hook` is replaced with the key of your module. In your case, your module appears to be named `sno`, so the function name is right. It just should not be part of a class.
> 0 votes

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


# Question
Title: How to change date format in the webform date element?
I have added a date element to my webform.

Now I want to change the date format for the date element.

I have used the following code.

```
function my_module_webform_element_alter(array &$element, FormStateInterface $form_state, array $context) {
  if ($element['#type'] === 'date') {
    $element['#date_date_format'] = 'd/m/Y';
  }
}

```

But I can still see the date element like this.

And when I try to submit the form and I get an error on date field.

Also is there a way to change the date format in the email which webform sends?

# Answer
I am assuming you are using Webform 6.x/

For Drupal 9.x, you need to install the jQueryUI datepicker module and then enable the datepicker via the UI.

For Drupal 8.x, the jQueryUI datepicker is included.
> 1 votes

# Answer
The date format in the field depends on the operating system settings. So it will display the date format according to the format set in your OS.

For the date format in the email, You need to change it from `admin/structure/webform/config/elements` in the `Element formats` section by setting the default format for the date field.
> 0 votes

---
Tags: 8, webforms, datetime
---


title: Token Replacement via Lazy_builder

text:
# Question
Title: Token Replacement via Lazy_builder
I've spent the best part of the last day or two trying to implement lazy\_builder (as seen in this brilliant tutorial https://github.com/joachim-n/drupalcon-europe-2020-lazy-builders).

However, rather than with a block or page render. I'd like to implement the lazy\_builder into hook\_tokens() and make the $replacements value dynamic so that it uses the lazy\_builder.

We have a value saved to session that we use as the value of a token (so it back be used across the site).

```
$session = \Drupal::request()->getSession();
$session->get('my_value');

```

I've tried setting $bubbleable\_metadata with both addCacheContexts and addCacheableDependency

```
$bubbleable_metadata->addCacheContexts(['session']);

```

&

```
$session = \Drupal::request()->getSession();
$bubbleable_metadata->addCacheableDependency($session);

```

However both these options make the page UNCACHABLE.

I'd like to keep the page a cache HIT, but load in the token value via lazy\_builder.

My question is, is there anyway to leverage lazy\_builder, in the token replacement?

```
/**
 * Implements hook_tokens().
 */
function mymodule_tokens($type, $tokens, array $data, array $options, BubbleableMetadata $bubbleable_metadata) {
  $replacements = array();
  if ($type == 'my_token') {
    foreach ($tokens as $name => $original) {
      // Find the desired token by name
      switch ($name) {
        case 'my_token':
          $session = \Drupal::request()->getSession();
          //make the below use lazy_builder
          $replacements[$original] = $session->get('tracking');
          break;
      }
    }
  }
  // Return the replacements.
  return $replacements;
}

```

# Answer
This answer might be helpful. In your case you could try to bubble up the attachment from the token itself:

```
$replacements[$original] = '<my-placeholder>';

$bubbleable_metadata->addAttachments([
  'placeholders' => [
    '<my-placeholder>' => [
      '#lazy_builder' => ['\Drupal\mytheme\MythemeLazyBuilders::replaceUid', []],
    ],
  ],
]);

```

You not really need the Drupal token system, you can attach placeholders almost everywhere in the rendering process, but for some cases this could be a convenient way to make a lazy builder available.
> 1 votes

---
Tags: hooks, caching, tokens, sessions
---


# Question
Title: Incorrect string value: '\xF0\x9F\x92\x99' for column "'comment_body_value'"
How can I fix the following error I get from a Drupal 7 site?

> Incorrect string value: '\xF0\x9F\x92\x99' for column "'comment\_body\_value'

I read it is about users posting emojis that cannot be handled by Drupal/MySQL.

I don't care if the comments are being stripped off the emojis, or converted as long as it does not trigger an error to the end-user. The simpler the solution the better. I found a few modules, for example the Emoji Scrub module that isn't covered by the security advisory policy.

# Answer
This explains how to solve this issue: https://www.jeffgeerling.com/blogs/jeff-geerling/solving-emoji-problem-drupal-7
> 0 votes

---
Tags: 7, comments
---


title: Entity reference additional field

text:
# Question
Title: Entity reference additional field
In D7 I have two new node type defined e.g. branch and leaf. The branch is a collection of leaves that I'm referring to using the entity\_reference module. In the picture below the leaves are the nodes representing the colors. The leaves could be re-used in several branches.

Here is a picture of my collection

I would like to add for each of the referenced leaves, two checkboxes to add some information about that leaf that is referenced in that branch. I have added on the picture manually the checkboxes. This is what I would like to achieve. Then, programmatically when I read the branch and all its leaves, I want to be able to retrieve the checkboxes value as well. Everything is working far, I just need to know how to add the leaves, so that at edit time when I edit a branch I can tick the checkboxes as needed.

How could I do that? If there is no module that exists, which hooks should I use for adding this fields to the referred leaf node in the branch? I do not want to add new fields for the leaf node type, I need the new fields/chekboxes to be added to a branch for each leaf thus at the moment of referring to the leaf and for each leaf.

# Answer
One of the ways to solve it is to use the Paragraphs module.

How to start with Paragraphs for Drupal 7

It's basically entity reference fields with layers.

You create a Paragraph field as a container for each data set, then within paragraph create fields for color and lists (checkboxes).

BTW why not upgrade to D8? D8 supports this type of structure better.
> 0 votes

---
Tags: 7, entities
---


# Question
Title: Synchronize commerce stock for product variations
I am selling tickets to a class at multiple price points (think student, adult, senior), and each class has limited seats. I have the product display working great using `product reference` with `inline entity form - Multiple values`. I can successfully checkout with each product variant.

I have run into a snag using Commerce Stock as the stock is per product, which in my case is each variant of the class. So say I have 30 seats, I need to be able to sell 30 of any product variant, but no more than 30 of all product variants total (per class, which is a single product display).

Is there a way for the stock to be per product display, not per product? If not, is there something I can invoke using Rules to subtract from all product variants stock when one is purchased?

Ultimately, I am looking for a way to synchronize all product variant's stock in a single product display.

# Answer
Here's a relatively straightforward way to track stock based on a group:

> *Caveat Emptor*: This will only work well if you have unique products per product display, if you try to re-use products (same ticket for multiple events) it could wreak havoc on your stock numbers.

*Before starting: Download and enable "Rules Data Transforms" and "Conditional Rules"*

1. **Create master stock field.** Add a field to your Product Display called "master stock" or "open seats" or whatever makes sense for your use case.
2. **Clone rule.** Find the rule that decrements stock on the product level, clone it, disable the original. If it is a component, you may need to locate the event rule that calls it and clone/disable that rule as well. Just depends on your setup.
3. **Edit new cloned rule.** Inside your newly cloned rule, you are going to add an action that decrements the master stock.
4. **Calculate new Stock number.** First, calculate the new stock number by subtracting one from the product's stock field. This will be the new stock number that we will set on the product display, and all of it's children.
5. **Load Product Display.** Pull a product display from the line item field `commerce_display_path`. This can be tricky, which is why I had you install the Rules Data Transforms (link above).

A. Add a condition `Entity has field` and we're checking that the line item has the field `commerce_display_path` (this works great with default add-to-cart settings, but may not work if your add-to-cart doesn't track the display node path).

B. Add an action `Explode Text` under data transforms. You are exploding `commerce-line-item:commerce-display-path` using the delimited `/` and calling it "display\_path"

C. Add an action `Convert data type` under the first group called `Data`. Your target type is `integer` and the value to convert is `display-path:1` (the second value after exploding) and we'll call this `product_display_nid`

D. Add an action `Fetch entity by id`. Click the "Switch to data select" button and pull in the newly converted `product-display-nid`
6. **Set master stock.** Set master stock value of product\_display by adding an action `Set a data value` for the `product_display`'s master stock field to your calculated new stock price.
7. **Create inline condition.** Next we need to create a conditional to bring in the "field\_product" (or whatever field you use for product references). This is why I had you install the Conditional Rules module. (Yes, this could be accomplished with core rules components, but this feels more straightforward.)

A. Click `Add Conditional`

B. Click `Add if` and let's make the conditional an `Entity has field` by loading the `product-display` node and looking for your product reference field. By default it's called `field_product`

C. Click `Add loop` and loop over the `product-display:field-product` list and call it `sibling_product`
8. **Set all sibling products stock.** Finally, we need to add a `Set a data value` action to set each `sibling_product`'s stock field to the new value. Note, this will include the product that has been purchased.

---

There you go! Admittedly, this is a pretty naive solution. If your master stock says "10" then all of your products will be "10" and when one is purchased, they will all say "9." When there is only 1 seat left, there will still be 3 tickets that could be purchased.
> 2 votes

# Answer
I'm facing the exact same issue ... with D8. unable to find a way to synchronize ticket stock (for a global limited ticket -seats- number). An other approach would be to have only 1 variant (adult price) and make a checkbox for children who when clicked, fire a rules with price adjustment... but nothing seems available to make a price reduction on checkbox event... A lot of D7 commerce module are not ported to D8 and cause missing functionnalities... Any idea for me to dive in?

thank a lot Seb
> 0 votes

---
Tags: 7, commerce
---


# Question
Title: How to create template suggestion for image like IMAGE--BLOCK-TYPE or IMAGE--FIELD-TYPE
I'm struggling to make template suggestions like IMAGE--BLOCK-TYPE or IMAGE--FIELD-TYPE. I have three different block types(image1, image2, image3) with one image field(field\_image\_1, field\_image\_2 and field\_image\_3). And I don't know how to get suggestion like

```
image--block_image1.html.twig
image--block_image2.html.twig
image--block_image3.html.twig

```

or

```
image--field_image_1.html.twig
image--field_image_2.html.twig
image--field_image_3.html.twig

```

Is there any way to pass variable between the two hooks below?

```
  function full_nature_theme_suggestions_block_alter(array &$suggestions, array $variables) {

    global $block_id;

    $block_id = $variables['elements']['#id'];

  }

```

and

```
  function full_nature_theme_suggestions_image_alter(array &$suggestions, array $variables) {

    $suggestions[] = 'image__'.$block_id;

  }

```

Please help!

# Answer
Solution is here

https://www.drupal.org/forum/support/theme-development/2021-02-23/how-to-create-template-suggestion-for-image-like-image#comment-14017195

It is alternative solution but it works with this module

https://www.drupal.org/project/image\_class
> 0 votes

# Answer
This is right solution but it works only with this module https://www.drupal.org/project/image\_class

```
/**
 * Implements hook_theme_suggestions_HOOK_alter().
 */

function full_nature_theme_suggestions_image_alter(array &$suggestions, array $variables) {
  $image = $variables['attributes']['class'][0];
  $suggestions[] = 'image__'.$image;
}

```
> 0 votes

---
Tags: 8, theming
---


title: Internal links aren't getting aliased

text:
# Question
Title: Internal links aren't getting aliased
When saving an internal link to content (within the wysiwyg editor), the paths don't get aliased like they do with D7.

If I have a node (at path /node/10), with an alias of /some/other/path, when that page gets saved, then cached/viewed, the link that gets generated for the user is /node/10.

This has several drawbacks, not the least of which is that we have our breadcrumbs reliant on the URL path.

I've looked at all the input filters on the appropriate text format, but there's nothing there for it. This seems like kind of a huge issue for Drupal, I'm hoping that the fact that I can't seem to find anything on the issue means I just have a config wrong somewhere.

# Answer
Use the Redirect module (a.k.a. Global Redirect in D7).

It automatically changes `/node/#` links to aliases when rendering.
> 1 votes

# Answer
Drupal 7 doesn't do anything like that in core. You likely used another module. Pathologic provides this, also exists as a D8 version, only as a dev version, though.
> 1 votes

# Answer
You can have a look at this issue to make it work thanks to **pathologic module** : https://www.drupal.org/project/pathologic/issues/2692641

I've just tested patch submitted in comment #15 (1.0@alpha version of pathologic module) and it works perfectly. I've now my aliases showing in my blocks bodies !
> 0 votes

---
Tags: 8, path-aliases, wysiwyg
---


# Question
Title: Programmatically create a user and assign a role
I'm programmatically creating a user with the following code.

```
$newUser = array(
  'name' => $mail,
  'pass' => 'password',  // note: do not md5 the password
  'mail' => $mail,
  'status' => 1,
  'init' => $mail,
  'roles' => array(5)
);
$user = user_save(null, $newUser);

```

I have got a role with the role ID equal to 5; when I create the user, in the table "users\_roles" there is only a row with the value 0 for the role ID, but if I print the user object with `var_dump()`, it looks like the roles are created.

What am I doing wrong?

# Answer
> 48 votes
This code worked for me:

```
$new_user = array(
  'name' => $name,
  'pass' => $sifra, // note: do not md5 the password
  'mail' => $email,
  'status' => 1,
  'init' => $email,
  'roles' => array(
    DRUPAL_AUTHENTICATED_RID => 'authenticated user',
    3 => 'custom role',
  ),
);

// The first parameter is sent blank so a new user is created.
user_save('', $new_user);

```

# Answer
> 16 votes
To programmatically create a user with roles and custom field values (like e.g. First Name and Last Name) you can use the following code:

```
$new_user = array(
  'name' => 'xgramp',
  'pass' => 'idontwantnoonebutyoutoloveme',
  'mail' => 'xgparsons@flyingburritobrothers.la',
  'signature_format' => 'full_html',
  'status' => 1,
  'language' => 'en',
  'timezone' => 'America/Los_Angeles',
  'init' => 'Email',
  'roles' => array(
    DRUPAL_AUTHENTICATED_RID => 'authenticated user',
    6 => 'member', // role id for custom roles varies per website
  ),
  'field_first_name' => array(
    'und' => array(
      0 => array(
        'value' => 'Gram',
      ),
    ),
  ),
  'field_last_name' => array(
    'und' => array(
      0 => array(
        'value' => 'Parsons',
      ),
    ),
  ),
);

$account = user_save(NULL, $new_user);

```

See this blog post and the comments for more details: http://codekarate.com/blog/create-user-account-drupal-7-programmatically

# Answer
> 13 votes
This is an example I found on a site.

```
$account = new stdClass;
$account->is_new = TRUE;
$account->name = 'foo';
$account->pass = user_hash_password('bar');
$account->mail = 'foo@example.com';
$account->init = 'foo@example.com';
$account->status = TRUE;
$account->roles = array(DRUPAL_AUTHENTICATED_RID => TRUE);
$account->timezone = variable_get('date_default_timezone', '');
user_save($account);

```

# Answer
> 3 votes
To create a user programmatically from an e-mail address, try this:

```
// Use the e-mail address prefix as a user name.
$name = substr($mail, 0, strpos($mail, '@'));

// Make sure the user name isn't already taken.
$query = db_select('users', 'u')
  ->fields('u', array('uid'))
  ->condition('u.name', $name)
  ->execute();
$result = $query->fetch();

// If the user name is taken, append a random string to the end of it.
if ($result->uid) { $name .= '-' . user_password(); }

// Build the user account object and then save it.
$account = new stdClass();
$account->name = $name;
$account->mail = $mail;
$account->init = $mail;
$account->pass = user_password();
$account->status = 1;
user_save($account);
if ($account->uid) {
  drupal_set_message('Created new user with id %uid', array('%uid' => $account->uid));
}

```

# Answer
> 1 votes
To create user in Drupal 8

```
  // Mandatory user creation settings
  use Drupal\user\Entity\User;
  $user = User::create();
  $language = 'en'; //you can set your language
  $email = 'test@gmail.com';
  $user_name = 'ajay_gadhavana';
  $user->enforceIsNew();
  $user->setPassword('Password');
  $user->setEmail($email);
  $user->setUsername($user_name); // This username must be unique and accept only a-Z,0-9, - _ @ .
  $user->set("langcode", $language);
  // Optional settings
  $user->set("init", $email);
  $user->set("preferred_langcode", $language);
  $user->set("preferred_admin_langcode", $language);
  $user->activate();
  // Add a role to user
  $user->addRole('administrator');
  //Save user
  $user->save();`

```

# Answer
> 0 votes
To create a user programmatically:

```
$newUser = array(
      'name' => 'theUserName,
      'pass' => 'thePassWord',
      'mail' => 'the@mail.com',
      'status' => 1,
      'roles' => array(DRUPAL_AUTHENTICATED_RID => 'authenticated user'),
      'init' =>  'the@mail.com',
  );
user_save(null, $newUser);

```

---
Tags: 7, users
---


# Question
Title: Users chosen from a field in a content type see only their result
I have a list of students who are users in my Drupal 8 site. I want to publish their result but I want each student to see only his/her result. I have a content type where I can get marks and an entity reference field from which I can get users. As I am the author of the node, I cannot use the content-author relationship. I have to match the user id chosen in the node to the logged in user. I am trying to use contextual filter on the entity reference field from where I get the user list, but not getting any result. Please help me with the same.

# Answer
> 0 votes
## Views module doesn't control content access

Views module respects the entities permissions set elsewhere in Drupal.

There are Permissions option available in Views but that only controls that particular Views Display global visibility, it doesn't control the nodes/users visibility. You can set Views to be visible by a certain user role or some other permission, but it will only apply to that Views page/block, it will **not** apply to nodes that are listed in that Views results! Even if a user is restricted from viewing that Views, they will still be able to see the nodes listed in the Views if they visit the nodes through the individual nodes links.

To properly restrict access to content on your Drupal site you need to restrict it on the node level, not Views level. Once you have it sorted out on node level, Views will respect it, check access for each node and show only the result rows that the user has access to view. There is a way to turn of node access check in Views (under Advanced options) but that's not recommended and it's rarely used.

## Use Content access modules, Views will respect them

In your case you want to restrict access in a very granular way, to show content to only the user that is referenced from individual content item. You can do that with the help of additional module(s), you should research Access modules on drupal.org that relate to entity references.

Some of the ones I can suggest to test:

---
Tags: 8, views, nodes
---


# Question
Title: Template suggestion does not work for table in a custom block / Might there be a way around?
I created a block on pages of the "Author" content type that lists all the articles the author has contributed to in a table (via contextual filter). Now I want to customize the table layout. I already did this before in a similar case, where I show the table on a page, not in a block. There I get file name suggestions for the template inside HTML comments like that:

```
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_table__articles' -->
<!-- FILE NAME SUGGESTIONS:
   x views-view-table--articles.html.twig
   x views-view-table--articles.html.twig
   * views-view-table.html.twig
-->
<!-- BEGIN OUTPUT from 'themes/MYTHEMEFOLDER/templates/views/views-view-table--articles.html.twig' -->

```

But in my latest case, the table in a block, I only get this suggestion:

```
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_table' -->
<!-- BEGIN OUTPUT from 'themes/MYPARENTTHEMEFOLDER/templates/views/views-view-table.html.twig' -->

```

Note that it outputs the template of my parent theme, not my actual theme.

I did some research and found this issue, which currently is not resolved and the proposed patch not included inside the Drupal code. Is this the reason I cannot create a custom template or is there something else I can do?

If not, how would I create that table of referenced articles on the author's page?

# Answer
> 1 votes
Since Drupal doesn't suggest certain template file names I had to create a custom module which adds the template name for my needs. I had to implement the `hook_theme_suggestions_HOOK()` for my table view and add an appropriate name to the suggestions array.

```
<?php

use Drupal\views\ViewExecutable;

/**
 * Implements hook_theme_suggestions_HOOK().
 */
function custom_template_suggestions_theme_suggestions_views_view_table_alter(array &$suggestions, array $variables) {
  if (isset($variables['view']) && $variables['view'] instanceof ViewExecutable) {
    $id = $variables['view']->current_display;

    if (!in_array('views_view_table__' . $id, $suggestions)) {
      $suggestions[] = 'views_view_table__' . $id;
    }
  }
}

```

---
Tags: views, theming, blocks
---


# Question
Title: How can I have a view <th> tag render markup correctly?
Objective : show a link on the column heading of the table so that the user can reach an explanation page on the content of the column.

I am having trouble figuring out how to add a link to a `<th>` tag in my View, simply.

So I need a field label to contain HTML.

For example if I enter `<a href="/node/1">My field label</a>` in Field configuration label input, the resulting table header is not a link and the markup is visible (plain text).

Table Format settings : no sticky headers and no sortable columns.

Any tip here?

**Views Field Configuration:**

**The result:**

# Answer
with Views UI, in the `HEADER`section, add a Global Text area with this Content in Text format = Full HTML:

```
<a href="/whatever/path/location" title="some text" class="form-submit">Ajouter</a>

```

and it gives something like:
> 0 votes

# Answer
maybe using `hook_views_pre_view`...

```
function hook_views_pre_view(ViewExecutable $view, $display_id, array &$args)
{
  switch ($view->id()) {
    case 'your_view_id':
      switch ($display_id) {
        case 'your_view_display_id':
          $fields = $view->display_handler->getOption('fields');
          foreach ($fields as $key => $value) {
            if ($key == something) {
              $newLabel = 'whatever';
              $view->setHandlerOption($view->current_display, 'field', $key, 'label', $newLabel);
            }
          }
          break;
        default:
      }
      break;
    default:
  }
}

```

I use it only to change the label of some fields but you may try to handle your link this way.
> 0 votes

---
Tags: 8, views
---


# Question
Title: Can you save state in the $form_state variable that remains when the form is rebuilt?
I have a form with a nested subform that has an ajax submit button in it. The subform is built inside a form\_alter and attached to the form. The submit buttons `#name` is made unique by using a UUID generator.

When I press the ajax submit button, Drupal steps through its form builder steps rebuilding the form. Because of this, the same code in the form\_alter is called rebuilding the same subform. The problem is that when it is rebuilt, the submit button gets a brand new #name via the UUID generator. As such, Drupal cannot match the `_triggering_element` to a `#name`, and the ajax fails.

One solution I thought to try was to attach the `#name` to $form\_state storage when the form is first built hoping that it would be available when the form is rebuilt. For e.g. in the same form\_alter I execute:

```
      $input = $form_state->getUserInput();
      if($input){
        //This only runs when the form is being rebuilt
      }

```

And I may be able to grab the correct `#name` out of $form\_state storage and set it so Drupal can correctly match and find the right ajax callbacks.

Is something like this possible? Is there a better way to handle this?

# Answer
You only need `#name` if the form array keys don't provide a unique path for form\_state. I agree with @Jaypan, I too found setting `#name` never really necessary, it seems to be more reliable to define a unique key to the lowest level of the form element if you have issues with Ajax not finding the form element. In either case, `#name` or form key, it has to be predictable, derived from data which doesn't change between form builds, for example a field delta.

The form object and $form\_state are not cached when a form is rendered, only after submitting the first Ajax request. So it doesn't help to store data in $form\_state you want to use to rebuild $form.
> 1 votes

---
Tags: 8, forms
---


title: How do I embed an Ionic webapp?

text:
# Question
Title: How do I embed an Ionic webapp?
I am building a partially decoupled Drupal 8 site. Drupal hosts all the content, but I also built mobile apps and a webapp in Ionic. The mobile apps are working fine, and now I want to host the webapp on my Drupal site.

I want my Ionic app to take over all the paths from `/webapp/*`, and these should all redirect to Ionic's `index.html` and then be passed the relevant argument from the URL.

Before I made the Ionic app, I had a React app, which I embedded into Drupal as follows.

This is the code I am using.

### MY\_MODULE/src/Controller/PageController.php

```
  public function reactApp() {
    return [
      '#markup' => '<div id="my-react-app"></div>',
      '#attached' => [
        'library' => [
          'MY_THEME/react_app',
        ],
      ],
    ];
  }

```

### MY\_MODULE/MY\_MODULE.routing.yml

```
MY_MODULE.myreactapp:
  path: '/webapp/{react_route}'
  defaults:
    _controller: '\Drupal\MY_MODULE\Controller\PageController::reactApp'
    _title: 'React App'
  react_route: ''
  requirements:
    _permission: 'access content'

```

### MY\_THEME.libraries.yml

```
react_app:
  version: VERSION
  js:
    js/dist/main.min.js: {minified: true}

```

This worked great for embedding a simple react app and giving it all the routes at `/webapp/*`.

However, a webapp built in Ionic generates an index.html that looks like this.

```
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8"/>
  <title>Ionic App</title>
  <base href="/"/>
  <meta name="color-scheme" content="light dark"/>
  <meta name="viewport"
        content="viewport-fit=cover,width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>
  <meta name="format-detection" content="telephone=no"/>
  <meta name="msapplication-tap-highlight" content="no"/>
  <link rel="manifest" href="/manifest.json"/>
  <link rel="shortcut icon" type="image/png" href="/assets/icon/favicon.png"/>
  <meta name="apple-mobile-web-app-capable" content="yes"/>
  <meta name="apple-mobile-web-app-title" content="Ionic App"/>
  <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
  <link href="/static/css/4.21302a68.chunk.css" rel="stylesheet">
  <link href="/static/css/main.1d86f075.chunk.css" rel="stylesheet">
</head>
<body class="has-navbar-fixed-top">
<div id="root"></div>
<script src="/static/js/runtime-main.48098029.js"></script>
<script src="/static/js/4.54463739.chunk.js"></script>
<script src="/static/js/main.3b08ecfa.chunk.js"></script>
</body>
</html>

```

### What I want to do

1. Put all the ionic build assets in a subdirectory (`/webapp`) inside my Drupal site (done).
2. Tell Drupal to redirect all requests to (`/webapp`) to Ionic's `index.html`. (how do I do this?)

I thought of using a theme hook, but I don't know how to add all the scripts and css in Ionic's `index.html` to the twig template.

If possible, I don't want to hard-code the Ionic script assets inside Drupal because the names will change every time the app is built, which will be often.

# Answer
> 1 votes
The problem probably is you have two .htaccess files rewriting URLs to index.php (Drupal) or index.html (Ionic). I think you need to adjust Drupal's rewrite rule because it is in the top level:

```
  # Pass all requests not referring directly to files in the filesystem to
  # index.php.
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^ index.php [L]

```

For example by adding this condition:

```
RewriteCond %{REQUEST_URI} !^/webapp

```

# Answer
> 0 votes
I'm hosting with Pantheon, which doesn't allow making changes to the server configuration. I contacted Pantheon support, who told me that I may be able to do it with domain masking if I upgrade to enterprise hosting. So I guess I'm stuck with the following until I switch hosts.

Temporary solution: use the PageController to redirect the user to the Ionic app if on the `/webapp/*` path:

In `MY_MODULE/src/Controller/PageController.php`:

```
use Symfony\Component\HttpFoundation\RedirectResponse;

class PageController extends ControllerBase implements ContainerInjectionInterface {
  public function reactApp($react_route) {
    // Append the react-router route as a query string so I can handle redirects in react.
    $response = new RedirectResponse("/webapp/index.html?&route=$react_route");
    $response->send();
    return;
  }
}

```

In `MY_MODULE/MY_MODULE.routing.yml`:

```
MY_MODULE.myreactapp:
  path: '/webapp/{react_route}'
  defaults:
    _controller: '\Drupal\MY_MODULE\Controller\PageController::reactApp'
    _title: 'React App'
  react_route: ''
  requirements:
    _permission: 'access content'

```

This will allow the user to use the "back" button when moving from the Ionic app to the Drupal site and then going back. **However, the user will always be redirected to the index instead of the last page that he/she was actually on, so this is not an ideal solution.**

---
Tags: theming, routes
---