title: Batch redirect to http instead of https

text:
# Question
Title: Batch redirect to http instead of https
i'm working on a project and all batch callbacks in ***http*** not ***https*** so instead of redirecting to `https://example.com/batch?id=844&op=start` redirect to `http://example.com/batch?id=844&op=start`, and as result **query params** get lost and redirect me after to `https://example.com/batch` which gives me a 403 forbidden page:

i have checked ***htaccess*** file and also the server i don't have any redirection.
anyone has experienced this, any help ?

**EDIT:**
I have checked the result of `\Drupal\Core\Url::fromRoute('<front>')->setAbsolute()->toString()` i get the url correct with the right protocol and also i have added:

```
$settings['reverse_proxy'] = TRUE;
$settings['reverse_proxy_addresses'] = array($_SERVER['REMOTE_ADDR']);

```

to my **settings.php** and again no luck.
**Note:** all redirections in the site works perfectly with https only this one!

# Answer
The issue was caused by the apache server, the **HTTPS** variable wasn't set to **on** so the Drupal in redirection send **Location:** response header with HTTP instead of HTTPS.
So the solution is to set **HTTPS** variable to **on** with:

```
  SetEnv HTTPS on

```
> 0 votes

# Answer
For debugging try to output the result of:

```
\Drupal\Core\Url::fromRoute('<front>')->setAbsolute()->toString()

```

Is this the wrong protocol, too? Then your browser terminates with a different protocol than the CDN to your web server.

Symfony is able to detect the correct protocol, but you need to configure the CDN (reverse proxy) in settings.php.
> 0 votes

---
Tags: 8, redirection, batch-operations
---


# Question
Title: How to make a display mode of the current user on the home page?
I have a site built with Drupal 8 and the Twig Tweak module. I want to make the current user's `frontpage_tasks` display mode on my home page. How to do this ?

I can make a user's `frontpage_tasks` display mode by manually entering their ID :

page--front.html.twig :

```
{{ drupal_entity('user', 51, 'frontpage_tasks') }}
{{ drupal_entity('commerce_store', ???, 'frontpage_tasks') }}
{{ drupal_entity('group', ???, 'frontpage_tasks') }}

```

For stores, I want to display all stores that the current user owns.

For groups, I want to display all groups whose current user is the creator.

What I want to do is render the current user account, stores and groups with `frontpage_tasks` view mode.

# Answer
In a Twig template you can get the current user id with `user.id`.

With the help of Twig Tweak you can use it to render the user entity:

```
{{ drupal_entity('user', user.id, 'full') }}

```

As discussed in the comments this only works if your template has already a cache context for the current user.
> 0 votes

---
Tags: 8, entities
---


# Question
Title: Ajax callback on Views exposed form filter
I'm trying to add an #ajax callback method to my views exposed form filter select box. But it seems the form have some issues with the callback. My code is pretty simple

```
/**
 * Implements hook_form_FORM_ID_alter() for views_exposed_form.
 */
function mymodule_form_views_exposed_form_alter(&$form, FormStateInterface $form_state) {
  if ($form['#id'] == 'views-exposed-form-viewid') {
    $op = ['hi' => 'hi', 'all' => 'all'];
    $form['test'] = [
      '#type' => 'select',
      '#name' => 'test',
      '#empty_option' => 'none',
      '#options' => $op,
      '#ajax' => [
        'callback' => '_my_call',
        'event' => 'change',
        'wrapper' => 'edit-output-test',
        'progress' => [
          'type' => 'throbber',
        ],
      ],
    ];

    $form['callfield'] = [
      '#type' => 'select',
      '#options' => [],
      '#prefix' => '<div id="edit-output-test">',
      '#suffix' => '</div>',
    ];
  }
}

function _my_call(array &$form, FormStateInterface $form_state) {
  $response = new AjaxResponse();
  $message = 'test';
  $response->addCommand(new HtmlCommand('#edit-output-test', $message));
  return $response;

}

```

When I try to change the 'test' select box from view edit screen I get the below error

**"Symfony\Component\HttpKernel\Exception\HttpException: The specified #ajax callback is empty or not callable. in Drupal\Core\Form\FormAjaxResponseBuilder-\>buildResponse() (line 67 of /var/www/mypoc/docroot/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php)."**

When I change the filter from the front end I get the following error

**"An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (32 MB) that this server supports."**

And I see a lot of similar issues -

Ajax callback is not working on views exposed filters

Ajax submission leads to =\> An unrecoverable error occurred. The uploaded file likely exceeded the maximum file size (2 MB) that this server supports

Any working example would be great! Thanks.

# Answer
Sounds like there is an ongoing core issue queue - https://www.drupal.org/project/drupal/issues/2842525

After applying the patch - https://www.drupal.org/files/issues/2020-03-27/2842525-83.patch this seems to work.
> 0 votes

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


# Question
Title: How can i get the value a field type 'date' using $form_state->getValue?
I have an ajax callback on my date field that changes a particular field when user chooses a date.

Here is my code:

// INSIDE FORM\_ALTER

```
$form['field_camp_scheduled_time']['widget']['#options'] = populate_scheduled_time($form, $form_state);

```

//THE METHOD

```
function populate_scheduled_time($form, $form_state){
$date = $form_state->getValue('field_camp_scheduled_date')[0];
}

```

As you can see from the method above, I'm trying to get the value of the date field. But instead of getting the date '2018-26-01', I'm getting an array:

> Drupal\Core\Datetime\DrupalDateTime Object ( \[formatTranslationCache:protected\] =\> \[inputTimeRaw:protected\] =\> \[inputTimeAdjusted:protected\] =\> \[inputTimeZoneRaw:protected\] =\> \[inputTimeZoneAdjusted:protected\] =\> \[inputFormatRaw:protected\] =\> \[inputFormatAdjusted:protected\] =\> \[langcode:protected\] =\> en \[errors:protected\] =\> Array ( ) \[dateTimeObject:protected\] =\> DateTime Object ( \[date\] =\> 2018-01-27 12:00:00.000000 \[timezone\_type\] =\> 3 \[timezone\] =\> UTC ) \[stringTranslation:protected\] =\> )

# Answer
I was able to get the value by using this code:

```
$date_value = $form_state->getValue('field_camp_scheduled_date')[0]['value'];

$date = new DrupalDateTime($date_value, DATETIME_STORAGE_TIMEZONE);

$value = $date->format('Y-m-d');

```
> 3 votes

# Answer
`Drupal\Core\Datetime\DrupalDateTime` is a class - what you have is an object, not an array.

Looking at the docs for the class, you'll find the `prepareFormat` method:

```
$formatted_date = $form_state->getValue('field_camp_scheduled_date')[0]
  ->prepareFormat('Y-m-d');

```
> 1 votes

# Answer
For some reason, creating a new date object from Bernard's answer above didn't work for me. If I cut out that step, it works fine for my webform alter.

```
$date_value = $form_state->getValue('field_camp_scheduled_date')[0]['value'];
$value = $date_value->format('Y-m-d');

```

I am running Drupal 8.9.6
> 1 votes

---
Tags: entities, datetime
---


title: Get the actual query executed by a view

text:
# Question
Title: Get the actual query executed by a view
I need to find out the SQL query that is executed by a certain query. Views module can show the SQL when configuring the view but apparently the query is not the actual query that gets run in all cases.
I am aware that the Devel module can show the database queries, but there is no way with devel to show the actual queries except clicking the associated 'A' link with every query and there are hundreds of them.

How can I find out the actual query that the view executes? The view is displayed as a block.

# Answer
You have to use hook\_views\_pre\_execute and with Devel installed use `dpq` to view the SQL String:

```
function hook_views_pre_execute(&$view) {
  dpq($view->build_info['query']);
}

```
> 40 votes

# Answer
No need for patches or hooks. Just use the following code.

```
// Run the view.
$view = views_get_view('frontpage');
$view->set_display('page');
$view->pre_execute();
$view->execute();

/* Magic Below Here */
// Get query from the view.
$query = $view->query->query();

// Format SelectQueryInterface into a string.
$string = (string) $query;

// Replace arguments.
$arguments = $query->arguments();
if (!empty($arguments) && is_array($arguments)) {
  foreach ($arguments as $placeholder => &$value) {
    if (is_string($value)) {
      $value = "'$value'";
    }
  }
  $string = strtr($string, $arguments);
}

// Format the query string for more readable output.
$string = str_replace(array(' {', "\n{"), ' ', $string);
$string = str_replace(array('} ', "}\n"), ' AS ', $string);
$string = str_replace(', ', ",\n  ", $string);
$string = str_replace(' AND ', "\n  AND ", $string);
$string = str_replace(' ON ', "\n  ON ", $string);
$string = str_replace('SELECT ', "SELECT\n  ", $string);
$string = str_replace('ORDER BY ', "ORDER BY\n  ", $string);

// echo $string;
echo str_replace('  ', '  ', nl2br($string));

```

Its output is the following.

```
SELECT
  node.sticky AS node_sticky,
  node.created AS node_created,
  node.nid AS nid,
  'frontpage:page' AS view_name
FROM  node AS node
WHERE (( (node.promote <> 0)
  AND (node.status = 1) ))
ORDER BY
  node_sticky DESC,
  node_created DESC
LIMIT 10 OFFSET 0

```
> 6 votes

# Answer
```
function hook_views_pre_execute(&$view) {
  if ($view->name == 'XYZ') {
    $query = (string)$view->build_info['query'];
    echo $query;
  }
}

```
> 3 votes

# Answer
//Get The Results by View Name and Contextual Filter nid here

```
    $viewr = views_get_view('your_view_display');
    $args[] = $myarg;
    $display_id = 'default';
    $viewr->set_arguments($args);
    $viewr->set_display($display_id);
    $viewr->execute();
    $view_content = $viewr->result;

```

See the doc for more reference: https://api.drupal.org/api/views/views.module/function/views\_get\_view\_result/7.x-3.x
> -1 votes

# Answer
Get query without running view-\>execute. Wrapped in a function with the \_fast suffix.

```
function get_view_query_string_fast($view_name, $view_display, $pager = TRUE) {
  // Get view and set display.
  $view = views_get_view($view_name);
  $view->set_display($view_display);

  // Disable Pager.
  if (!$pager) {
    $pager = $view->display_handler->get_option('pager');
    $pager['type'] = 'none';
    $view->display_handler->set_option('pager', $pager);
  }

  // Get query object.
  $view->pre_execute();
  $view->build();
  $query = $view->build_info['query'];
  $query->addMetaData('view', $view);
  $query->preExecute();

  // Get the query string, ready to run.
  $query_string = (string)$query;
  $query_string = str_replace('{', '', $query_string);
  $query_string = str_replace('}', '', $query_string);
  $query_params = $query->getArguments();
  foreach($query_params as $placeholder => $value) {
    if(!is_numeric($value)) {
      $query_string = str_replace($placeholder, "'$value'",    $query_string);
    }
    else {
      $query_string = str_replace($placeholder, $value, $query_string);
    }
  }
  return $query_string;
}

```

`$sql_a = get_view_query_string_fast('frontpage', 'page', TRUE);`

```
SELECT node.sticky AS node_sticky, node.created AS node_created, node.nid AS nid, 'frontpage:page' AS view_name
FROM
node node
WHERE (( (node.promote <> 0) AND (node.status = 1) ))
ORDER BY node_sticky DESC, node_created DESC
LIMIT 10 OFFSET 0

```

`$sql_b = get_view_query_string_fast('frontpage', 'page', FALSE);`

```
SELECT node.sticky AS node_sticky, node.created AS node_created, node.nid AS nid, 'frontpage:page' AS view_name
FROM
node node
WHERE (( (node.promote <> 0) AND (node.status = 1) ))
ORDER BY node_sticky DESC, node_created DESC

```
> -1 votes

---
Tags: 7, views, database
---


# Question
Title: Access denied to all profiles of a certain type
I am migrating from D7 to D8. I've had success with everything but the profiles from D7's profile2 module.

Four profile types have to be migrated. One of them is being migrated without issue: I can view and edit them. The other three, however, are giving me "Access Denied" errors when I try to view them. There is no difference in the parameters for the individual profile type migrations, aside from the names of the fields and the names of the profiles themselves.

When I view the list of profiles at `admin/people/profiles`, only one type of profile as an option to edit it. The others just have a button that says "Devel."

My user has permission to view, edit, and create profiles of all types, so it does not appear to be a permissions issue. I know for a fact that the data is being migrated, because I can see it in the MySQL DB. I have also cleared the cache, updated the db, and rebuilt the permissions.

I'm stumped, and I really need to have access to those profiles.

* Drupal Version: 8.9.6
* PHP Version 7.3.22
* MariaDB Version: 5.5.5-10.4.14

Incidentally, using the patch at https://www.drupal.org/project/profile/issues/2957256 made the migration of profiles possible in the first place.

# Answer
I think I understand what's happening now. During migration, empty profiles were made for users who did not have profiles on the origin site. That is why access is denied: there isn't anything to access. That message really should be "a profile doesn't exist yet," or something like that. I can see the existing profiles without any issue.
> 0 votes

---
Tags: 8, users, migrations
---


# Question
Title: Is it possible to schedule approving and blocking users (user status) triggered for example by date?
On D8, any recommendation on approving and blocking user status (active or blocked) by schedule (for example triggered by some dates)? Use case e.g. users as members on subscription, will require renewal for e.g. annually. No payments/commerce involved.

# Answer
You'll need to create a cron job and you can schedule it with Job Scheduler.

Simple example:

> ```
> // Declare scheduler.
>
>   function example_cron_job_scheduler_info() {
>     $schedulers = [];
>     $schedulers['example_unpublish'] = [
>       'worker callback' => 'example_unpublish_nodes',
>     ];
>     return $schedulers;
>   }
>
> // Add a job.
>
>   $job = [
>     'name' => 'example_unpublish',
>     'type' => 'story',
>     'id' => 12, // must be unique
>     'period' => 3600, // in seconds, so its set to 60 min / 1 hour
>     'periodic' => TRUE, // set to false if you want to just run once.
>   ];
>   $service = \Drupal::service('job_scheduler.manager');
>   $service->set($job);
>
> // Work off a job.
>
>   function example_unpublish_nodes(\Drupal\job_scheduler\Entity\JobSchedule $job) {
>     // Do stuff.
>   }
>
> ```

There is more examples & info in the READ.ME, so read it.
> 2 votes

---
Tags: 8, users
---


title: How to include SVG in a block markup?

text:
# Question
Title: How to include SVG in a block markup?
I'm building a custom markup for a block but the SVG part is not rendered. Everything else is rendered correctly.

```
class HomeSocial extends BlockBase
{

    /**
     * {@inheritdoc}
     */
    public function build()
    {
        $markup = '<div id="container">';
        $markup .= '<svg width="26.383960" height="21.428597" viewBox="0.736608 -42.857194 26.383960 21.428597"
xmlns="http://www.w3.org/2000/svg">
<path d="M27.120568 -40.312548C26.149585 -39.894021 25.094896 -39.592681 24.006725 -39.475493C25.128378 -40.145137 25.982174 -41.199826 26.383960 -42.455408C25.346012 -41.835987 24.174136 -41.383978 22.952036 -41.149603C21.964312 -42.204291 20.558060 -42.857194 19.001139 -42.857194C16.004483 -42.857194 13.593766 -40.429736 13.593766 -37.449821C13.593766 -37.031294 13.643989 -36.612767 13.727695 -36.210981C9.241082 -36.445356 5.239962 -38.588216 2.578128 -41.869470C2.109378 -41.065897 1.841520 -40.145137 1.841520 -39.140672C1.841520 -37.265669 2.795762 -35.608301 4.252237 -34.637318C3.364959 -34.670800 2.527905 -34.921917 1.808038 -35.323703C1.808038 -35.306962 1.808038 -35.273480 1.808038 -35.256738C1.808038 -32.628387 3.666299 -30.452045 6.143981 -29.949812C5.691971 -29.832625 5.206479 -29.765660 4.720988 -29.765660C4.369425 -29.765660 4.034603 -29.799143 3.699781 -29.849366C4.386166 -27.706506 6.378356 -26.149585 8.755591 -26.099361C6.897330 -24.642887 4.570318 -23.789091 2.042413 -23.789091C1.590404 -23.789091 1.171876 -23.805832 0.736608 -23.856055C3.130584 -22.315875 5.976570 -21.428597 9.040189 -21.428597C18.984398 -21.428597 24.425252 -29.665214 24.425252 -36.813660C24.425252 -37.048035 24.425252 -37.282411 24.408511 -37.516786C25.463200 -38.286876 26.383960 -39.241118 27.120568 -40.312548ZM27.120568 -40.312548"></path></svg>';
        $markup .= '</div>';

        return array(
            '#markup' => $markup,
            '#cache' => array(
                'max-age' => 3600,
            ),
        );
    }

```

Do I neet to allow SVG tag somewhere in the configuration?

# Answer
> 4 votes
Use `inline_template` instead of markup, or a theme function (as suggested by Ivan Jaros in a comment also).

Refer to class InlineTemplate for way more details. Here is a partial quote of it:

> Provides a render element where the user supplies an in-line Twig template.
>
> Properties:
>
> * **#template**: The inline Twig template used to render the element.
> * **#context**: (array) The variables to substitute into the Twig template. Each variable may be a string or a render array.
>
> Usage example:
>
> ```
> $build['hello']  = [
>   '#type' => 'inline_template',
>   '#template' => "{% trans %} Hello {% endtrans %} <strong>{{name}}</strong>",
>   '#context' => [
>     'name' => $name,
>   ]
> ];
>
> ```

# Answer
> 4 votes
Drupal 8 has moved away from using `#markup` like in your example. While you still can use it there are some limitations. Certain attributes can't be set and certain tags can't be used.

Generally if you want to follow best practice, you should make theme functions and template file, in your example it's pretty simple.

PHP code in module

```
/**
 * Implements hook_theme().
 */
function hook_theme() {
  return array(
    'svg' => array(
      'variables' => array('svg_attibutes' => [], 'path_attributes' => []),
    ),
  );
}

```

Add the `svg.html.twig` template file in the templates folder:

```
<div id="container">;
  <svg {{ svg_attributes }}>
    <path {{ path_attributes }}></path>
  </svg>
</div>

```

Doing the above, your render array would become

```
$render = [
  '#theme' => 'svg',
  '#svg_attributes' => [...],
  '#path_attributes' => [...],
];

```

Doing it this way also has the advantage that you can in theme debug can see where markup is coming from, you can make theme suggestions or invoke them directly fx using

```
$render = [
  '#theme' => 'svg__awesome',
  ...

```

While the initial work is a bit more, it gives a lot of readability and help you working in good way, where markup and logic is separated.

# Answer
> 3 votes
You have to use the `Drupal\Core\Render\Markup::create()` method. In your case, the render array should become:

```
return array(
    '#markup' => \Drupal\Core\Render\Markup::create($markup),
    '#cache' => array(
        'max-age' => 3600,
    ),
);

```

# Answer
> 0 votes
A convenient and simple way is yo use the include() function in your Twig Block template:

```
  {% include('themes/path/to/your/logo.svg') %}

```

---
Tags: blocks, 8
---


# Question
Title: Update existing 'paragraph' entity while changing the ID is not supported
I'm trying to update a paragraph with this code:

```
$entityManager = \Drupal::entityTypeManager();
      $paragraph = $entityManager->getStorage('paragraph')->load('1');
      $paragraph->set('field_test','testValue');
      $paragraph->save();

```

But I received this error:

```
Drupal\Core\Entity\EntityStorageException: Update existing 'paragraph' entity while changing the ID is not supported. in Drupal\Core\Entity\Sql\SqlContentEntityStorage->save() (line 846 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).

```

Do you know why?

P.s. If I try to update with the last ID it works. It doesn't work only for old Paragraphs.

# Answer
You could load the paragraphs through their parent entity to get the active revisions:

```
$nids = \Drupal::entityQuery('node')
  // load only nodes where this paragraph reference field exists and has content
  ->exists('field_paragraph')
  ->execute();
$nodes = \Drupal::entityTypeManager()->getStorage('node')->loadMultiple($nids);
foreach ($nodes as $node) {
  $paragraphs = $node->field_paragraph->referencedEntities();
  foreach ($paragraphs as $paragraph) {
    if ($paragraph->hasField('field_foo')) {
      $paragraph->field_foo->value = 'bar';
      $paragraph->save();
    }
  }
}

```
> 0 votes

---
Tags: entities
---


title: Price resolver save custom field

text:
# Question
Title: Price resolver save custom field
I would like to update a custom field, added to my order items, in the price resolver process. The price resolver process do some sort of queries to select the right price and this selection has a key that I want to save in the custom field. I'm not sure how could I alter the order line item after the right price was selected.

# Answer
You price resolver should have something like

```
if (isset($result['price'])) {
    return new Price((string) $result['price'], $context->getStore()->getDefaultCurrencyCode());
}

```

Before your price resolver's `return` line put:

```
$cart_provider = \Drupal::service('commerce_cart.cart_provider');
$cart = $cart_provider->getCart('default');
$order_items = $cart->order_items->referencedEntities();
foreach ($order_items as $order_item) {
  if (!empty($order_item->field_custom)) {
    $order_item->field_custom->value = 'Hello World'; // set new value
    $cart_manager = \Drupal::service('commerce_cart.cart_manager');
    $cart_manager->updateOrderItem($cart, $order_item);
  }
}

```
> 2 votes

---
Tags: 8, commerce
---


title: Why doesn't the authentication work?

text:
# Question
Title: Why doesn't the authentication work?
I am using Rest web service . I CREATED a view called ART and specified its path (/viewpath) and I set the http baisc authentication within that view's structure such that the results will be accessible only for a user whose role is RESTADMIN . Everything works fine when I curl using the path of that view and the username and password of the user (of role restadmin) :

```
curl http://username:password@example.com/viewpath

```

However , when I try to get a simple article using its nid :

```
curl http://example.com/node/2?_format=hal_json

```

I get no results and "The used authentication method is not allowed on this route" . Even when I put the username and password as before I still get this error. I do realize that the authentication I have set is just for the view ART. But I can't find the solution to let the other link work any idea why?

# Answer
Since the latter uses `hal_json`, you need to do it like this

```
curl --request GET --user myusername:mypassword --header 'Accept: application/hal+json' \
http://example.com/node/2?_format=hal_json

```

For more info, see Using other authentication protocols.
> 0 votes

---
Tags: authentication-authorization
---


title: Create a custom fieldset template

text:
# Question
Title: Create a custom fieldset template
**Normal scenario**

In a custom form (created using FAPI) I have a fieldset definition:

```
$company_field_set = [
  '#type'  => 'fieldset',
];

```

If I would like to customize the fieldset template, I normally would create a `hook_theme_suggestions_HOOK_alter` function to add suggestions and then overwrite the template.

**Alternative**

I was wondering though why I wouldn't simply use the `#theme` key, so I tried this:

```
$company_field_set = [
  '#type'  => 'fieldset',
  '#theme' => 'my_custom_company_fieldset',
];

```

This does indeed render my custom template instead of fieldset.html.twig, but I don't get any variables in it. I would expect it to behave just like fieldset.html.twig.

I have tried several theme definitions:

```
// Same as default fieldset
'my_custom_company_fieldset' => [
  'render element' => 'element',
]

// Another tryout
'my_custom_company_fieldset' => [
  'render element' => 'children',
]

```

My template currently looks like this:

```
{% extends 'fieldset.html.twig' %}

```

I also tried:

```
{{ children }}

```

I see the template contents (like static text and such), but no variables.

I think I know a little bit too little about this and am missing something somewhere. Could anyone point out my mistakes and/or tell me whether or not this is even possible?

# Answer
> 1 votes
After looking a little deeper in the Drupal core I found out that in this case I shouldn't overwrite `#theme`, but use `#theme_wrappers` instead.

So my theme definition:

```
function mymodule_theme($existing, $type, $theme, $path) {
  return [
    'my_custom_fieldset' => [
      'render element' => 'children',
    ],
  ];
}

```

In my form:

```
$form['some_fieldset'] = [
  '#type'  => 'fieldset',
  '#title' => 'Some title',
  '#theme_wrappers' => ['my_custom_fieldset'],
];

$form['some_fieldset']['some_field1'] = [
  '#type' => 'textfield',
  '#title' => 'Some title',
];

$form['some_fieldset']['some_field2'] = [
  '#type' => 'textfield',
  '#title' => 'Another title',
];

```

And then my template my-custom-fieldset.html.twig:

```
<fieldset>{{children}}</fieldset>

```

Or for example:

```
<fieldset>
  {{ children.some_field1 }}
  Some customization here
  {{ children.some_field2 }}
  Something custom here
</fieldset>

```

# Answer
> 1 votes
**Normal Solution** (easy).

```
/*
 * Implements hook_theme_suggestions_HOOK_alter()
 */
function journey_talk_theme_suggestions_fieldset_alter(array &$suggestions, array $variables) {
  $suggestions[] = 'fieldset__' . $variables['element']['#parents'][0];
}

```

---

**Alternative Solution** (doable, not recommended, you'll work harder).

First you need to declare theme and variable names in hook\_theme()

```
function mymodule_theme($existing, $type, $theme, $path) {
  return [
    'my_custom_company_fieldset' => [
      'variables' => ['my_var' => null],
    ],
  ];
}

```

Second, you set the variable value where you assign #theme (OR also in a preprocess function)

```
$form['book']['title'] = [
  '#type' => 'textfield',
  '#title' => $this->t('Title'),
];

$form['book']['publisher'] = [
  '#type' => 'textfield',
  '#title' => $this->t('Publisher'),
];

// You have to put your fieldset after your fields, otherwise they won't be inside $form['book'];
$form['book'] = [
  '#type' => 'fieldset',
  '#title' => $this->t('Book Info (type = fieldset)'),
  '#theme' => 'my_custom_company_fieldset',
  '#my_var' => $form['book'], // setting a value for the "my_var" variable declared in hook_theme()
];

```

and in twig you can render the fields with

```
{{ my_var.title }}

{{ my_var.publisher }}

```

But the downside of this approach is that you cant access all the existing variables available in fieldset.html.twig. Although, you could at the end of the day get access to those values through your variable (my\_var) tree.

**You know what the say, work smarter not harder! Thus, normal solution is the way to go.**

---
Tags: theming
---


# Question
Title: Modules installed with composer do not have a version number
Recently we ran into an issue where the Focal Point module has a dependency on a specific version of the CropAPI module. Since composer is installing these modules directly from git, they dont have the version numbers that were added to the .info file by the drupal.org packaging scripts. This cause the focal point module to fail during enable.

Has anyone else solved this?

# Answer
I am using https://packagist.drupal-composer.org/ as Packagist repository for Drupal modules, and I get the version information inside the .info.yml file of the modules I require with `composer require`.

I first added the new repository with `composer config repositories.drupal composer https://packagist.drupal-composer.org/`. After, I can add any modules, for example the Focal Point module with a command like the following.

```
composer require drupal/focal_point 8.1.*@dev

```

The command install the module and its dependencies, producing the following output.

```
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing drupal/crop (8.1.0)
    Downloading: 100%

> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
  - Installing drupal/focal_point (8.1.0-beta3)
    Downloading: 100%

> Drupal\Core\Composer\Composer::vendorTestCodeCleanup
drupal/crop suggests installing drupal/media_entity (Required by drupal/crop_media_entity)
Writing lock file
Generating autoload files
> Drupal\Core\Composer\Composer::preAutoloadDump
> Drupal\Core\Composer\Composer::ensureHtaccess

```

If then I check the content of modules/focal\_point/focal\_point.info.yml and modules/crop/crop.info.yml, I get the following output.

```
name: Focal Point
type: module
description: Allows users to specify the focal point of an image for use during cropping.
# core: 8.x
package: Images
# version: VERSION
test_dependencies:
  - crop
dependencies:
  - image
  - crop (>=8.x-1.0-alpha2)

# Information added by Drupal.org packaging script on 2016-09-01
version: '8.x-1.0-beta3'
core: '8.x'
project: 'focal_point'
datestamp: 1472695440

```

```
name: Crop API
description: 'Provides storage and API for image crops.'
# core: 8.x
package: Media
type: module
dependencies:
  - image
  - user

# Information added by Drupal.org packaging script on 2016-05-25
version: '8.x-1.0-rc1'
core: '8.x'
project: 'crop'
datestamp: 1464160143

```

In both the cases, the information added from the Drupal.org packaging script is present for both the modules (the one I directly required, and it's dependency). I am using this method for all the module I need in my site, and I have never had problems with the version strings.
To update the modules, I just run `composer update`, and Composer updates all the modules with a new version that respects the restriction I set for each module.
> 4 votes

# Answer
This is a known issue, only tagged releases contain a version number. Dev-releases are directly retrieved via git. You can you the Composer deploy module (https://www.drupal.org/project/composer\_deploy) to read version numbers for dev releases from composer metadata. Composer deploy has no Config UI. You have to configure the location by yourself. (http://cgit.drupalcode.org/composer\_deploy/tree/config/install/composer\_deploy.settings.yml)
> 2 votes

# Answer
There is a Composer plugin which adds version information to Drupal modules, much like the packaging script:

https://github.com/drupal-composer/info-rewrite
> 0 votes

# Answer
Make sure you don't have `"preferred-install": "source"` present in config of composer.json. In my case, due to this config it was directly cloning the drupal projects from git instead of downloading the tagged package.
> 0 votes

---
Tags: 8, composer
---


# Question
Title: How do I install on Ubuntu 20.04 (LAMP)?
I have Ubuntu 20.04. I installed Apache2 and MySQL 8 on it, but I can't install Drupal 8. When I try to add the database information like usual, I get the following error message.

I traced the possibilities of the error and be sure of solving it, but it still doesn't work. I didn't find instructions on the net to work on it.

# Answer
This might be an issue with the new ways MySQL 8 does authentication.

Read more about that in this answer: What is mysql\_native\_password?

From the docs: MySQL Secure Deployment Guide / Enabling Authentication

You need to adjust the authentication method for the MySQl user you're using with Drupal (seems to be `root` from your screenshot). You can't do that through Drupal, you have to login MySQL through terminal or go through some other way of configuring your installed database server.

If switching to the new way of authentication isn't an option then you can change the user to use the old way of authenticating with mysql\_native\_password:

```
alter user 'root'@'localhost' identified with mysql_native_password by 'whateveryourpasswordis';
flush privileges;

```

After that Drupal should be able to connect with the chosen database.

This is probably unrelated to your problem, but I've had problems in the past with some special characters in the *password* (not the database name), I couldn't use `&` nor `#` IIRC.
> 2 votes

# Answer
I think that the database name is not allowed. Try to create a new database and name it according to the following conventions.

* Database names must only consist of the letters a to z (both lower and upper case allowed), the numbers 0 to 9, and the underscore (\_) or dash (-) symbols
* Database names are case-sensitive
* Database names starting with an underscore are considered to be system databases, and users should not create or delete those
* The maximum allowed length of a database name is 64 bytes

Naming conventions are taken from Database Names.
> 0 votes

# Answer
Here is what I did on a fresh install of ubuntu 20.04.

First we'll need to install lamp:

```
apt install lamp-server^

```

Then install php 7.4 gd

```
apt install php7.4-gd

```

Setup mysql securely:

```
sudo mysql_secure_installation

```

Enable apache rewrite and restart:

```
a2enmod rewrite; service apache2 restart

```

Install composer:

```
curl -sS https://getcomposer.org/installer -o composer-setup.php

```

Install drush launcher so u can use drush which needs to be installed individually per site (https://github.com/drush-ops/drush-launcher):

```
wget -O drush.phar https://github.com/drush-ops/drush-launcher/releases/latest/download/drush.phar

```

Next, create a mysql user so you can create databases for your drupal install: https://www.digitalocean.com/community/tutorials/how-to-create-a-new-user-and-grant-permissions-in-mysql

Now install drupal:

```
composer create-project drupal/recommended-project drupal

```

OR for drupal 8.9

```
composer create-project drupal/recommended-project:8.9 drupal

```

Then cd into that directory and install drush:

```
composer require drush/drush

```

Install drupal:

```
drush site:install

```

Enter all your info and it will auto install. Remember to link this directory to your apache folder /var/www/html or however you want to do it.
> 0 votes

---
Tags: installation
---


# Question
Title: How can I understand when hook_form_alter() is called?
In Drupal 8, `hook_form_alter()` is invoked multiple times: at page load, submission, after executing custom submission handlers, and back to form action.

How can I see at which stage `hook_form_alter()` is invoked?

# Answer
The lifetime cycle of a form and its stages depends on whether the form is rebuilding and using Ajax. Most times you react then on the form action you find in:

`$form_state->getTriggeringElement()`

The two different calls between page load and before the first submit is because the original form build is not cached and then has to be built the same way as the first one. Normally you don't care and alter the form build the same way for each call. If you need to make a distinction between both calls you find the raw submitted values in `$form_state->getUserInput()`
> 1 votes

---
Tags: 8, forms
---


# Question
Title: How to get taxonomy term reference fields value translated in twig
I have a taxonomy vocabulary with terms.

In a content type, I have a referenced field with this taxonomy.

I can get the taxonomy term in twig like this :

```
{% for item in node.field_lorem %}

    {{ item.entity.label }}

{% endfor %}

```

It works. But I don't know hot to get the translated terms when I switch language.

All other basic fields are translated. The multilingual configuration seems ok.

Example, a text field `{{ content.field_text }}` is translated.

The translation is activated for taxonomy (Taxonomy term is checked).

```
/admin/config/regional/content-language

```

The termes are translated :

```
taxonomy/term/11/translations

```

Is there something I miss in my twig ? Actually, I always get the terms in default language.

# Answer
Maybe I poorly explained the question but the solution was possible without preprocess.

In a content type, the referenced field with a taxonomy is called `field_lorem`

For this Entity reference field (Type of item to reference : taxonomy term), we select in Manage display (`admin/structure/types/manage/content_type_name/display`) « Rendered entity » instead of Label :

In the node template (`node--lorem-ipsum-content-type--full.html.twig`), we have simply `{{ content.field_lorem }}`

Then, we are able to see twig suggestion template name for this field based on `taxonomy_term.html.twig` :

In this twig, we can style independently all of the fields of the taxonomy term :

```
    {{ content.field_image[0] }}

    <p>{{ name[0] }}</p>

```

With this solution, translation of vocabulary terms works and we are able to have a custom template with all the field (in example an image field and name of the term)
> 1 votes

---
Tags: theming, taxonomy-terms, i18n-l10n
---


# Question
Title: How To Set Order State Completed after Notification?
I am Writing a **Payment Gateway(Onsite) Plugin** For Commerce 2, I am Stuck with Checkout Flow Step Transitions.

**Let Me Explain:** I am extending the **OnsitePaymentGatewayBase** and in the **createPayment()** Method I am setting the payment states to 'pending' \[if the payment gateway accepted the request\]and the payment state is setting well(no issues with payment state), Since My Payment Gateway is Async I need to implement onNotify() to change the payment state to 'completed'.

**My Issue:** Since Payment Gateway is Async(payment notification will be sent after a day) My order Sates also be needed to be in 'Pending' or something similar states but when I use default checkout flow I am getting the order completed even before the notification is processed. means after I checkout the order state is 'completed',

**What I want:** I want the order state to pending or review ..etc even after the checkout. only after the processing of notification the order state to be 'completed'

***Or Simply:*** *How can I set Order state to Pending or Review or darft..etc and Not 'completed' Only after receiving the Notification from Gateway, I have to set order state to completed*

Github LINK

# Answer
> 0 votes
Unfortunately, the "Default" order workflow for Commerce 2.x is fairly naive. It only has states for Draft (i.e. shopping carts), Completed (i.e. any placed order), and Canceled. If you need more states, you'll need to supply an alternate workflow. Core ships with a "Default, with validation" workflow you can set for your order type that includes a "Validation" step you could make use of instead.

Generally speaking, it's likely your payment gateway module shouldn't be controlling the actual order state transition. It can and should update the payment transition, and then a separate module specific to your site can be responsible for defining exactly what you want your workflow to be and automating the transition based on the order paid event (cf. OrderEvents::ORDER\_PAID).

---
Tags: commerce, plugins, payment-gateways
---


# Question
Title: How do the variables in .twig files work?
I am using a theme based off awesome zymphonies theme.

I'm trying to use the site\_logo variable from page.html.twig, but it doesn't have access to it, instead I have to use the page.header region, which somehow (I need clarification as to how) calls upon the code in block--system-branding-block.html.twig and there I can use site\_logo.

So my question is why site\_logo can only be accessed from that twig, and what would I need to do in order to use site\_logo, or any other variable in any other twig file?

# Answer
The `site_logo` block is available in the `page.header` region because that logo block itself is placed into that region using Drupal's block layout: mydrupalsite.com/admin/structure/block

Drupal's template/twig system is a set in parent and children type templates. So the `page.header` region/template may print `{{ site_logo }}` \- but the contents of `{{ site_logo }}` are outputted in `block--system-branding-block.html.twig`

Blocks are placed in regions so you can't really access a block directly in `page.html.twig` unless you add it programmatically.

Probably what you are looking to do is place the `site_logo` block into the region which approximates the position you want it to be displayed. Then if you want to "fine tune" it you can override that regions template using the following naming convention:

```
my_drupal_theme/templates/region--[region].html.twig

```

E.g.

```
my_drupal_theme/templates/region--header.html.twig

```

Then maybe your `region--header.html.twig` file looks like:

```
<div class="my-custom-wrapper-class">
  {{ site_logo }}
</div>

```

What can be really helpful here is knowing the basics of twig template naming conventions - and also turning on "twig template debugging" which gives you template names you can use to override.

https://www.drupal.org/docs/theming-drupal/twig-in-drupal/twig-template-naming-conventions https://www.drupal.org/docs/theming-drupal/twig-in-drupal/debugging-twig-templates#s-enable-debugging

Just for completeness: if you did want to load the logo directly in your `page.html.twig` you could add it via a `hook_preprocess_HOOK`

```
@file my_drupal_theme/my_drupal_theme.theme

/**
 * Implements hook_preprocess_page().
 */
function my_drupal_theme_preprocess_page(&$variables) {
  $block_manager = \Drupal::service('plugin.manager.block');
  $plugin_block = $block_manager->createInstance('system_branding_block', []);
  $variables['site_logo'] = $plugin_block->build();
}

```
> 4 votes

---
Tags: theming
---


# Question
Title: A deleted module is appearing in getEditable('core.extension')
Using Drupal core 8.9.6, created a custom module called `wdocsApi`. I wanted to rename it, so I uninstalled it and created `wdocs_api`. The problem is, when I try to install the new one, I get the error

> Drupal\Core\Extension\Exception\UnknownExtensionException: The module wdocsApi does not exist. in Drupal\Core\Extension\ExtensionList-\>getPathname() (line 522 of core/lib/Drupal/Core/Extension/ExtensionList.php).

I tracked it down to `Drupal/Core/Extension/ModuleInstaller.php` where a call is made to `$extension_config = \Drupal::configFactory()->getEditable('core.extension');` and my old module is returned in the list of modules.

What can I do to erase any remnants of the old one from my database?

# Answer
> 3 votes
There is many reasons for this and most likely the rename hapend before was completely uninstalled...

Here is a few examples of how to make sure its gone for good:

---

run the following somewhere

```
 \Drupal::service('module_installer')->uninstall(['wdocsApi']);

```

or Just

1. run `drush cex` to export the active config
2. Open up `core.extension.yml`  and delete the reference to "wdocsApi"
3. run `drush cim` to import the config

---
Tags: installation
---


# Question
Title: What could cause a View template to ouput wrong row index?
### Context

I have a weird issue on my live environment that I have never seen on my local environment. Cache bins are disabled on my local environment and enabled on live server.

When clearing all caches on live server, the problem disappears for some time, then reappears. When disabling cache bins on live server the problem doesn't seem to happen anymore.

### Issue

In my custom theme, I use a simple "Single field" template to override a given view field.

```
/**
 * @file
 * Theme override for a single field in a view.
 *
 * Available variables:
 * - view: The view that the field belongs to.
 * - field: The field handler that can process the input.
 * - row: The raw result of the database query that generated this field.
 * - output: The processed output that will normally be used.
 *
 * When fetching output from the row this construct should be used:
 * data = row[field.field_alias]
 *
 * The above will guarantee that you'll always get the correct data, regardless
 * of any changes in the aliasing that might happen if the view is modified.
 *
 * @see template_preprocess_views_view_field()
 */

```

In the output HTML of this field, I need a simple incremental id from `0` to `n` where `n` would be the total number of rows in the view results. Something like below for a View with 5 results:

```
<div data-index="0">...</div>
<div data-index="1">...</div>
<div data-index="2">...</div>
<div data-index="3">...</div>
<div data-index="4">...</div>

```

So in my field template, I use:

```
<div data-index="{{ row.index }}">...</div>

```

This works fine, except on some occasions, only on my live server with caching enabled where the output will be for example:

```
<div data-index="0">...</div>
<div data-index="1">...</div>
<div data-index="19">...</div>
<div data-index="3">...</div>
<div data-index="21">...</div>

```

Important notes:

* I sometimes get indices such as `19` when there are only 10 or 15 results in the view so that number seems to come out of the blue.
* This happens when the view is filtered using a single taxonomy term.

### Question

Am I wrong assuming that `row.index` should give me an incremental sequence of integers for every view, with or without caching? If I am wrong, then what should I be using? And if not, what could cause this behavior?

# Answer
To solve it using views-view-field.html.twig

First in view settings, add field "View Result Counter" and hide from display.

Now in your twig you can do

```
<div data-index="{{ view.field['counter'].getValue(row) }}">...</div>

```
> 2 votes

# Answer
> If I am wrong, then what should I be using?

Instead, you could do it using views-view--unformatted.html.twig

and modify the row part to

```
{% set count = 0 %}
{% for row in rows %}
  set count = count + 1
  {%
    set row_classes = [
      default_row_class ? 'views-row',
    ]
  %}
  <div data-index=count {{ row.attributes.addClass(row_classes) }}>
    {{ row.content }}
  </div>
{% endfor %}

```
> 1 votes

---
Tags: 8, views, theming
---


title: Error handling with Drupal.ajax()

text:
# Question
Title: Error handling with Drupal.ajax()
First I am not very good in JavaScript so maybe I do not know some very basics... I apologize in advance.

I created a form where I want to save every change in single fields directly without the need to submit the form each time. Therefore I created a custom route which returns an AjaxResponse on successfull database savings as well as on any errors on the Drupal side.

But I want to be aware of any errors which may appear on the client side as well. `$.ajax()` has the function `.fail()` and `.done()` where I can do different things in my JavaScript when something went wrong. These methods are missing for `Drupal.ajax()`. Is there any way to react on errors when using `Drupal.ajax()`?

I tried

```
try {
  Drupal.ajax({url: path}).execute();
}
catch (e) {
  alert(e.name + ": " + e.message);
}

```

and built in some errors on my controller but all that happens is that the browsers console lists Ajax errors - no alert is shown to the client.

# Answer
You can using like jQuery ajax. Because `Drupal.ajax({}).execute()` is a function and return the jqXHR.

```
 /**
   * Execute the ajax request.
   *
   * Allows developers to execute an Ajax request manually without specifying
   * an event to respond to.
   *
   * @return {object}
   *   Returns the jQuery.Deferred object underlying the Ajax request. If
   *   pre-serialization fails, the Deferred will be returned in the rejected
   *   state.
   */
  Drupal.Ajax.prototype.execute = function() {
    // Do not perform another ajax command if one is already in progress.
    if (this.ajaxing) {
      return;
    }

    try {
      this.beforeSerialize(this.element, this.options);
      // Return the jqXHR so that external code can hook into the Deferred API.
      return $.ajax(this.options);
    } catch (e) {
      // Unset the ajax.ajaxing flag here because it won't be unset during
      // the complete response.
      this.ajaxing = false;
      window.alert(
        `An error occurred while attempting to process ${this.options.url}: ${e.message}`,
      );
      // For consistency, return a rejected Deferred (i.e., jqXHR's superclass)
      // so that calling code can take appropriate action.
      return $.Deferred().reject();
    }
  };

```

source

So in your case:

```
var ajaxExecute = Drupal.ajax({url: path}).execute();

ajaxExecute.done(function() {
    alert( "success" );
})
.fail(function() {
    alert( "error" );
})

```
> 8 votes

---
Tags: 8, ajax
---


# Question
Title: Allow specific HTML tags inside a text field of a custom content type using CKEditor
I would like to add a new content type with a field which supports some HTML tags. So far, I added a text editor format and there I chose CKEditor as the editor and edited the list of allowed tags according to what I want to achieve. Then I added a new content type with a field of type formatted text. If I now add new content, CKEditor shows up where I expect it, but when I edit the source code and enter, for instance, an `<h2>` tag, it becomes a `<p>` tag after saving. The specific problem I'm facing is that I can't figure out how to "connect" an editor format to a field and make it selectable for the one who adds a field to a content type (for example inside the drop down menu where one can select the field type). Do you know any good documentation or tutorial which deals with this topic? Thanks in advance for your help!

# Answer
> I can't figure out how to "connect" an editor format to a field and make it selectable for the one who adds a field to a content type.

The text formats are shown in order here:

`/admin/config/content/formats`

The format at the top of the list is the default format. To change the order of the formats, drag the arrow icon on the leftmost side and then press save.

Users can only see formats for which they have permission. The roles with permission are listed in the **Roles** column of the table at `/admin/config/content/formats`. To change the permissions, click "Configure" for the relevant format and add the correct roles.
> 3 votes

---
Tags: wysiwyg
---


title: Webform Start Date and End Date

text:
# Question
Title: Webform Start Date and End Date
I'm having a heck of a time setting the start date and end date for a Webform.

We've got a node with a webform entity reference field that generates a new Webform. On that node form, we want to give people the option to set the new form's status. Here's a trimmed-down look at our code (I've omitted most of the superfluous stuff)...

```
// Get the status from the node creation form
$reg_form_status = $form_state->getValue('field_registration_form')[0]['settings']['status'];
// Get the scheduled dates
$reg_form_scheduled_open = $form_state->getValue('field_registration_form')[0]['settings']['scheduled']['open'];
$reg_form_scheduled_close = $form_state->getValue('field_registration_form')[0]['settings']['scheduled']['close'];
// create a new instance of our pre-generated webform
$webform = \Drupal::entityTypeManager()->getStorage('webform')->load('student_registration');
if (!empty($webform)) {
  $duplicate = $webform->createDuplicate();
  $duplicate->set('status',$reg_form_status);
  $duplicate->set('open',$reg_form_scheduled_open);
  $duplicate->set('close',$reg_form_scheduled_close);
  $duplicate->save();
}

```

Without setting the open/close dates, the form is created just fine. If it's set as "Open", then it sets correctly as open. If it's set as "Closed", then it is created as closed. However, if I try to set it as Scheduled, it defaults to open. If I try to set it as scheduled with the dates, then it throws `Invalid data type for config element` when saving the node.

I tried re-casting as a date object, but that doesn't seem to be working either.

```
$event_date_start = new DrupalDateTime($reg_form_scheduled_open, 'EST');
$event_date_close = new DrupalDateTime($reg_form_scheduled_close, 'EST');

```

with

```
$duplicate->set('open',$event_date_start);
$duplicate->set('close',$event_date_close);

```

Which hasn't resolved this issue. Here's the full stack trace...

```
An error has occurred: Drupal\Core\Config\UnsupportedDataTypeConfigException: Invalid data type for config element webform.webform.student_registration2006:open in /var/www/docroot/core/lib/Drupal/Core/Config/StorableConfigBase.php:207 Stack trace: #0 /var/www/docroot/core/lib/Drupal/Core/Config/Config.php(212): Drupal\Core\Config\StorableConfigBase->castValue('open', Object(Drupal\Core\Datetime\DrupalDateTime)) #1 /var/www/docroot/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php(284): Drupal\Core\Config\Config->save(false) #2 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityStorageBase.php(457): Drupal\Core\Config\Entity\ConfigEntityStorage->doSave('student_registr...', Object(Drupal\webform\Entity\Webform)) #3 /var/www/docroot/core/lib/Drupal/Core/Config/Entity/ConfigEntityStorage.php(263): Drupal\Core\Entity\EntityStorageBase->save(Object(Drupal\webform\Entity\Webform)) #4 /var/www/docroot/modules/contrib/webform/src/WebformEntityStorage.php(133): Drupal\Core\Config\Entity\ConfigEntityStorage->save(Object(Drupal\webform\Entity\Webform)) #5 /var/www/docroot/core/lib/Drupal/Core/Entity/EntityBase.php(395): Drupal\webform\WebformEntityStorage->save(Object(Drupal\webform\Entity\Webform)) #6 /var/www/docroot/core/lib/Drupal/Core/Config/Entity/ConfigEntityBase.php(616): Drupal\Core\Entity\EntityBase->save() #7 /var/www/docroot/modules/custom/shgt_theme_helper/shgt_theme_helper.module(288): Drupal\Core\Config\Entity\ConfigEntityBase->save() #8 [internal function]: shgt_theme_helper_event_by_county(Array, Object(Drupal\Core\Form\FormState)) #9 /var/www/docroot/core/lib/Drupal/Core/Form/FormSubmitter.php(114): call_user_func_array('shgt_theme_help...', Array) #10 /var/www/docroot/core/lib/Drupal/Core/Form/FormSubmitter.php(52): Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object(Drupal\Core\Form\FormState)) #11 /var/www/docroot/core/lib/Drupal/Core/Form/FormBuilder.php(593): Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object(Drupal\Core\Form\FormState)) #12 /var/www/docroot/modules/contrib/autosave_form/src/Form/AutosaveFormBuilder.php(144): Drupal\Core\Form\FormBuilder->processForm('node_event_by_c...', Array, Object(Drupal\Core\Form\FormState)) #13 /var/www/docroot/core/lib/Drupal/Core/Form/FormBuilder.php(321): Drupal\autosave_form\Form\AutosaveFormBuilder->processForm('node_event_by_c...', Array, Object(Drupal\Core\Form\FormState)) #14 /var/www/docroot/modules/contrib/autosave_form/src/Form/AutosaveFormBuilder.php(97): Drupal\Core\Form\FormBuilder->buildForm(Object(Drupal\node\NodeForm), Object(Drupal\Core\Form\FormState)) #15 /var/www/docroot/core/lib/Drupal/Core/Controller/FormController.php(91): Drupal\autosave_form\Form\AutosaveFormBuilder->buildForm(Object(Drupal\node\NodeForm), Object(Drupal\Core\Form\FormState)) #16 /var/www/docroot/core/modules/layout_builder/src/Controller/LayoutBuilderHtmlEntityFormController.php(39): Drupal\Core\Controller\FormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch)) #17 [internal function]: Drupal\layout_builder\Controller\LayoutBuilderHtmlEntityFormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch)) #18 /var/www/docroot/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array) #19 /var/www/docroot/core/lib/Drupal/Core/Render/Renderer.php(573): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() #20 /var/www/docroot/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure)) #21 /var/www/docroot/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) #22 /var/www/vendor/symfony/http-kernel/HttpKernel.php(151): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() #23 /var/www/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #24 /var/www/docroot/modules/contrib/simple_oauth/src/HttpMiddleware/BasicAuthSwap.php(67): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #25 /var/www/docroot/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Drupal\simple_oauth\HttpMiddleware\BasicAuthSwap->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #26 /var/www/docroot/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #27 /var/www/docroot/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #28 /var/www/docroot/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #29 /var/www/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #30 /var/www/docroot/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true) #31 /var/www/docroot/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request)) #32 {main}

```

Does anyone have a working example or link to documentation on setting the open/close date on a webform programmatically?

# Answer
> 1 votes
I believe I may have found the answer in WebformEntityTest.php in the Webform module. There, a test creates a webform with the following settings for the scheduled dates...

```
$webform->setStatus(WebformInterface::STATUS_SCHEDULED);
// Check set open date to yesterday.
$webform->set('open', date('Y-m-d\TH:i:s', strtotime('today -1 days')));
$webform->set('close', NULL);
$this->assertTrue($webform->isOpen());</code>

```

So I've done some testing, and for my use case, the following seems to be working so far.

```
$duplicate->set('open',date('Y-m-d\TH:i:s', strtotime($reg_form_scheduled_open)));
$duplicate->set('close',date('Y-m-d\TH:i:s', strtotime($reg_form_scheduled_close)));

```

If anyone has any remaining input on this, I'd appreciate that. Thanks!

---
Tags: webforms
---


title: Custom Module to remove User Menu Tabs

text:
# Question
Title: Custom Module to remove User Menu Tabs
I'm hoping someone can take pity on me because I just can't seem to figure out how to make a simple module to remove, or hide some tabs in my user pages. I read the docs on making custom modules, questions about removing tabs, and thought I figured it out. I made a custom module called 'TabEdit' with this structure, just to test it out:

/tabedit

```
    tabedit.info.yml
    tabedit.module

```

tabedit.info.yml

```
name: TabEdit
description: Edit tabs shown in user pages.
type: module
package: custom
core: 8.x
core_version_requirement: ^8 || ^9

```

tabedit.module

```
<?php
/**
 * Implements hook_menu_local_tasks_alter()
 */
function tabedit_menu_local_tasks_alter(&$data, $route_name) {
  unset($data['tabs'][0]['simplenews.newsletter_subscriptions_user']);
}

```

It didn't work, so I obviously still don't get the fundamentals on how to make a module. What I want to do is remove the Shortcuts, Simplenews Subscriptions, Activity, and Submissions from the user menu tabs.

# Answer
Hooks need to be written in . module file not in controller. Move your code to .module file and also it should be tabedit\_menu\_local\_tasks\_alter

**tabedit.module**

```
<?php

/**
 * Implements hook_menu_local_tasks_alter()
 */
function tabedit_menu_local_tasks_alter(&$data, $route_name) {
  unset($data['tabs'][0]['simplenews.newsletter_subscriptions_user']);
}

```
* Clear flush all caches so hook gets pickedup.
> 2 votes

# Answer
A file like src/Controller/RemoveTabEdit.php is for a class, not a function. In the specific, it's not for hook implementations, which should always go in the module file.

The src/Controller/RemoveTabEdit.php file is automatically loaded when the `RemoveTabEdit` class is used, but since that doesn't happen, the file is never loaded and that hook implementation is never found.

As side note, it's better to avoid uppercase characters in the module machine name. While PHP is case insensitive, the code looking for `hook_update_N()` implementations is still case sensitive.
> 1 votes

# Answer
This did finally works. I renamed it tabedit.module and made the code

```
<?php
/**
  * Implements hook_menu_local_tasks_alter().
  */
function tabedit_menu_local_tasks_alter(&$data, $route_name) {
/*      If a current user has the 'administrator' role then do not hide the tabs.
    $current_user_roles = \Drupal::currentUser()->getRoles();
    if (in_array('administrator', $current_user_roles)) {
        return;
    }
*/
    unset($data['tabs'][0]['tracker.user_tab']);
    unset($data['tabs'][0]['shortcut.set_switch']);
    unset($data['tabs'][0]['simplenews.newsletter_subscriptions_user']);
    unset($data['tabs'][0]['entity.webform_submission.user']);
}
``

```
> 0 votes

---
Tags: navigation
---


# Question
Title: Is there a NULL value for a multi-value list?
I have a list that accepts 5 different values, but some things on my spreadsheet are empty, meaning its none of the 5 things. However during the feeds import, it is saying my empty field is not a valid selection.

Is there a way I can still import even though the value is empty?

# Answer
> 0 votes
Select Element's API

> #empty\_option: (optional) The label to show for the first default option. By default, the label is automatically set to "- Select -" for a required field and "- None -" for an optional field.
>
> #empty\_value: (optional) The value for the first default option, which is used to determine whether the user submitted a value or not.

So using this information, you are able to use the null value's defaults from the select element.

---
Tags: 8, feeds
---


# Question
Title: How do I index custom fields with the search API using elasticsearch?
I see all kinds of tutorials to get apache to index content. Is there any difference in getting elasticsearch to index my new custom field?

On the field page I can see my field but when i expand it there is nothing to add.

Using this Create custom fields using custom Processors in Drupal 8 tutorial, but it doesn't seem to be working and no errors are being thrown so I don't know if my code is broken or this is apache specific.

# Answer
You seems to have provided link for creating custom fields using processor. Processor works smoothly for me.

1. Create custom fields using processor.
2. Make sure your name spaces are done correctly.
3. Enable your processor from the processor tab of Elasticsearch ui in Backend.
4. Go to "fields" section. You will see your added field there.
5. Finally Index item.
> 0 votes

---
Tags: 8, search
---


title: Aggregating data to show latest result?

text:
# Question
Title: Aggregating data to show latest result?
I'm currently using the Elasticsearch Connector to get my data from Elasticsearch for displaying. I've managed to set up some basic pages and display the data successfully, but am now looking for a way to group it. for example, if I have several results but they are all from the same server address, I would like to group them by server and show only the lastest input.

I've looked through options on views, and the aggregator module but can't seem to manage it. Is this something that's possible, and I've missed? Or is that not possible in drupal anyway?

# Answer
In Views you can group by a particular field if the display allows fields (table, not teaser, etc). Under the Settings for Table for example you can choose the field to group the results:

The field has to be present in the list of Fields, but can be excluded from display if desired.
> 0 votes

# Answer
You can use aggregation query in elastic search to group data.

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations.html
> 0 votes

---
Tags: css-js-aggregation
---


# Question
Title: Menu setting not visibile for other roles on Node Form
In Drupal 8 I am creating Editor role with limited access, but the Editor cannot see "Menu Settings" while creating or editing content, this would be helpful when Editor add the node to the menu while creating node. I checked the permission and I can't see any option to turn on Menu Settings for the Editor role or for other roles.

# Answer
> 1 votes
Go to /admin/people/permissions and make sure the 'administer menu settings' are set for the Editor role. But I think it is better to install the Menu Admin per Menu module. With this module you make sure the Editor only gets access to certain menu's.

> Menu Admin per Menu allows to give roles per menu admin permissions without giving them full admin permission.

> For instance, you may let certain users manage the items of the Main or Navigation menus but not those of the Management menu.

---
Tags: 8, navigation
---


# Question
Title: Search API location distance filter not working
I'm trying to create a search page with Search API Solr, Search API location and a Geolocation field.

I've got my view, and my lat/lng fields are correctly indexed. E.g. I've selected these fields for my view

```
Content datasource: my_title_field (indexed field)
Content datasource: my_geo_field
Content datasource: my_geo_field (distance) (indexed field)
Content datasource: my_geo_field (indexed field)

```

and I'm getting results like this:

```
foo_title
47.4051909, 10.2867823
47.4051909, 10.2867823

```

The `(distance)` version of the geolocation field is always empty.

As soon as I add a filter to `my_geo_field`, I incorrectly do not get any results:

The query seems to be correctly:

```

Index: cms
Keys: NULL
Options: array (
    'search_api_view' => 'object (Drupal\\views\\ViewExecutable)',
    'search_api_location' =>
    array (
      0 =>
      array (
        'field' => 'field_geo',
        'lat' => '47.4051909',
        'lon' => '10.2867823',
        'radius' => 100,
      ),
    ),
    'search_api_base_path' => 'testsuche',
  )

```

but the results are empty, no matter which filter settings.

I've also tried the "Boundary" filter from Geolocation module, it also doesn't work with boundary lat/lng pairs.

### Questions:

What is the difference between the normal `my_geo_field` and the `my_geo_field (indexed field)` when selecting fields to display? Which one should I Use?

What is the purpose of `my_geo_field (distance) (indexed field)`? It does not have any content, it is not available in the filters section of the view, it does not have a configuration for the remote point to calculate the distance... it doesn't make any sense and it is really confusing me.

And finally and most important: Which settings do I need to make the filter working?

Has anybody managed to make a working proximity filter with Search API or is it just broken?

# Answer
> 0 votes
Geolocation indexing is broken with Search API v1.16+ and will be fixed with issue 3157397

If you manually want to check the index on the Solr server, be sure to check the right fields: Spatial fields from Search API Location have the prefix `locs_`, e.g. if your Search API field name is `field_geo`, the Solr field name is `locs_gield_geo`

If you have any other `lat` or `lng` fields in the Solr index, those are NOT spatial fields and can not be used with Search API Location. E.g. I had Solr fields like `fts_lat` and `fts_lng` with correct geo data, but those were decimal number values, which cannot be used for proximity queries.

Also be careful with pseudo-debugging by rendering the raw geofield values as a field in your Drupal View. Just because Views is able do render the correct values, it does not necessarily mean that those values are originating from the Solr server. I made the wrong assumption when Views is rendering them, they had to be correctly indexed by Solr. But obvisouly those values were coming from the local SQL database, good enough for rendering, but not good enough for filtering or sorting.

---
Tags: 8, search, location
---


# Question
Title: Finding nodes that have not been indexed
On a Drupal 8 website I'm administering the ratio of paged indexed by search\_cron stays at a value far below 100%.

New pages are indexed, but it looks as if updated pages are not indexed again. I suspect that there is some problem that keeps nodes from being (re-)indexed. However, I see no error in the log. Search\_cron takes very long - several minutes even when indexing only 20 pages per cron run.

There is a page Troubleshooting cron which contains an SQL query (under "Check for problems with modules") to find nodes that haven't been indexed so one can inspect them for bad content. Unfortunately, this works only with Drupal 7, and I couldn't find a similar page for Drupal 8.

How can I find non-indexed nodes on Drupal 8?

Any other idea on how to track down the problem?

**Update:** I now found a way to log the nodes being indexed by adding a call to the logger to NodeSearch.php. Which admittedly is a hack.

I can now see that Drupal tries to index the same nodes again and again, without success and without error messages. However, I haven't found out the reason yet.

# Answer
> 3 votes
The status of node indexing is based on the `search_dataset`. This table stores content keyword blobs and their associated `sid`, the primary key for the content's keyword (i.e. the `nid`). When compared/joined against the `node` table, it should let you see which nodes aren't index.

From what it sounds like, you've already spotted problem node(s) so it's just a matter of confirmation. Removing the node(s) from being indexed (e.g. hacking `NodeSearch::indexNode()`) to confirm it's the problem, then finding out what content in the node is blocking indexer.

# Answer
> 0 votes
We have a tracker to mark nodes indexed in the Drupal database in 'search\_api\_item' table.

```
\Drupal\search_api\Plugin\search_api\tracker\Basic

```

You can investigate the class. It will help to understand how to check if nodes were indexed. For example, after updating a node this tracker will be called from this method

```
\Drupal\search_api\Entity\Index::trackItemsInsertedOrUpdated

```

Be care with 'indexing\_order': 'fifo' =\> $this-\>t('Index items in the same order in which they were saved'),

It can make problems because we have this code in the tracker class:

```
    // Update the status of unindexed items only if the item order is LIFO.
    // (Otherwise, an item that's regularly being updated might never get
    // indexed.)
    if ($this->configuration['indexing_order'] === 'fifo') {
      $update->condition('status', self::STATUS_INDEXED);
    }

```

---
Tags: search, cron
---


# Question
Title: "You are not authorized to access this page." in Chrome after returning from offsite payment
After concluding checkout flow on site I'm redirected to offsite payment service (Datatrans). There if I finish payment and I get redirected back to:

/checkout/order\_number/payment/return

or I cancel payment and get redirected back to:

/checkout/order\_number/payment/cancel

on site I get the message:

***You are not authorized to access this page.***

At that point I'm not logged out - if I just reload the page (click on browser address bar and hit enter to open page again. I get redirected to:

/checkout/order\_number/order\_information

Important - this happens only **in Google Chrome**. In Firefox this works well.

# Answer
> 0 votes
Possible solution would be adding following rows to .htaccess file inside `<IfModule mod_headers.c>` block.

```
  Header always edit Set-Cookie (.*) "$1; SameSite=None; Secure"
  Header onsuccess edit Set-Cookie (.*) "$1; SameSite=None; Secure"

```

Some more info on this issue:

https://docs.datatrans.ch/v1.0.1/docs/security-samesite-cookies

---
Tags: 8, commerce
---


# Question
Title: How can I make a view block of related products?
I have read through the issue queue and read all kinds of documentation and made all kinds of settings in Views Contextual Filter and no luck at all. What can be the definitive way to make a Views block of related Commerce 2 products?

My products are tagged to taxonomy terms of which the taxonomy vocabulary is referenced on the product. I now tried to make a Views block to make contextual filter such that if viewing a product you can find a block of other products belonging to same taxonomy term.

No settings are working.

# Answer
This patch solved this issue, https://www.drupal.org/project/commerce/issues/3015347#comment-13310494
> 0 votes

---
Tags: commerce
---


title: Changing 2 Elements on Ajax Callback

text:
# Question
Title: Changing 2 Elements on Ajax Callback
I have an element `$form['elements']['manufacturer']`. On change, I want to change `$form['elements']['form_factor']` and `$form['elements']['model']`.

Currently I have:

```
$form['elements']['manufacturer']['#ajax'] = [
    'callback' => 'formChanged',
    'wrapper' => 'form-factor',
    'event' => 'change',
];

```

which works and changes the form-factor. But, **I want to change the model** as well.

Iniside `formChanged` return form-factor in the callback function, so I can't return model element.

```
function formChanged(array &$form, FormStateInterface $formState){
  $form["elements"]["form_factor"]["#value"] = 0;
  return $form["elements"]["form_factor"];
}

```

Reading from past posts, one option was to return the whole form inside `formChanged` (`return $form`), but this doesn't seem like a good approach.

I can't do something like, having 2 callbacks:

```
$form['elements']['manufacturer']['#ajax'] = [
   [
    'callback' => 'formChanged',
    'wrapper' => 'form-factor',
    'event' => 'change',
   ],
   [
    'callback' => 'anothercallback',
    'wrapper' => 'another-one',
    'event' => 'change',
   ]
];

```

# Answer
> 4 votes
Remove the wrapper key

```
$form['elements']['manufacturer']['#ajax'] = [
  'callback' => 'formChanged',
  'event' => 'change',
];

```

Your callback

```
public function formChanged(array &$form, FormStateInterface $formState){
    $form['elements']['form_factor']['#value'] = 0;
    $form['elements']['model']['#value'] = 0;
    $response = new \Drupal\Core\Ajax\AjaxResponse();
    $response->addCommand(new \Drupal\Core\Ajax\ReplaceCommand(".form-item-form-factor", $form['elements']['form_factor']));
    $response->addCommand(new \Drupal\Core\Ajax\ReplaceCommand(".form-item-model", $form['elements']['model']));
    return $response;
}

```

# Answer
> 3 votes
Instead of returning a single render array (of all or part of your form) from your `callback`, you will need to return an `AjaxResponse` that contains a `ReplaceCommand` for each piece of the form you want to replace:

For example, in your callback:

```
$response = new AjaxResponse();
$response
  ->addCommand(new ReplaceCommand('#edit-form-factor', $form_factor_element))
  ->addCommand(new ReplaceCommand('#edit-model', $model_element));
return $response;

```

See the guide: https://www.drupal.org/docs/drupal-apis/ajax-api/basic-concepts#sub\_form

And the Ajax commands reference: https://www.drupal.org/docs/drupal-apis/ajax-api/core-ajax-callback-commands

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


# Question
Title: Creating a fallback field to load conditionally
So if I have a node type of Article. I have two fields on it:

* field\_image
* field\_secondary

If field\_secondary is being used, I'd like for that to be shown over field\_image. Can anyone help point me in the right direction how I'd go about this?

# Answer
> 1 votes
If field\_secondary is also an image field, then you can check if it is empty in your Twig template:

For example, in `node--article.html.twig`:

```
{% if content.field_secondary is empty %}
  {{ content.field_image }}
{% else %}
  {{ content.field_secondary }}
  {{ content.field_image }}
{% endif %}

{{ content.without('field_image', 'field_secondary') }}

```

(Your actual template will have more HTML in it.)

---
Tags: nodes
---


# Question
Title: How do I send a command after submitting a form?
I need to do something when the user submits a form so that it sends a command to the server, :

```
 if($_GET["cmd"]=="save")

```

Got to do something with the thing above, I thought of using:

```
<a href="?cmd=save">Save</a>

```

But if I do that it will not complete the form action so:

```
<form action="{{ pageName }}">

```

Will not be executed... So how would I fix this problem? thanks all :)

# Answer
> 2 votes
The Drupal way to do this is to use hook\_form\_alter() to add a submit hook, and then add your command in the submit hook. Here's a simple example.

You'll need to add this code to a custom module.

```
function MYMODULE_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'my_form_id') {
      $form['actions']['submit']['#submit'][] = 'MYMODULE_my_form_submit';
  }
}

function MYMODULE_my_form_submit(array &$form, FormStateInterface &$form_state) {
  // Insert command here.
}

```

---
Tags: forms
---


# Question
Title: Sending form to mail from custom module fails without error
I've created a module with a form and a block.

When I push the subscribe button, the submitForm function is executed.

The successmessage is shown, but no e-mail is send ...

There are no errors reported in the recent logmessages or in on the server in the folder /logs.

```
public function submitForm(array &$form, FormStateInterface $form_state)
    {
        /**
         * @var MailManager $mailer
         */
        $mailer = \Drupal::service('plugin.manager.mail');

        $email = $form_state->getValue('email');
        $params['context']['subject'] = "Subscribe newsletter";
        $params['context']['message'] = 'Someone subscribed: ' . $email;
        $params['email'] = $email;

        try {
            $response = $mailer->mail('my_module', 'subscribe', 'to@email.com', 'nl', $params);
            if ($response) {
                $this->messenger()->addStatus($this->t('You are successfully subscribed to our newsletter with your e-mail: @email', ['@email' => $email]));
            } else {
                $this->messenger()->addStatus($this->t('There was an error.'));
            }
        } catch (MailHandlerException $e) {
            \Drupal::logger('mailinglist_send_mail_error')->notice('<pre><code>' . print_r($e, true) . '</code></pre>');
        }

    }

```

# Answer
> 1 votes
> Did you implement hook\_mail in your module? – Alfred Armstrong
>
> where to place the hook\_mail function? – Lance

Goes in the .module file. Ex: **my\_module.module**

```
/*
* Implements hook_mail().
*/
function my_module_mail($key, &$message, $params) {
  switch($key) {
    case 'my_module':
      $options = [
        'langcode' => $message['langcode'],
      ];
      $message['subject'] = t('@title', ['@title' => $params['context']['subject']], $options);
      $message['body'][] = t('@body', ['@body' => $params['context']['message']], $options);
      break;
  }
}

```

Flush all caches so hook gets picked up.

---
Tags: forms, emails
---


title: Clear entity cache before render

text:
# Question
Title: Clear entity cache before render
I secured some file in an s3 bucket using s3fs. My problem is : the "Expires" argument send to build the file URI is not reset each time the object is call in my API.

time doesn't change if I don't clear the cache with drush

```
$expires = time() + 10;

```

So I tried to use hook\_entity\_view :

```
if ($entity->bundle() === 'my_bundle') {
    foreach ($entity->getCacheTags() as $tag) {
      $tags[] = $tag;
    }
  }

```

Doesn't work

```
Drupal::entityTypeManager()->getStorage($entityType)->resetCache();

```

Nop

```
\Drupal::service('cache.render')->deleteAll();
\Drupal::service('cache.entity')->deleteAll();
\Drupal::service('cache.data')->deleteAll();

```

deleteAll or invalidateAll, none of it work.

```
drupal_flush_all_caches();

```

Nothing, I'm starting to think I have config problem... If someone can save me !

### UPDATE

It seems hook\_entity\_load works with my API, it clear the cache correctly. The problem remains when i'm trying to watch the content in my Drupal website, in the content view.

# Answer
> 0 votes
Ok everything is fixed, there were 2 points :

* Clean the cache when the media 'masterclass\_private\_video' is called, so the request to AWS s3 has the correct "Expires" timestamp when call by my VueJs API.
* Clean the render cache of the content view in my drupal backend.

Clean the media cache for the API :

```
function mymodule_entity_load(array $entities, $entity_type_id)
{
  $tags = [];
  foreach ($entities as $entity) {
    if ($entity->bundle() === 'masterclass_private_video') {
      foreach ($entity->getCacheTags() as $tag) {
        $tags[] = $tag;
      }
    }
  }

  if (!empty($tags)) {
    Cache::invalidateTags($tags);
  }
}

```

Clean the page cache :

```
function mymodule_node_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display)
{
  if ($entity->bundle() === 'masterclass' || $entity->bundle() === 'masterclass_chapter') {
    $build['#cache']['max-age'] = 0;
    \Drupal::service('page_cache_kill_switch')->trigger();
  }
}

```

To be clear, the goal is to reset the $expires, so the AWS s3 works :

```
function mymodule_s3fs_url_settings_alter(array &$url_settings, $s3_file_path)
{
  $split = explode('/', $s3_file_path);

  if (in_array('private', $split)) {
    $file_path = getenv('AWS_CLOUDFRONT_ENDPOINT') . $s3_file_path;

    $expires = time() + 86400;
    $private_key_filename = '/var/www/my-drupal/keys/pk-cloudfront.pem';
    $key_pair_id = getenv('AWS_S3_KEY_ID');

    $canned_policy_getters = Drupal::service('mymodule.aws.signature')
      ->getCannedPolicyGetters($file_path, $private_key_filename, $key_pair_id, $expires);

    $url_settings['custom_GET_args'] = $canned_policy_getters;
  }
}

```

---
Tags: hooks, caching
---


# Question
Title: How do I use Font Awesome on a form submission button?
So I've got Font Awesome working on my Drupal 7 site. I'm not using the Font Awesome Drupal module. I'm just declaring the style sheet in the template.php.

```
function genchstyle_preprocess_html(&$variables) {
  drupal_add_css(
    'http://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css',
    array('type' => 'external')
  );
}

```

Now, if I use `<i class="icon-search"></i>`, I get a nice little magnifying glass icon.

I've recently learned how to replace a form's *Submit* button with an image like this.

```
function genchstyle_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'search_block_form') {
    $form['actions']['submit']['#type'] = 'image_button';
    $form['actions']['submit']['#src'] = drupal_get_path('theme', 'genchstyle') . 'images/search.png';
    $form['actions']['submit']['#attributes']['class'][] = 'icon-search';
  }
}

```

I can't figure out how to replace the submit button with the Font Awesome icon. I tried adapting the above script to use `$form['actions']['submit']['#markup']` and I can get it to replace the button with the icon, but then the icon is no longer a functioning submission trigger (or even a link).

I've reviewed all the Font Awesome examples and googled the heck out of this but I can't find a solution.

Any suggestions?

# Answer
> 9 votes
I've been trying to solve the same problem, and I think I've found a solution, but it's a little hacky. I'm hoping that someone else can build on this and make it better.

So, the fundamental problem is that Drupal forms by default use `<input type="submit" value="Submit">` and in order to use FontAwesome, you need to apply css which you cannot do to `<input>`. You can, however, add text and apply css using `<button>`. So the goal is to replace `<input type="submit" value="Submit">` with `<button type="submit" value="Submit"><i class="icon-search"></i></button>`

In order to add the new form button, I used hook\_form\_alter in my template.php file in my theme folder (replace MYTHEME with the name of your theme):

```
function MYTHEME_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'search_block_form') {
    $form['actions']['button']['#prefix'] = '<button type="submit" value="Submit">';
    $form['actions']['button']['#suffix'] = '</button>';
    $form['actions']['button']['#markup'] = '<i class="icon-search"></i>';
  }
}

```

So this adds the correct markup to the form, but unfortunately, we now have two submit buttons. If you use kpr($form), you can see that there's a default submit button array in $form\['actions\]\['submit'\]. I tried getting rid of it by using unset($form\['actions'\]\['submit\]); and also $form\['actions'\]\['submit'\]\['#access'\]=FALSE. Both of these will get rid of the default submit button, but unfortunately, that breaks the search form in Drupal such that upon submission, the user gets sent to the home page with no search results displayed. The form action points to the home page, and then gets redirected to /search/node/\[search term\], so I'm guessing that Drupal core does some processing that requires the `<input>` field to redirect to the search results page. I don't know how to make this work with my `<button>`.

So my hack was to use css to set the default `<input>` submit button to "display: none", so my form has effectively two submit buttons, but the default one is hidden and only my `<button>` element with FontAwesome is visible. Now, the search function works, but it seems inelegant to have two submit buttons in the html. If anyone can improve upon this, I'd be very grateful.

# Answer
> 20 votes
I normal replace search button value into Fontawesome Unicode code.

In your css just define fontawesome font-family.

E.G In your own module call hook\_form\_alter()

```
if($form_id = 'search_block_form'){
  $form['actions']['submit']['#value'] = decode_entities('');

```

}

remeber use decode\_entities() to parse the Unicode code.

CSS

```
.block-search input[type="submit"]{
  border: 0;
  font-size: 1.3em;
  vertical-align: top;
  margin-left: -45px;
  font-family: 'FontAwesome';
}

```

You should get search icon on button and place inside of your text input field.

ref. Font-Awesome cheatsheet

# Answer
> 3 votes
I've accomplished this with my own theme function to account for an extra setting in a `hook_form_alter`. My example is changing the search input from an input to a button. From there I can add classes for pseudo element icons. This would go in the template.php with the proper machine names and form ids swapped out.

```
/**
 * Implements theme_button().
 */
function THEMENAME_button($variables) {
  $element = $variables['element'];
  $element ['#attributes']['type'] = 'submit';
  element_set_attributes($element, array('id', 'name', 'value'));

  // My custom setting coming from the hook_form_alter below...
  $element_type = isset($element['#element_type']) ? $element['#element_type'] : 'submit';

  $element ['#attributes']['class'][] = 'form-' . $element ['#button_type'];
  if (!empty($element ['#attributes']['disabled'])) {
    $element ['#attributes']['class'][] = 'form-button-disabled';
  }

  // And output a button or input element...
  if ($element_type === 'button') {
    return '<button' . drupal_attributes($element['#attributes']) . '>' . $element['#value'] . '</button>';
  } else {
    return '<input' . drupal_attributes($element['#attributes']) . ' />';
  }
}

/**
 * Implements hook_form_alter().
 */
function THEMENAME_form_alter(&$form, &$form_state, $form_id) {
  switch ($form_id) {
    // Your FORM ID here...
    case 'search_block_form':
      $form['actions']['submit']['#element_type'] = 'button';
      $form['actions']['submit']['#attributes']['class'][] = 'glyphicon halflings-search';
      break;
    // Add more switch cases to affect other forms...
    case 'FORM_ID':
      break;
  }
}

```

Of course, you could add another setting in the array to handle markup inside the button. I have not because a button element will allow `:after` & `:before` pseudo elements. That was enough for me to get an icon in there and just hiding the default 'Search' text with css.

# Answer
> 2 votes
For Drupal 8:

a) If using **Bootstrap theme** you can use GLYPHICONS setting property #icon in the submit declaration:

```
$form['submit'] = array(
    '#type' => 'submit',
    '#value' => $this->t('Do something'),
    "#icon" => Bootstrap::glyphicon('chevron-left'),
);

```

b) If not using Bootstrap theme or you want icons other than Glyphicons (for example Fontawesome, like in this example), you can customize it a little more, like this:

```
$form['submit'] = array(
    '#type' => 'submit',
    '#value' => $this->t('Login to Facebook to vote'),
    "#icon" => array(
        '#type' => "html_tag",
        '#tag' => "span",
        '#value' => "",
        '#attributes' =>  array(
            'class' => array("fa","fa-facebook")
        )
    )
);

```

I expect this all applies to FORM\_ALTER too....

# Answer
> 2 votes
This is almost the same solution as Steven's, but it replaces the `<input>` submit with `<button>` rather than adding such that both exist in the HTML. This comes with the same proviso that IE6/7 doesn't support `<button>`, and even more so because it removes the possibility that having both as in Steven's solution would at least allow IE6/7 users to press Enter even though the shown button wouldn't work.

This approach below has the benefit that it keeps the HTML markup in template files.

In **yourtheme.theme**:

```
/**
 * Implements hook_theme_suggestions_HOOK_alter for form input elements.
 */
function yourtheme_theme_suggestions_input_alter(array &$suggestions, array $variables) {
  $suggestions[] = $variables['theme_hook_original'] . '__' . str_replace('-', '_', $variables['element']['#id']);
}

```

In the corresponding template suggestion now available, such as **templates/input--submit--edit-submit.html**, override the core input.html.twig with:

```
{#
/**
 * @file
 * Overridden theme implementation for an 'input' #type form element.
 *
 * Available variables:
 * - attributes: A list of HTML attributes for the input element.
 * - children: Optional additional rendered elements.
 *
 * @see template_preprocess_input()
 *
 * @ingroup themeable
 */
#}
<button{{ attributes }}>
  <i class="icon-search"></i>
  <span class="visually-hidden">Search</span>
</button>
{{ children }}

```

A template file like this of course very easy to change or add additional classes or markup.

# Answer
> 0 votes
Since the image is added via css class, you shouldn't be using \[#type\] =\> 'image\_button'. Try this instead:

```
function genchstyle_form_alter(&$form, &$form_state, $form_id) {
if ($form_id == 'search_block_form') {
$form['actions']['submit']['#type'] = 'button';
$form['actions']['submit']['#attributes']['class'][] = 'icon-search';
}

```

# Answer
> 0 votes
This is how I got this working.

In THEMENAME.theme file I have this, to remove the 'Search' button text:

```
function THEMENAME_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == 'views_exposed_form' && $form['#id'] == 'views-exposed-form-search-content-page-1') {
    $form['actions']['submit']['#value'] = '';
    }
  }

```

The I used CSS Pseudo-elements to add the Search icon on the button like so:

```
#views-exposed-form-search-content-page-1 button:before {
    font-family: "FontAwesome";
    font-weight: 400;
    content: "\f002";
 }

```

---
Tags: forms
---


title: Custom source to field in Feeds module?

text:
# Question
Title: Custom source to field in Feeds module?
I'm setting up a way for a Drupal site to import data from third party sites using a PHP script that creates a XML structure.

I'm using the Feeds module, which otherwise works fine. But I miss something.

Now, I need to add a custom source from the feed that adds data to a field.

Like that I have a inside the XML that I want to be used for the nodes image\_field. I need more then just a image, but as an example.

How do I do that?

Is there perhaps a way that will work so that I wont have to code it by myself?

PS. Since I've coded the script that creates the XML, I could easily change XML to about anything else that might work better. DS.

# Answer
> 5 votes
Feeds Xpath Parser module can help you map custom fields to your xml values. I've used this myself. There is also Querypath Parser which may do the same thing (I've never tried this one).

# Answer
> 0 votes
Both *Feeds Xpath Parser* and *Querypath Parser* modules are near end-of-life on Drupal 7. Going forward, use the XML (XPath) parser or the QueryPath XML parser from Feeds extensible parser module for Drupal 8 and 9.

---
Tags: feeds, importing-exporting
---


# Question
Title: Patching docroot htaccess: file not found
I tried to create my first patch file in order to reverse the overwriting of the scaffold file .htaccess after executing composer install. I get the following errors:

```
can't find file to patch at input line 5
Perhaps you used the wrong -p or --strip option?
The text leading up to this was:
--------------------------
|diff --git a/web/.htaccess b/web/.htaccess
|index 6f9123d..4ae5471 100644
|--- a/web/.htaccess
|+++ b/web/.htaccess
--------------------------

Script cd web && patch -p1 < ../patches/htaccess.patch handling the post-drupal-scaffold-cmd event returned with error code 1

```

This is how the patch file looks like:

```
diff --git a/web/.htaccess b/web/.htaccess
index 6f9123d..4ae5471 100644
--- a/web/.htaccess
+++ b/web/.htaccess
@@ -113,7 +113,7 @@ AddEncoding gzip svgz
   #
   # If your site is running in a VirtualDocumentRoot at http://example.com/,
   # uncomment the following line:
-  # RewriteBase /
+  RewriteBase /

   # Redirect common PHP files to their new locations.
   RewriteCond %{REQUEST_URI} ^(.*)?/(install.php) [OR]

```

And this is how it is loaded in composer.json:

```
"post-drupal-scaffold-cmd": [
     "cd web && patch -p1 < ../patches/htaccess.patch"
]

```

# Answer
> 3 votes
Look your patch already has the path to `web/` in it:

```
--- a/web/.htaccess
+++ b/web/.htaccess

```

Just remove the `cd web &&`  and adjust the path to the patch accordingly.

```
"post-drupal-scaffold-cmd": [
     "patch -p1 < patches/htaccess.patch"
]

```

---
Tags: 8, composer, .htaccess
---


title: How to block third party cookies?

text:
# Question
Title: How to block third party cookies?
I have EU Cookie Compliance installed on my website.

In the settings I have selected `Opt-in` option.

On the site front end, I only agreed to the `functional cookies` but there are cookies set by third party websites which are still saved.

I checked the module's issue queue and found this.

https://www.drupal.org/project/eu\_cookie\_compliance/issues/3109974#comment-13459494 https://www.drupal.org/project/eu\_cookie\_compliance/issues/3059471

It seems that this module will not block the third party cookies.

Is there any other way to do this?

# Answer
> 2 votes
There's no way for the module out-of-the-box to block cookies created by 3rd party components. That's a simple fact of life. For example, if you by some means inject the code to embed a YouTube video on your site, it'll serve YouTube cookies to visitors to that page and EU Cookie Compliance won't be able to block them. When a YouTube video is served there is a direct communication between YouTube and the browser which other components cannot interfere with.

(In the case of YouTube you *can* use their cookie-free domain but let's ignore that for the sake of this illustration.)

In order to allow EU Cookie Compliance to prevent YouTube videos appearing to users who haven't accepted cookies, you'll need to implement some Javascript that calls the function `Drupal.eu_cookie_compliance.hasAgreed()` provided by the module for this purpose and blocks YouTube by some means when they have not. Typically you'll have to alter the embedding code to include your own JavaScript checks and display a suitable placeholder message when a video is blocked.

An example of how to do this for Google Analytics can be found at https://www.drupal.org/node/1648286#comment-6145800

For YouTube, the EU has their own component that does a similar job, that can be seen at https://ec.europa.eu/trustfund-syria-region/content/home\_en

You'll need to perform a full audit of all cookies if you want to properly comply with the regulations. That's a larger topic than I can cover here but there are plenty of online guides and tools to get you started.

---
Tags: 7, cookies
---