# Question
Title: How do I get the current node from a Block module?
I'm looking to create a block that renders differently, depending on the content (metadata, really) of the node in which it is embedded.

The “Title” block is a good example of what I'm trying to do, I think. When you put “Page title” in a section (from the Structure menu), it displays the title of the node being displayed.

I'd like to do something similar. The end goal is to read the workflow state data from the node in order to provide large visual clues to readers that the document they are reading is approved/unapproved/et cetera.

There are some other similar ends to which I may put this technique as well, provided I figure it out.

Here's what I have:

```
/**
 * Provides a 'Workflow Block'.
 *
 * @Block(
 *   id = "workflow_tag_block",
 *   admin_label = @Translation("Workflow Block"),
 * )
 */
class WorkflowTagBlock extends BlockBase implements ContainerFactoryPluginInterface {
        protected $node;

        public function __construct(array $configuration, $plugin_id, $plugin_definition, $node) {
                parent::__construct($configuration, $plugin_id, $plugin_definition);

                $this->node = $node;
        }

        public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
                return new static(
                        $configuration,
                        $plugin_id,
                        $plugin_definition,
                        $container->get /*... something here, I think. I need this to be the node I'm rendering. */
                );
        }

        /**
         * {@inheritdoc}
         */
        public function build() {
                // do things with $this->node;

                return [
                        '#markup' => $this->t('Here Be Dragons! '),
                ];
        }
}

```

Obviously, there's an important line I don't have complete in there. The most obvious attempt would be: `$container->get('request_stack')->getCurrentRequest()->get('node')`. But that returns the WorkflowTagBlock object itself, not the primary content node.

I'm aware that multiple nodes might be rendered on the screen at once (for example, in a list), so I can't just try to snag the node id from the uri or anything like that.

This is done in other places, so surely there's a way to do it. How?

# Answer
Update your plugin definition to require the node context:

```
 *   context_definitions = {
 *     "node" = @ContextDefinition("entity:node", label = @Translation("Node"))
 *   }

```

Then in your `build()` method, you can access it like this:

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

```

If the block is displayed on a node page, then the node will be stored in the `$node` variable.

When dealing with an existing block, make sure to either replace the block with a new one once the code is updated; or add the following to the `settings:` of the block.

If not done, your block will return empty due to missing config.

```
context_mapping:
  node: '@node.node_route_context:node'

```
> 6 votes

# Answer
The Book module implements a block that needs to access to the currently viewed node, and it uses the following code, in `BookNavigationBlock::build()`.

```
if ($node = $this->requestStack->getCurrentRequest()->get('node')) {
  $current_bid = empty($node->book['bid']) ? 0 : $node->book['bid'];
}

```

`$this->requestStack` is initialized from the following code.

```
  public function __construct(array $configuration, $plugin_id, $plugin_definition, RequestStack $request_stack, BookManagerInterface $book_manager, EntityStorageInterface $node_storage) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);

    $this->requestStack = $request_stack;
    $this->bookManager = $book_manager;
    $this->nodeStorage = $node_storage;
  }

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
    $configuration,
    $plugin_id,
    $plugin_definition,
    $container->get('request_stack'),
    $container->get('book.manager'),
    $container->get('entity.manager')->getStorage('node')
    );
  }

```

The code is essentially like the one you are using, but it seems that in your case, a module is messing up with what `$container->get('request_stack')->getCurrentRequest()->get('node')` is returning.

As workaround, if you find in which cases it happens, you could override `BlockBase::blockAccess()` to avoid your `build()` method is called in those cases.
> 5 votes

# Answer
You can also try:

```
$node = \Drupal::routeMatch()->getParameter('node');

```
> 1 votes

# Answer
I'm not sure that creating a block directly is the most Drupalistic way to achieve this?

I would think in terms of creating a field or pseudo-field. Once you've done that, there's a number of routes (Views with contextual filter and block display, "Field as block" module, and ctools D8) to displaying the field as a block (if you even need to).
> 1 votes

---
Tags: 8, plugins
---


# Question
Title: How to have calendar popup in a form field of 'date' type?
Using Drupal Console, I created a custom content entity in which there is a 'date' field:

```
$fields['subscription_date'] = BaseFieldDefinition::create('datetime')
  ->setLabel(t('Date souscription'))
  ->setSetting('datetime_type', 'date')
  ->setDefaultValue(array(0 => array(
    'default_date_type' => 'now',
    'default_date' => 'now',
  )))

```

The edit-form works as supposed and, particularly, editing 'subscription\_date' brings up the calendar popup:
In my custom module, I defined a table form to 'mass' edit this entity:
I defined the date field in the form this way:

```
$form['souscriptions'][$key]['date'] = array(
    '#type' => 'date',
    '#default_value' => $default_value,
);

```

In Firefox, it looks like:
and editing a date field doesn't show the date popup :-(
While in Chrome, it's OK:
Any idea why?
What should I add to my form to have at least the simple calendar popup I have in my content entity edit-form?

Forgot to say: i'm using Drupal 8.4.2

# Answer
This issue is coming because of jQuery confliction. Either you can update jQuery version or find out the confliction of jquery object.
> 1 votes

# Answer
The reason is because at the time you asked this question, Firefox did not implement HTML5 date popup picker yet. As of right now Firefox already has it, but Safari for example still does not. To make the calendar popup work on browsers like Safari you would need some sort of a JavaScript solution such as jQuery UI date picker
> 0 votes

---
Tags: 8, forms
---


# Question
Title: Do we have another solution for the "After cloning a node" event for the Node clone module?
I would like to use the event in Rules "After cloning a node" but unfortunality this does not work. (see Event "After cloning a node" by node clone module is not working).

I tried to patch the module but did not succeed.

I would like to solve this with rules with :

Event - "Node Edit on type foo" and then add some conditions.

Does anybody knows a good condition for this? What can I compare?

Are there other solution possible?

I need it for the folowing situation: the user has two options for a node: (1) Edit (2) Clone

(1) The edit option is just going to the edit form. Normal editing should be done.

(2) The clone option makes a copy of the Content Type and then starts editing in this node. Before the user is starting this editing two fields in the content type should be empty.

```
--- Patch log (#8)
$ patch -p1 <2212039-8.patch
patching file clone.pages.inc
Hunk #1 FAILED at 160 (different line endings).
1 out of 1 hunk FAILED -- saving rejects to file clone.pages.inc.rej

--- Patch log (#8) With option --ignore-whitespace
$ patch -p1 --ignore-whitespace <2212039-8.patch
patching file clone.pages.inc
Hunk #1 FAILED at 160 (different line endings).
1 out of 1 hunk FAILED -- saving rejects to file clone.pages.inc.rej

```

# Answer
> 1 votes
Try to think of a way to better describe what you're trying to do, and for which using that specific event does not work (because of that bug).

Obviously, it doesn't matter what the subsequent Rules Condition and/or Rules Action would be (after you have "an" alternative for that Rules Event you are asking about).

But sometimes the solution for a problem, is to avoid the problem from happening, right? E.g. maybe there is some specific path you could try to intercept (also using the Rules module), right before/after that event occurred. I seem to remember node clone also has such path. And if anything else fails, use Rules Event "Drupal is initializing", followed by a Rules Condition to check such path (if needed using RegEx also ... I bet you know about that Rules trick also).

# Answer
> 0 votes
You should really try first to apply the patch or patches.

1. Save the patch file(s) into the node\_clone folder
2. cd into that folder
3. apply patch #8
> patch -p1 \< 2212039-8.patch
4. check if the problem persists and apply patch #9 if it does
> patch -p1 \< node\_clone-7.x-1.x-add\_preparing\_clone\_rule-2212039-9.patch
5. check if the problem still persists
6. :-(

You need to try both patches I guess and see if the error is fixed.

Cheers!

Issue reference on D.O.: https://www.drupal.org/node/2212039

# Answer
> 0 votes
I made a custom rules action module that clones any node, based on this code it returns new cloned node NID, then in rules do other stuff with new NID, code of my rules action:

```
  <?php
  /**
  * Implement hook_rules_action_info()
  * Declare any meta data about actions for Rules
  */

  function clone_poliza_rules_action_info() {

  $actions = array(
    'clone_poliza_action' => array(
        'label' => t('Clone a node'),
        'group' => t('cadena'),

        'parameter' => array(

          'poliza_nid' => array(
                  'type' => 'integer',
                  'label' => t('node NID to be cloned'),
                  ),

              ),

        'provides' => array(
            'new_poliza_nid' => array(
                    'type' => 'integer',
                    'label' => t('new cloned node NID'),
                    // 'wrap' => TRUE,
                    //'format' => 'full_html'
                    ),
                  ),
      ),
    );
      return $actions;

  } // fin de actions_info

  function clone_poliza_action($poliza_nid) {

  $node = node_load($poliza_nid);

  $new = clone $node;
  $new->is_new = true;
  unset($new->nid);
  unset($new->vid);
  unset($new->tnid);
  node_save($new);

  $new_poliza_nid = $new->nid;

  return array('new_poliza_nid' => $new_poliza_nid);

  }

```

---
Tags: 7, nodes, rules
---


# Question
Title: How to access form elements in table via getValue()?
I'm trying to do so using array indices. Say, we have

```
$form['mytable'] = array(
'#type' => 'table',
'#header' => array(t('a'), t('b')));

$form['mytable'][1]['a'] = array(
'#type' => 'textfield',
'#required' => true));

$form['mytable'][1]['b'] = array(
'#type' => 'textfield',
'#required' => true));

```

What am I doing: `$form_state->getValue('mytable[1][b]');`, and it's not working. And how to pass such a field to `setErrorByName`?

# Answer
> 1 votes
Since you aren't setting `#tree` to `TRUE`, you just need to use the following code.

```
$a = $form_state->getValue('a');
$b = $form_state->getValue('b');

```

The same is true for `setErrorByName()`: You use `'a'` and `'b'` as names of the fields.

For example, `CommentAdminOverview::buildForm()` contains the following code.

```
  // Build an 'Update options' form.
  $form['options'] = array(
    '#type' => 'details',
    '#title' => $this->t('Update options'),
    '#open' => TRUE,
    '#attributes' => array('class' => array('container-inline')),
  );

  // Omissis.

  $form['options']['operation'] = array(
    '#type' => 'select',
    '#title' => $this->t('Action'),
    '#title_display' => 'invisible',
    '#options' => $options,
    '#default_value' => 'publish',
  );
  $form['options']['submit'] = array(
    '#type' => 'submit',
    '#value' => $this->t('Update'),
  );

```

The submission handler (`CommentAdminOverview::submitForm()`), accesses the value submitted for `$form['options']['operation']` using the following code.

```
$operation = $form_state->getValue('operation');

```

# Answer
> 1 votes
You can access `$form_state` values like below

`$values = $form_state->getValues();`

If you are printing `$values` then you will get

```
Array
(
    [mytable] => Array
        (
            [1] => Array
                (
                    [a] => Value of a
                    [b] => Value of b
                )

        )
)

```

`setErrorByName()` function can be used while validating the elements.

# Answer
> 0 votes
The form table is going to give you a structured array (like Arun stated).

I find it easier to just get the full array for the table from $form\_state and then get the specific data from that array.

```
$mytable = $form_state->getValue('mytable');
$a = $mytable[1]['a'];
$b = $mytable[1]['b'];

```

But really, you'll probably end up looping through all the values in the table:

```
foreach($form_state->getValue('mytable') as $i => $row){
   $row_number = $i;
   $a = $row['a'];
   $b = $row['b'];
}

```

Finally, the form validation is a little confusing. In the setErrorByName method, Drupal basically converts the string name in the validation to the array structure of the multidimensional form array by exploding the string on '\]\['. So to validate a specific value in your table, you could do this:

```
$mytable = $form_state->getValue('mytable');
if ($mytable[1]['a'] == 'invalid'){
  $form_state->setErrorByName('mytable][1][a', 'there was an error');
}

```

Or again, you will probably want to check each row of your table doing something like this:

```
$mytable = $form_state->getValue('mytable');
foreach($form_state->getValue('mytable') as $i => $row){
  if ($row['a'] == 'invalid'){
    $form_state->setErrorByName('mytable]['.$i.'][a', 'there was an error');
  }
}

```

One last thing. In Drupal 7, you need to set #tree to true for table forms or else it does not build a multidimensional array. But with the table form element in Drupal 8, this is not necessary. https://www.drupal.org/node/1876710

---
Tags: 8, forms
---


# Question
Title: How can submitted values be translatable?
Like for the node, we can add the translations and the same node ID can hold all language translations. In a similar fashion, is it possible in Drupal 8 webform?

# Answer
Webforms are configuration entities and they need to be translated using a different UI/UX. @see https://www.youtube.com/watch?v=dfG37uW5Qu8
> 3 votes

---
Tags: 8, webforms
---


title: How do I migrate dates?

text:
# Question
Title: How do I migrate dates?
In my Drupal 7 site, the date is stored in the database as *2020-08-10 00:00:00*.

When I migrate those dates without any formatting (`field_blog_post_date: field_blog_post_date`), the date is migrated into the Drupal 8 table with the same exact formatting. However, it doesn't show when a node is viewed.

I tried to use a `format_date` plugin.

```
field_blog_post_date:
  plugin: format_date
  source: field_blog_post_date
  from_format: 'Y-m-d H:i:s'
  to_format: 'Y-m-d'

```

When I use it, it causes the following error.

> DateTime::createFromFormat() expects parameter 2 to be string, array given
> DateTimePlus.php:251

# Answer
this worked! found the answer here https://www.drupal.org/project/drupal/issues/2923723#comment-12343660

```
 field_blog_post_date:
        plugin: iterator
        source: field_blog_post_date
        process:
          value:
            plugin: substr
            source: value
            start: 0
            length: 10

```
> 2 votes

# Answer
Also from https://www.drupal.org/project/drupal/issues/2923723#comment-13141671

```
field_blog_post_date:
    plugin: sub_process
    source: field_blog_post_date
    process:
      value:
        plugin: format_date
        from_format: 'Y-m-d H:i:s'
        to_format: 'Y-m-d'
        source: value

```

Should work
> 3 votes

---
Tags: migrations, datetime
---


title: Can user UUID be null?

text:
# Question
Title: Can user UUID be null?
I have a Drupal 7 site with a bunch of users. I want to migrate the users to Drupal 8 but not any of the content so I'm writing a crosswalk. Drupal 8 has uuid in the users table. Is there a way I can compute this or can I just set it to NULL? Thanks!

# Answer
No, cannot be empty.

You can generate one with

```
$uuid_service = \Drupal::service('uuid');
$uuid = $uuid_service->generate();

```

If you use User::create it will automatically generate one for you.

```
Drupal\user\Entity\User::create([
  'uid' => $uid,
  'name' => '$user_name,
  'mail' => $email,
  'roles' => [],
  'pass' => [
    'value' => $hashed_drupal_7_password,
    'pre_hashed' => TRUE,
  ],
  'status' => 1,
])->save();

```

---

Rather than code it from scratch. The proper, Drupal way, to migrate is using all of these:

I suggest your read this article A Quick Guide to Migrating Drupal Content from D7 to D8 which goes over how to migrate users and other scenarios.
> 3 votes

---
Tags: users
---


# Question
Title: How can I use the grouped nid in a views template with two content types?
In Drupal 8.9x, I have a view with two content types in it: Each business (and its details are grouped), and underneath each business I'm displaying multiple offers by that business...and then I want to display more business details underneath that.

For example:

```
Business #1 "title"
 -- offer A for business #1 (row)
 -- offer B for business #1 (row)
Business #1 Details (ideally inserted via the twig template)

Business #2 "title"
-- offer C for business #2 (row)
-- offer D for business #2 (row)
Business #2 Details (ideally inserted via the twig template)

```

I've got my view set up so that ALMOST all of the business details are grouped into a custom field. This outputs as "title" in the `views-view-unformatted.html.twig` template file, and all the offers are the "rows" that are placed inside the default twig for loop. The problem is, I need to place more business details after the for loop, and I don't know how to reliably insert that data via the template.

For example, if I try to access the Business's nid:

```
{% set bizNid = rows[0].content['#row'].node_field_data_node__field_business_location_nid %}

```

This grabs the very first row in the array, which doesn't necessarily correspond with the first business in the list. I spend a few hours looking through the twig var dump to see if I could find a reliable way of extracting the nid, but I just can't figure it out. My question is, how can I access the grouped/relationship data/fields/content inside a twig template file so I can sandwich the businesses offers between two sets of business data from the same business?

Here's a gist of my views-view-unformatted.html.twig file for more insight on what I'm trying to do.

And here's a screenshot of ultimately what the output should look like:

And here's a screenshot off my Views config page for "offers":

Thanks in advance for your help.

# Answer
Here's one way to solve this. This is the easiest way to solve it through the interface, without the need for templating or coding.

It may not be the best option performance-wise because of combining data from two db tables through Views, but then again you'd probably need to build a very custom query to optimize, and caching might solve possible lags.

It can all be done through the Offers Views, without Relationships and Contextuals, but with the help of View Modes.

View Modes don't have anything to do with Views module, so this is something to keep in mind, I wish they were named Display Modes or something along those lines. You've probably already used two of them before: Full and Teaser.

View Modes are different ways you can display your entity Fields. Each mode controls which fields are shown, in which order, and with which display settings.

You need to create two additional View Modes for your Business CT (you can do that on the "Manage display" page of your CT or through Structure \> Display modes \> View modes, it will appear among the tabs). One mode will be for the top Business info (so you should include the fields you want to show there), and the other for what is shown bellow the Offers.

In your Offers Views add the Offers Fields how you want them displayed.

Then add two Business Entity Reference fields as well.

Rearrange the fields so you have one Business reference on top of the fields list, and the other on the bottom.

Configure the top one's Formatter to `Rendered entity` and choose the View mode you created earlier for it. Exclude it from display and save, then choose it as the 1st grouping field under Format Settings.

Configure the bottom Business reference to also format as `Rendered entity` but choose the second View mode you created for it.

You should now have it all groupped by Businesses and displaying correct info in correct places. Be mindful of the pagination you set because it can "break" one Business to display on two pages depending on the number of offers.
> 1 votes

---
Tags: views, theming, 9
---


# Question
Title: How do you make a Image View of a specific page?
I have a problem.

The thing is that I know that you can have a \[Content Type\] with an image \[Field\], and then you can create a \[View\] to display the image \[Field\] in each of the pages that are of the selected \[Content Type\].

However, (if I have a \[Content Type\] that is an image gallery), how can I create a view that only displays the gallery of one specific page? I mean, just one entry of a \[Content Type\]. For example, a services\_list page of basic\_page \[Content Type\].

The end goal I want to reach is a Slideshow of a gallery, and clicking that slideshow must send me to a specific page. So if it was possible to assign a specific link to a slideshow, instead of using the option \[Link to: Content\] that would work too.

# Answer
In the block's options there's a paginator setion that lets you include a "more" link, so it isn't exactly what I wanted, but I just put the page's link there, and it does work so I think I'll just leave it there.
> 0 votes

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


# Question
Title: ExtensionDiscovery::scanDirectory() takes too long
I have been debugging a bit an issue on our platform and I notice that our scanDirectory takes, from time to time, way to long, more than 100seconds. I have been looking at the default.settings.php and I noticed

```
/**
 * The default list of directories that will be ignored by Drupal's file API.
 *
 * By default ignore node_modules and bower_components folders to avoid issues
 * with common frontend tools and recursive scanning of directories looking for
 * extensions.
 *
 * @see file_scan_directory()
 * @see \Drupal\Core\Extension\ExtensionDiscovery::scanDirectory()
 */
$settings['file_scan_ignore_directories'] = [
  'node_modules',
  'bower_components',
  'vendor',
];

```

I found that out that our sites/default directory is the one to blame. Can I just add it here? Or should I include the subdirectories(fx sites/default/files)?

I am really surprised about this one. Been working with drupal years now and I see this first time!

# Answer
If you need the `file_scan_ignore_directories` setting changed, you should add the `$settings['file_scan_ignore_directories']` assignment in your `settings.php`, not `default.settings.php` lest it's overwritten when you update Drupal core.

Regarding what path strings to add to `$settings['file_scan_ignore_directories']`, that's up to you. As the comment block states, that setting affects all calls to `ExtensionDiscovery::scanDirectory()` and `FileSystem::scanDirectory()` (if a `nomask` option isn't specified).

Add the most inclusive path that you know will never contain extensions or files to be scanned/discovered.
> 1 votes

---
Tags: files, performance
---


# Question
Title: Changing the billing address on order informations page only closes payment information box?
On order information page during checkout process in “Payment information” block I see checkbox “My billing information is the same as my shipping information.” and it’s checked when page is opened first time. If I uncheck it I get drop-down for selecting some other address from address book or creating new one. But what ever option I choose from that drop-down block just closes again and checkbox becomes checked again?!?

Is that normal behavior or it's is a bug? Should the block stay open if different address is selected?

# Answer
> 1 votes
Bug is fixed in latest module version (Commerce Shipping 8.x-2.0-rc2).

---
Tags: commerce
---


title: How to enable a field programmatically

text:
# Question
Title: How to enable a field programmatically
I've created a field programmatically :

```
$field_storage = FieldStorageConfig::create(
  array('entity_type' => 'node', 'field_name' => 'field_desc', 'type' => 'string'));
$field_storage->save();
$field = FieldConfig::create(
  array('entity_type' => 'node', 'field_name' => 'field_desc', 'bundle' => 'mybundle', 'settings' => array('handler' => 'default', 'handler_settings' => array())));
$field->save();

```

But the field is disabled by default when I access to "manage form display".

My question is : how can I enable the field programatically?

thanks :)

# Answer
You enable the field by adding a widget to the default form display mode:

```
$display_repository = \Drupal::service('entity_display.repository');

// Assign widget settings for the default form mode.
$display_repository->getFormDisplay('node', 'mybundle')
  ->setComponent('field_desc', [
    'type' => 'string_textfield',
  ])
  ->save();

```

See Add content type field programmatically
> 4 votes

---
Tags: entities
---


# Question
Title: How to use dd(debug_backtrace()); for an error debugging?
I have this exact error on my site.

I am trying to troubleshoot the error using `dd(debug_backtrace());` through the Devel module as is described on the link above.

Being the noob on developing I can't figure out how to print the output in a `drupal_debug.txt` file under the `tmp` folder in the root of my Drupal Installation (As is described in the in the link above).

I have tried dd(debug\_backtrace()); but I don't see any error file being created so I also tried dd(debug\_backtrace('drupal\_debug.txt')); but I get the error:

> Warning: file\_put\_contents(): Only 0 of 1 bytes written, possibly out of free disk space in drupal\_debug() (line 1793 of /home/bigcypru/public\_html/sites/all/modules/devel/devel.module).
>
> Devel was unable to write to `/tmp/drupal_debug.txt`.

I created the file manually and set 777 permissions to be sure is writable but still get the same error and I am sure I have enough space in my hosting plan.

# Answer
> 1 votes
You can run:

```
dd(debug_backtrace());

```

which prints the output to `drupal_debug.txt` file by default in your temporary folder which can be found in your `tmp` folder (See: Where Drupal creates temporary files?). You can specify different file, but in Drupal settings related to file system.

The call to ~~`dd(debug_backtrace('drupal_debug.txt'));`~~ is invalid, since debug\_backtrace() accepts int $options, not the file.

Regarding this warning:

> Only 0 of 1 bytes written, **possibly out of free disk space** in drupal\_debug(). Devel was unable to write to `/tmp/drupal_debug.txt`.

it says you're likely to be out of free disk space on your hard drive. So you should remove this file from your temporary folder at `/tmp`, then try again.

To make it more light, use the following version:

```
dd(debug_backtrace(FALSE, 5));

```

which won't populate all objects (FALSE) and limit number of stack frames returned to 5.

If your function is called too many times, try adding `die()` or `exit();` to avoid multiple calls.

You can also use the following one-liner:

```
array_walk(debug_backtrace(),create_function('$a,$b','print "<pre>{$a[\'function\']}()(".basename($a[\'file\']).":{$a[\'line\']});</pre>\\n";'));

```

which will print even more minimalized version of the backtrace to avoid out-of-space issues.

# Answer
> 1 votes
I also can recommend the Past Log module.

It offers you enhanced logging capabilites (including backtrace) out of the box!

---
Tags: 7, debugging
---


# Question
Title: How to limit country list for address form drop-down?
In my store I defined list of supported billing and shipping countries at store settings. This list is respected during checkout process - limited list of countries is shown when customer is entering the address. But when user is on "Address book" tab of user profile page and wants to add new address list is not limited, but all countries are allowed there.

How can I limit list of displayed countries when editing address at address book user profile tab?

I tried using `hook_form_alter()` but I don't see country drop-down there? Also tried `hook_preprocess_input()` and I see other fields, but not country drop-down.

`theme_preprocess_field()` didn't help either.

And of course, I didn't find that option in back-end.

# Answer
> 4 votes
Found solution here: https://docs.drupalcommerce.org/commerce2/developer-guide/customers/addresses/countries-and-subdivisions

Created new module "country\_limit" added event subsriber like explained there:

```
<?php

namespace Drupal\country_limit;

use Drupal\address\Event\AddressEvents;
use Drupal\address\Event\AvailableCountriesEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class LimitCountriesEventSubscriber implements EventSubscriberInterface {

  public static function getSubscribedEvents() {
    $events[AddressEvents::AVAILABLE_COUNTRIES][] = ['onAvailableCountries'];
    return $events;
  }

  public function onAvailableCountries(AvailableCountriesEvent $event) {
    $countries = ['AT' => 'AT', 'DE' => 'DE', 'CH' => 'CH'];
    $event->setAvailableCountries($countries);
  }

}

```

and registered it like:

```
services:
  # Name of this service.
  my_config_events_subscriber:
    # Event subscriber class that will listen for the events.
    class: '\Drupal\country_limit\LimitCountriesEventSubscriber'
    # Tagged as an event_subscriber to register this subscriber with the event_dispatch service.
    tags:
      - { name: 'event_subscriber' }

```

Event subsriber class is directly inside "src" dir, since I don't have other functionalities in this module.

---
Tags: 8, users
---


# Question
Title: How do I export and import content types (including fields) between environments?
I've been trying to find a smart way of exporting content type and all its fields from one installation of Drupal to another. The core "Configuration synchronization" export only export the content type, but not its fields and configuration.

So far I have not met anything applicable for Drupal 8. All I can find is mentions of this functionality is possible in Drupal 7 module called Bundle Copy, which was never ported properly for 8.

I've also tried this, however I cannot find any good documenation on how the "drupal config:import" or "drupal config:import:single" works.

Is it really so hard to export and import content types between environments or have I missed something essential?

# Answer
## Configuration management

Deploying content types, fields, views, site settings (everything that is not content) from one environment (local) to another (stage, prod etc.) in Drupal 8+ works by exporting the currently active configuration (stored in the database) into YAML files. The most common approach is to simply **export** all your site's configuration at once. Drupal takes care of that. You just specify the folder where you want these YAML files to be located in your project (at best outside the Drupal root). Then you uploaded all these YAML files or `git push` and `git pull` them to another environment and **import** the whole config there into the database. The export and import can be done by either using the UI or by using Drush.

Now when you add new features to your site locally (a new content type with fields for example) you simply **export** the whole config again. With some version control system like Git you'll then see that most of the already existing YAML files didn't change and only some new YAML files have been added. Simply upload/push the changes or the new files into another environment where you **import** the config again. The new content type with the fields now should have been created.

## Configuration split/ignore

Of course, things can get more complex than what I described above, especially when working with lots of people on feature-rich and content-heavy projects. Then it can become necessary that you want some config to be ignored from getting exported or imported. Let's say you want to prevent that some API keys get exported. Or you want to prevent that some setting on the live site gets reset when you import the config again. Or maybe you always want to have some additional modules enabled only locally during development. Then there's the Config Ignore and the Configuration Split module to cover that.

## Exporting/importing isolated config

This basically has been the way how you used to deploy configuration in Drupal 7. Now this approach can be used during local development to sync for example only one isolated content type or paragraph type and its fields across many multi-site instances. Of course you could rebuild the content type in every single instance manually yourself, but you can also use the Features module to have it create a module for you which only contains the config of this isolated content type and its fields. Then simply enable this feature module in all other multi-site instances to have the content type created there as well. And finally export the config on all instances for deployment as described under "Configuration management".

When you now change the content type on one instance, Features will recognize these changes and lets you recreate the feature module which then also contains the changes. These changes will be recognized by Features in all other instances where this module is enabled and you can re-import the changes into every instance's database; after which you finally export every instance's global config again, for deployment. Since every feature module actually is simply another Drupal module you can also use them to bring a certain isolated feature like a content type and its fields to any other unrelated Drupal 8+ site.
> 5 votes

# Answer
You're on the right track with the configuration export but I am guessing you did the single export option for the content type. Each field on your content type has several configuration items that should be exported too.

An alternative is using the Features module. This will allow you to select your content type. It will also automatically gather up all the required configuration items for exporting them.
> 6 votes

# Answer
The best way in my opinion is to use git work flow. What we do to export content type configuration with fields between the environments is we take a git feature branch and create content type and it's corresponding fields in our local environment and make a drush cex. Now in the git branch we have only the configuration related to the particular content type.

Once config is exported we create a custom module and include those config in config/install directory in the module and enable that module on all the required sites.

Here is the example of such config export

https://git.drupalcode.org/sandbox/Bhanu951-3103712/-/tree/8.x-dev/card\_content

If the exported config is dependent on other modules. We define required modules in info.yml. So that you won't be having issues while enabling that module in different site.
> 3 votes

---
Tags: 8, importing-exporting, configuration
---


# Question
Title: How to display form element and label inline
This must be simple, but I cannot find the answer.

I want the label and the textfield on the same line. I tried this:

```
'odt-filter' => array(
  '#type' => 'textfield',
  '#title' => 'Filtra',
  '#attributes' => array(
    'id' => array(
      'odt-filter',
      ),
    'class' => array(
      'container-inline',
    ),
  ),
) ,

```

but then the class is applied to the `input` element, not to the item that contains both it and the label:

```
<div class="js-form-item form-item js-form-type-textfield form-type-textfield js-form-item-odt-filter form-item-odt-filter">
  <label for="edit-odt-filter">Filtra</label>
  <input id="odt-filter" class="container-inline form-text" data-drupal-selector="edit-odt-filter" name="odt-filter" value="" size="60" maxlength="128" type="text">
</div>

```

so that the class has not the desired effect. I can (and I actually did, somewhere else) enclose the form element in a container which I can apply the class to, but since a container is already provided by default, I guess there should be a way to add a class to it... isn't there?

# Answer
> 2 votes
The label placement is something set by the theme you're using, and should be consistent across your site. If all labels are above the corresponding element, you should think twice about changing that position just for one or only a few form elements. If you want all the labels next to the element instead of above, the proper place to change that is in the theme.

But let me answer the question as posed:

There is no need to complicate the document structure by adding container elements for the sole purpose of adding a class. The Form API already wraps input elements with a div, and adds standard classes to these divs, so the trick here is to target the existing div and put your class on that existing div.

You can add your class to the div surrounding the form element by using the totally undocumented property `#wrapper_attributes`. It is used like this:

```
'odt-filter' => [
  '#type' => 'textfield',
  '#title' => 'Filtra',
  '#wrapper_attributes' => [
    'id' => 'odt-filter',
    'class' => ['container-inline'],
  ],
] ,

```

Note this is Drupal 8 so I have changed your example to use short array syntax and I have changed your 'id' attribute to be a string, not an array. You may use both the `#attributes` and the `#wrapper_attributes` properties at the same time, in case you wanted to add the class to the div and the id to the input, for example.

# Answer
> 1 votes
Wrap your element in a container like here:

```
$form['frame'] = ['#type' => 'container', '#attributes' => ['class' => ['container-inline']]];
$form['frame']['e_mail'] = [
      '#type' => 'email',
      '#title' => $this->t('EMail'),
    ];

```

For your code it should work like

```
$form['odt-filter'] = [
      '#type' => "container",
      '#attributes' => ['class' => ['container-inline']],
      'odt-filter' => [
        '#type' => 'textfield',
        '#title' => 'Filtra',
        '#attributes' => [
          'id' => [
            'odt-filter',
          ],
        ],
      ],
    ];

```

---
Tags: 8, forms
---


title: Expiration date on product variation

text:
# Question
Title: Expiration date on product variation
How can I set an expiration date on a product variation?

I am building a webshop and my goal is to have an expiration date on a product variation, meaning the after a scheduled date, the product would no longer be available to sell, so it would automatically unpublish. Also, vice versa, the product variation might have a publishing date.

Currently I am looking at scheduler, but that is for nodes, not for products. Is there another way of doing this?

# Answer
### Job Scheduler

Provides an API to schedule jobs. Where you can programmatically unpublish product variation in worker callback.

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
>     'crontab' => * 3 * * 0, // Every Sunday at 3 AM
>     '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_update_users_total(\Drupal\job_scheduler\Entity\JobSchedule $job) {
>     // Do stuff.
>   }
>
> ```

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

---

### Ultimate Cron

Provides a UI where you can schedule all the cron jobs. You can implement your own hook\_cron and then schedule it using Ultimate Cron.
> 0 votes

---
Tags: 8, commerce
---


# Question
Title: What is the purpose of rerender FormState property?
I am trying to understand With a taxonomy term view Exposed form in block has incorrect action URL /taxonomy/term/all, not taking into account term id and breaking filtering without AJAX/JS and in the process I see the `rerender` property is mentioned in code a lot, such as on Render exposed filter without creating block and How to programmatically render a view exposed filter inputs with form state maintain? The original problem is that the code runs the second time and it doesn't get view arguments, but I don't see where the `rerender` property can influence this process and how it's reasonably used at all. The only place I see is in an Ajax sub-folder, but I don't have Ajax enabled on my view yet.

What problem does this property solve?

# Answer
> 1 votes
The only place in core that checks for, `$form_state->get('rerender')` in an `if` statement is in:

/core/modules/**views\_ui**/src/Form/Ajax/ **ViewsFormBase.php**

```
// If the form has not been submitted, or was not set for rerendering, stop.
if (!$form_state->isSubmitted() || $form_state->get('rerender')) {
  return $response;
}

// Sometimes we need to re-generate the form for multi-step type operations.
if (!empty($view->stack)) {
  $stack = $view->stack;
  $top = array_shift($stack);

  // Build the new form state for the next form in the stack.
  $reflection = new \ReflectionClass($view::$forms[$top[1]]);
  /** @var $form_state \Drupal\Core\Form\FormStateInterface */
  $form_state = $reflection->newInstanceArgs(array_slice($top, 3, 2))->getFormState($view, $top[2], $form_state->get('ajax'));
  $form_class = get_class($form_state->getFormObject());

  $form_state->setUserInput([]);
  $form_url = views_ui_build_form_url($form_state);
  if (!$form_state->get('ajax')) {
    return new RedirectResponse($form_url->setAbsolute()->toString());
  }
  $form_state->set('url', $form_url);
  $response = $this->ajaxFormWrapper($form_class, $form_state);
}
elseif (!$form_state->get('ajax')) {
  // if nothing on the stack, non-js forms just go back to the main view editor.
  $display_id = $form_state->get('display_id');
  return new RedirectResponse(Url::fromRoute('entity.view.edit_display_form', ['view' => $view->id(), 'display_id' => $display_id], ['absolute' => TRUE])->toString());
}
else {
  $response = new AjaxResponse();
  $response->addCommand(new CloseModalDialogCommand());
  $response->addCommand(new ShowButtonsCommand(!empty($view->changed)));
  $response->addCommand(new TriggerPreviewCommand());
  if ($page_title = $form_state->get('page_title')) {
    $response->addCommand(new ReplaceTitleCommand($page_title));
  }
}

```

The `if (!empty($view->stack)) {` part will only pass if the form is a multi-step form and you're not in the last step; otherwise, it will proceed to close the modal. Ex: when you click "Apply" or "Cancel" or "Remove". (Ex: when adding a field) it triggers the else:

```
else {
  $response = new AjaxResponse();
  $response->addCommand(new CloseModalDialogCommand());
  $response->addCommand(new ShowButtonsCommand(!empty($view->changed)));
  $response->addCommand(new TriggerPreviewCommand());
  if ($page_title = $form_state->get('page_title')) {
    $response->addCommand(new ReplaceTitleCommand($page_title));
  }
}

```

### Conclusion

As it only gets checked in the views\_ui module, this setting is basically a way to tell the **Views UI Form**:

if the setting form is a multi-step form, like when you're adding a field:

to keep the modal open and build a new `$form_state` for the next form

Otherwise, its like when you click apply/cancel/remove it tells it to close the modal, show save & cancel buttons, and show/refresh the live preview.

---
Tags: 8, views
---


title: How to make EntityListBuilder sortable?

text:
# Question
Title: How to make EntityListBuilder sortable?
When defining custom content entities one can use EntityListBuilder to build a list of those entities for administrative purpose.

By default such entities are ordered by ID, however it is possible to change ordering by overriding EntityListBuilder::getEntityIds(). Nevertheless this is only ordering of the items. But how to make that table sortable (by clicking on column header to sort ascending and descending)?

# Answer
> 13 votes
This is how i sort my entityListBuilder :

i use the method load() :

```
  public function load() {

    $entity_query = \Drupal::service('entity.query')->get('produits_entity');
    $header = $this->buildHeader();

    $entity_query->pager(50);
    $entity_query->tableSort($header);

    $uids = $entity_query->execute();

    return $this->storage->loadMultiple($uids);
  }

```

Then i build my header like this :

```
  /**
   * {@inheritdoc}
   */
  public function buildHeader() {

    $header = array(
        'id' => array(
            'data' => $this->t('N° produit'),
            'field' => 'id',
            'specifier' => 'id',
            'class' => array(RESPONSIVE_PRIORITY_LOW),
        ),
        'nom' => array(
            'data' => $this->t('Nom'),
            'field' => 'name',
            'specifier' => 'name',
        ),

        'prixHT' => array(
            'data' => $this->t('Prix HT'),
            'field' => 'prixHT',
            'specifier' => 'prixHT',
        ),

        'statut' => array(
            'data' => $this->t('Actif'),
            'field' => 'actif',
            'specifier' => 'actif',
        ),

    );

    return $header + parent::buildHeader();
  }

```

you need to add in your buildHeader() 2 param for each field you want sort :

> name of field and specifier

# Answer
> 10 votes
Entity query doesn't have tablesort integration. You'd have to implement the query logic yourself.

For content entities, I would strongly recommend to rely on the views integration instead. List builders are limited in functionality and mostly useful for config entities only.

# Answer
> 1 votes
For now, **DraggableListBuilder** is only available for config entities, not content entities. Take a look at the documentation for DraggableListBuilder 9.0 here. I spent about day trying to make that work until I noticed "config" in the route.

The best workaround I've come up with is to ignore **EntityListBuilder** and use the **ContentEntityForm** API instead. ContentEntityForm allows you to use the native TableDrag widget, which adds sortable handles to the form list. There's a well-documented example here.

These are the key lines of code to add to the usual buildform() function:

```
$form['table-row'][$id]['#attributes']['class'][] = 'draggable';
$form['table-row'][$id]['#weight'] = $row->weight->value;
$form['table-row'][$id]['weight'] = [
  '#type' => 'weight',
  '#title_display' => 'invisible',
  '#default_value' => $row->weight->value,
  '#attributes' => ['class' => ['table-sort-weight']],
];

```

If this solution is of interest, I can add a working example.

# Answer
> 0 votes
There is a sortable DraggableListBuilder available now.

```
use Drupal\Core\Config\Entity\DraggableListBuilder;

/**
 * Provides a listing of user roles.
 */
class RoleListBuilder extends DraggableListBuilder {

  public function getFormID() {
    return 'user_admin_roles_form';
  }

  public function buildHeader() {
    $header['label'] = t('Name');
    return $header + parent::buildHeader();
  }

  public function buildRow(EntityInterface $entity) {
    $row['label'] = $this->getLabel($entity);
    return $row + parent::buildRow($entity);
  }

}

```

You need to make sure your config entities have a weight and label.

---
Tags: 8, entities
---


# Question
Title: Should scripts/*.sh files be executable?
Drupal 7's recommended file permissions don't allow it's /scripts/\*.sh files to execute. Should any server user have the ability to run those?

# Answer
> 4 votes
No. You don't need to execute permissions on those scripts in a production server environment.

The only reason you'd need those scripts executable on a server is for running code testing utilities (e.g. simpletest test cases, generating dummy content, etc.) on the codebase. Unless you're wanting to run some of those testing utilities on a CI server, they don't need to be executable for Drupal to work.

---
Tags: 7, files
---


# Question
Title: Custom form calls different form in modal, submit/ajax callback of second form not called
I created 2 forms:

dms\_gift\_voucher/src/Form/GiftVoucherForm.php

```
  ...

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    ....

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
      '#attributes' => [
        'class' => [
          'use-ajax',
        ],
      ],
      '#ajax' => [
        'callback' => [$this, 'confirmGiftVoucher'],
        'event' => 'click',
      ],
    ];

    // Dialog box dependency
    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';

    return $form;
  }

  ...

  /**
   * Callback for opening the modal form.
   */
  public function confirmGiftVoucher(array $form, FormStateInterface $form_state) {
    $response = new AjaxResponse();

    // Get the modal form using the form builder.
    $modal_form = $this->formBuilder->getForm('Drupal\dms_gift_voucher\Form\GiftVoucherConfirmForm', $form_state->getValues());

    // Add an AJAX command to open a modal dialog with the form as the content.
    $dialog_options = [
      'width' => 'calc(100% - 20px)',
      'dialogClass' => 'modal--gift-voucher-confirm',
    ];
    $response->addCommand(new OpenModalDialogCommand($this->t('Test'), $modal_form, $dialog_options));

    return $response;
  }

```

dms\_gift\_voucher/src/Form/GiftVoucherConfirmForm.php

```
  ...

  /**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, $values = []) {
    ...

    $form['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Confirm'),
      '#weight' => 100,
      '#attributes' => [
        'class' => [
          'use-ajax',
        ],
      ],
      '#ajax' => [
        'callback' => [$this, 'submitModalFormAjax'],
        'event' => 'click',
      ],
    ];

    // Library
    $form['#attached']['library'][] = 'core/drupal.dialog.ajax';

    return $form;
  }

  ...

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    // Never called!
  }

  /**
   * {@inheritdoc}
   */
  public function submitModalFormAjax(array &$form, FormStateInterface $form_state) {
    $response = new AjaxResponse();
    // Never called!
    return $response;
  }

```

The first form works correct, the submit is called, the ajax callback renders the modal with the 2nd form. But when i submit the 2nd form, nothing happens, no submit, no ajax callback called from the 2nd form.

How can i fix this? Any suggestions.

(Every example of drupal modal forms start with a link trigger with routing, but i find it strange why this approach doesn't work).

EDIT: As suggested in the comments, routing info:

dms\_gift\_voucher.routing.yml

```
dms_gift_voucher.gift_voucher_form:
  path: '/dms_gift_voucher/form/gift_voucher'
  defaults:
    _form: '\Drupal\dms_gift_voucher\Form\GiftVoucherForm'
    _title: 'GiftVoucherForm'
  requirements:
    _access: 'TRUE'

dms_gift_voucher.gift_voucher_cofirm_form:
  path: '/dms_gift_voucher/form/gift_voucher_cofirm_form'
  defaults:
    _form: '\Drupal\dms_gift_voucher\Form\GiftVoucherConfirmForm'
    _title: 'GiftVoucherConfirmForm'
  requirements:
    _access: 'TRUE'

```

# Answer
Since you're programmatically setting a modal with

```
$response->addCommand(new OpenModalDialogCommand($this->t('Test'), $modal_form, $dialog_options));

```

For the form that is in the modal, Drupal needs to know what URL it should post the AJAX to and be told that its an AJAX request because this only gets set automatically when the `url` key doesn't have a value.

```
  '#ajax' => [
    'callback' => [$this, 'submitModalFormAjax'],
    'event' => 'click',
    'url' => \Drupal\Core\Url::fromRoute('dms_gift_voucher.gift_voucher_cofirm_form'),
    'options' => [
      'query' => [
        FormBuilderInterface::AJAX_FORM_REQUEST => TRUE,
      ],
    ],
  ];

```

---

**Side note:** The above isn't needed with the HTML way of opening dialog boxes, had you done:

```
<a class="use-ajax"
   data-dialog-options="{"width":600}"
   data-dialog-type="modal"
   href="/dms_gift_voucher/form/gift_voucher_cofirm_form">
   Should load Test webform in a Modal
</a>

```

because it has the URL of the form and knows its an AJAX request from the class name.
> 1 votes

---
Tags: 8, forms, ajax, modal-dialogs
---


# Question
Title: Why is the output from getDefinition($type) different from getStorage($type)->getEntityType()?
In a `Controller`, when calling: `$this->entityTypeManager()->getStorage($type)->getEntityType()`, I do not have the exact same return value as: `$this->entityTypeManager()->getDefinition($type)`.

They both return the same class (in my tests, it was `ContentEntityType`), but the only difference is in the `entity_keys` definition. Here is a diff of var export highlighting the diff between the two calls:

```
--- a/fromStorage.txt
+++ b/fromStorage.txt
@@ -19,6 +19,7 @@ Drupal\Core\Entity\ContentEntityType::__set_state(array(
     'uuid' => 'uuid',
     'langcode' => 'langcode',
     'published' => 'status',
+    'test' => 'entity_key_value',
     'revision' => '',
     'bundle' => '',
     'default_langcode' => 'default_langcode',

```

The `test` entity key was added after the module was installed (a custom entity). Only the `$this->entityTypeManager()->getDefinition($type)` call returns this entity key. The remaining of the entity definition is 100% the same.

At first, I thought that an entity update was needed, but the entity update manager detects no update to apply. Clearing the caches did not help either. Why the inconsistency? Am I missing an update call somewhere?

# Answer
> 3 votes
After digging into the internals of the entity type / storage management, I am fairly confident that I have found the answer: `$this->entityTypeManager()->getStorage($type)->getEntityType()` uses the result of `EntityManager::getActiveDefinition` which loads a sort of cached representation of the entity type. This was introduced by https://www.drupal.org/project/drupal/issues/2554235 which added the concept of last installed definition, which is meant to mitigate problems during update processes.

The difference between codebase and database means that the entity may need an update, like the following:

```
$codefieldstoragedef = $this->entityTypeManager->getDefinition($this->entityType->id());
\Drupal::entityDefinitionUpdateManager()->updateEntityType($codefieldstoragedef);

```

As `$this->entityTypeManager->getDefinition()` returns the codebase representation, this will tell Drupal to update the database representation with it. After doing this (preferably in a hook update), the entity keys will match.

---

This answer is also meant to fix some entity definition mismatch as shown in the status report page, especially regarding base fields to update which are used as entity keys.

---
Tags: 8, entities, updating
---


# Question
Title: How can I override the search result page title dynamically?
In my Drupal 8 site, I am using the default search page. If I enter a keyword, for example *article*, the search result will be listed under *Search result*.

I want to change that to *Search result for Article (keyword)*.

How can I achieve this?

# Answer
Here comes an example snippet on how to override the page title by URL query:

```
/**
 * Implements hook_preprocess_HOOK().
 */
function MYTHEME/MYMODULE_preprocess_page_title(&$variables) {

  $current_path = \Drupal::request()->getpathInfo();
  if ($current_path == '/search/node') {
    if (\Drupal::request()->query->has('keys')) {

      // Get the searched string.
      $keywords = \Drupal::request()->query->get('keys');

      // As of https://drupal.stackexchange.com/a/232304/15055 we probably
      // need to ensure the cache gets busted.
      $variables['#cache']['contexts'][] = 'url.query_args:keys';

      // Set the new title.
      $new_title = new \Drupal\Core\StringTranslation\TranslatableMarkup('Search result for Article (@keywords)', ['@keywords' => $keywords]);
      $variables['title'] = $new_title;
    }
  }
}

```
> 7 votes

# Answer
The hook mentioned above does not work in d8.Instead you can use hook\_preprocess\_page(&$variables). Also you can use hook\_preprocess\_views\_view(&$variables) and continue with the same logic . function themename\_preprocess\_page(&$variables) {

```
 $current_path = \Drupal::request()->getpathInfo();
//echo $current_path;
if ($current_path == '/search/node') {
  if (\Drupal::request()->query->has('keys')) {
    $keywords = \Drupal::request()->query->get('keys');
    echo "Search Results for " . $keywords;
    }
  }
}

```
> -1 votes

---
Tags: 8, search
---


title: Managing backward compatibility

text:
# Question
Title: Managing backward compatibility
It seems (correct me if I'm wrong) that there are some classes or services that must be used in relevant cases in Drupal 9 that are not present in Drupal 8.

For example, **New in Symfony 4.3: Simpler event dispatching** `Symfony\Component\HttpKernel\Event\RequestEvent` in place of `Symfony\Component\HttpKernel\Event\GetResponseEvent`.

Same with temporary session storage and more.

This means that if these features are used in a module, the module can only be compatible with one of these core versions; but it seems like a complete waste to manage two codebases at this point, since the versions are still very similar.

What is the correct way to manage this compatibility in one module, and has this question been addressed by the Drupal 9 release team?

# Answer
Yes, this has been addressed by the core maintainers. You are safe if your module doesn't use any APIs deprecated until Drupal 8.8/8.9:

> **Drupal 8.8 was the final release to introduce new deprecations that will be removed in Drupal 9**

A quote from the Drupal release team: https://groups.drupal.org/node/535670

You should wait to remove deprecations introduced in Drupal 9 until you prepare for Drupal 10 and don't need Drupal 8 support any longer.

So beginning with Drupal 8 you can manage compatibility for two Drupal versions at the same time.
> 2 votes

# Answer
The solution is to keep doing it the old way. For example the Commerce module keeps doing those the symfony 3 way and it works for both D8 & D9.

Alternatively, you could upgrade your D8 site to symfony 4.4. See Allow Symfony 4.4 to be installed in Drupal 8.

> ### API changes
>
> Symfony 4.4 API will be supported.

and do it, the new, symfony 4 way.
> 1 votes

---
Tags: 9
---


# Question
Title: Sitewide Ajax failure with http status 200
I'm not sure what's happened but I'm suddenly getting Ajax errors for every ajax call, site-wide. An example, from the views UI:

```
An AJAX HTTP error occurred.
HTTP Result Code: 200
Debugging information follows.
Path: /admin/structure/views/view/about_slider/preview/block/ajax
StatusText: OK
ResponseText: =[{"command":"settings","settings":{"basePath":"\/","pathPrefix":"","ajaxPageState":{"theme":"bartik","theme_token":"LEKfczQQG6fjcOEWhHnOrh8H-CJ0ihsdmJrl4nOQuAU","css":{"modules\/contextual\/contextual.css":1,"sites\/all\/modules\/views_slideshow\/contrib\/views_slideshow_cycle\/views_slideshow_cycle.css":1},"js":{"modules\/contextual\/contextual.js":1,"sites\/all\/libraries\/jquery.cycle\/jquery.cycle.all.js":1,"sites\/all\/modules\/views_slideshow\/contrib\/views_slideshow_cycle\/js\/views_slideshow_cycle.js":1}},"admin_menu":{"destination":"destination=admin\/structure\/views\/view\/about_slider\/preview\/block\/ajax","hash":"c67043301703a17ae56d13565b86913c","basePath":"\/admin_menu","replacements":{".admin-menu-users a":"1 \/ 1"},"margin_top":1},"viewsSlideshow":{"about_slider-block":{"methods":{"goToSlide":["viewsSlideshowPager","viewsSlideshowSlideCounter","viewsSlideshowCycle"],"nextSlide":["viewsSlideshowPager","viewsSlideshowSlideCounter","viewsSlideshowCycle"],"pause":["viewsSlideshowControls","viewsSlideshowCycle"],"play":["viewsSlideshowControls","viewsSlideshowCycle"],"previousSlide":["viewsSlideshowPager","viewsSlideshowSlideCounter","viewsSlideshowCycle"],"transitionBegin":["viewsSlideshowPager","viewsSlideshowSlideCounter"],"transitionEnd":[]},"paused":0}},"viewsSlideshowCycle":{"#vi...http:\/\/mtairy.toomodernmedia.com\/sites\/default\/files\/styles\/461x307\/public\/IMG_3936.JPG\" width=\"461\" height=\"307\" alt=\"\" \/\u003e\u003c\/div\u003e  \u003c\/div\u003e\u003c\/div\u003e\n\u003c\/div\u003e\n\u003cdiv id=\"views_slideshow_cycle_div_about_slider-block_2\" class=\"views-slideshow-cycle-main-frame-row views_slideshow_cycle_slide views_slideshow_slide views-row-3 views_slideshow_cycle_hidden views-row-odd\"\u003e\n  \u003cdiv class=\"views-slideshow-cycle-main-frame-row-item views-row views-row-0 views-row-first views-row-odd\"\u003e\n    \n  \u003cdiv class=\"views-field views-field-body\"\u003e        \u003cdiv class=\"field-content\"\u003e\u003cp\u003eEvery season we organize age and skill based baseball leagues open to all children in the area.\u003c\/p\u003e\n\u003c\/div\u003e  \u003c\/div\u003e  \n  \u003cdiv class=\"views-field views-field-field-image\"\u003e        \u003cdiv class=\"field-content\"\u003e\u003cimg typeof=\"foaf:Image\" src=\"http:\/\/mtairy.toomodernmedia.com\/sites\/default\/files\/styles\/461x307\/public\/IMG_4087.JPG\" width=\"461\" height=\"307\" alt=\"\" \/\u003e\u003c\/div\u003e  \u003c\/div\u003e\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n\u003c\/div\u003e\n  \u003c\/div\u003e\n\u003c\/div\u003e\u003c\/div\u003e    \u003c\/div\u003e\n  \n  \n  \n  \n  \n  \n\u003c\/div\u003e\u003c\/div\u003e\u003c\/div\u003e","settings":null},{"command":"insert","method":"prepend","selector":null,"data":"","settings":null}]

```

It appears as if some values are being left null, and I'm thinking that could be a clue to the cause of the problem.

Jquery.js is being loaded. I'm not getting any errors in the console.

Any help with debugging, heuristics, etc greatly appreciated.

# Answer
> -2 votes
Visit jquery update settings (intall, if it's missing) and set a different jquery version on "Alternate jQuery version for administrative pages" section.

---
Tags: 7, ajax
---


# Question
Title: How can I change a content entity to a config entity?
I created a project using Content Entity but now I need to change this entity to Config Entity. Do you know how I can do this?

# Answer
ContentEntity and ConfigEntity are very different. My advice is to just start over.
> 2 votes

# Answer
Agreed with @anonymous: the structure and purpose of config entities is very different from content entities. Start with a clean config entity and only then see if you can reuse some of your existing code, most likely in the form functions, twig templating and ancillary CSS and JS files.

And if you're starting from scratch, definitely try Drupal Console if you haven't already. It will generate spotless boilerplate code specifically for a config entity:

```
drupal generate:entity:config

```
> 2 votes

---
Tags: 8, entities
---


# Question
Title: How do I create custom layouts for Panelizer?
I was wondering how do you create custom layouts for Panelizer in D8? In D7, I can easily create my layouts, and just add a couple of lines on my .info file to let Drupal know where my layouts are.

I created a custom module following a "How to create custom layouts using Layout Builder tutorial". Can I just change the dependencies in the info.yml file that's inside my custom layout module like this:

```
name: 'Custom Layout'
type: module
description: 'Provides a way for layout'
core: 8.x
package: 'Custom'
dependencies:
  - panelizer:panelizer

```

Thanks!

# Answer
> 2 votes
Panelizer is based on Panels module, which uses Layout API module in Drupal Core for providing layout plugins. Please refer to the relevant documentation:

---
Tags: 8, panels, layout-builder
---


# Question
Title: How to get a list of fields that are used in entities?
I want to retrieve all fields that entities are using (including locked fields).

How can I get a list of fields that are used in entities?

Like we get in admin/reports/fields.

# Answer
> 9 votes
I would recommend EntityFieldManager::getFieldMap. The EntityManager is only a service to provide functions from other classes.

From documentation:

> **Return value**
>
> array An array keyed by entity type. Each value is an array which keys are field names and value is an array with two entries:
>
> * **type**: The field type.
> * **bundles**: An associative array of the bundles in which the field appears, where the keys and values are both the bundle's machine name.

# Answer
> 5 votes
`EntityFieldManagerInterface::getFieldMap()` produces a keyed array by entity type \> field name with further information on the field type and its associated bundles.

```
$field_map = \Drupal::entityManager()->getFieldMap();
$node_field_map = $field_map['node'];
$node_fields = array_keys($node_field_map['node']);

```

There's also `EntityFieldManagerInterface::getFieldDefinitions()` if you want further field metadata. It produces an array of `BaseFieldDefinition` & `FieldConfig` objects that you can parse through for further detail.

```
  $node_article_fields  =\Drupal::entityManager()->getFieldDefinitions('node','article');

```

# Answer
> 2 votes
`field_info_instance()` would do what you want, though if you look in the docs you will see that in D8 it is deprecated in favour of

```
Field::fieldInfo()->getBundleInstance($entity_type, $bundle, $field_name).

```

# Answer
> 1 votes
Different ways to get field data:

Get a list of fields include base fields like nid. (contains entity type, bundle, field name and field type).

```
$field_map = \Drupal::entityTypeManager()->getFieldMap();
// Can also get by field type.
$field_map = \Drupal::entityTypeManager()->getFieldMapByFieldType('entity_reference');

```

Also see @shawn-conn's answer.

Get a list of storage fields and their data. (non-bundle specific - e.g. 'node.field\_image')

```
// Get a list of storage fields
$field_config_ids = \Drupal::entityQuery('field_storage_config')
  // Allow access to all regardless of permissons.
  ->accessCheck(FALSE)
  ->condition('type', 'entity_reference')
  ->condition('status', 1)
  ->execute();

// Load all the fields.
$field_config_entities = \Drupal::entityTypeManager()->getStorage('field_storage_config')->loadMultipleOverrideFree($field_config_ids);

// Get where each config is used.
foreach (field_config_entities as $field_config_entity) {
  $bundles = $field_config_entity->getBundles();
}

```

Get a list of field instances and their data. (fields per bundle - e.g. 'node.story.field\_image')

```
$field_config_ids = \Drupal::entityQuery('field_config')
  ->accessCheck(FALSE)
  ->condition('field_type', 'entity_reference')
  ->condition('status', 1)
  ->execute();

// Get also filter to only get feilds with a default value.
$field_config_ids = \Drupal::entityQuery('field_config')
  ->accessCheck(FALSE)
  ->condition('field_type', 'entity_reference')
  ->condition('status', 1)
  ->condition('default_value.0.target_uuid', NULL, 'IS NOT NULL')
  ->execute();

// Load the data.
$field_config_entities = \Drupal::entityTypeManager()->getStorage('field_config')->loadMultipleOverrideFree($field_config_ids);

```

---
Tags: entities, 8
---


# Question
Title: How do I get the term name in a custom submit handler?
In Drupal 8/9, when you create a new term, the default status message is:

> Created new term %term.

`%term` contains the term name, which is linked to the term page.

I want to override this and remove the link (I want to show the term name, but I do not want to link the term name to the term page).

I thought I could do this in a custom submit handler:

```
function MYMODULE_term_create_form_submit(array &$form, FormStateInterface &$form_state) {
  \Drupal::messenger()->deleteByType('status');
  \Drupal::messenger()->addMessage(t('The group @group-name has been added.', ['@group-name' => NULL]));
}

```

However, I don't know how to get the term's name from `$form`. I searched the `$form` object with kint() and I could not find the form name.

Then I looked at core, which does this:

```
  public function save(array $form, FormStateInterface $form_state) {
    $term = $this->entity;

    $result = $term->save();

    $edit_link = $term->toLink($this->t('Edit'), 'edit-form')->toString();
    $view_link = $term->toLink()->toString();
    switch ($result) {
      case SAVED_NEW:
        $this->messenger()->addStatus($this->t('Created new term %term.', ['%term' => $view_link]));
        $this->logger('taxonomy')->notice('Created new term %term.', ['%term' => $term->getName(), 'link' => $edit_link]);
        break;

```

But, I don't have access to the term object in the submit handler.

What's the simplest way to do this without doing a quick-and-dirty patch to core?

# Answer
> 1 votes
In a submit handler you can find the form object in $form\_state:

```
$term = $form_state->getFormObject()->getEntity();

```

---
Tags: forms, taxonomy-terms
---


# Question
Title: How do I add/remove a user role based on subscription?
I have a product "Membership" that is set up as a subscription. When a user purchases this "Membership" I would like to assign them a "Member" role. How do I do this?

I have looked at the docs but they are incomplete for Commerce 2.

I have looked at Commerce License, but I'm not sure if it's production ready for 8/9 or even if it's the right choice.

# Answer
> 3 votes
Your question is way too broad for this site, but since I just did this in a site of mine recently, here are some hints.

Create an EventSubscriber:

```
  /**
   * Set fields and roles for user accounts that purchase subscriptions.
   */
  public function postPlaceTransition(WorkflowTransitionEvent $event) {
    $order = $event->getEntity();
    $customer = $order->getCustomer();
    $customer->addRole('MYROLE');
  }

```

---
Tags: commerce
---


# Question
Title: Is it possible to link images to different URLs?
Using View's module it is possible to create a page to display some content horizontally. I have done this using carousel feature. The content type that these contents belong to have an `image_field` and a `body_field`.

What I want from Drupal 8 is that when these images are clicked they should redirect visitors to a specific page (not to the node's / content's page).

Is it possible to do so or using html on `body_field` to place the images with `a` and `img` tags is the only way?

UPDATE:

At first I understood nothing from the answer below but a day later it just made sense like in the movie "Phenomenon"; I was struck by a mysterious light in the sky. Here is what I did:

* Created a new `link_field` inside the content type that I am using on this **View**.
* Went back to the content / node (under **Content**) where I wanted to add the link to the image and filled the `link_field`
* Added this newly created `link_field` to the **View** and made it hidden by checking the box titled *"Exclude from display"*.
* Clicked on the `image_field` on **View** settings (under the FEILDS) and *REWRITE RESULTS* \> check the box *"Output this field as a custom link"* (An empty area shows up to be filled here).
* Went down and expanded the drop down list titled *"REPLACEMENT PATTERNS"* and found the `link_field`'s name (The name you gave to your `link field` you have created it) and copied the string (something like `{{ the_name_of_my_link_field }}`).
* Pasted this string into the empty area above then Saved, Saved, Saved to exit.

That's all!

# Answer
You can do this using the Rewrite feature of Views.

These instructions assume that the view is set to show **Fields** (instead of **Content** or something else). If you are not using fields, you can switch to fields under **FORMAT** in the Views UI.

1. Click the image field in your view and select the checkbox **Exclude from display**.
2. Add a new field to the view of type **Custom text**.
3. On the custom text configuration screen, check the *Replacement patterns*. This will include some twig tokens that you can use, including the image file. You can then use this token to add HTML to the **Text** field to get the link you want. For example, `<a href="/mypage">{{ image }}</a>`.

Note that when using Views twig replacement tokens in a custom text field, order matters! If your custom text field is above another field, it won't be able to get the tokens from the field(s) below. In that case, you will need to click the flippy triangle to the right of **Fields** in the Views UI and choose rearrange, and then move the field that uses tokens below the field(s) that supply the tokens.

Another option is to open up the settings for your image field in Views and, under **Rewrite results**, click **Output this field as a custom link** and set the link options there.
> 2 votes

---
Tags: views, media
---


# Question
Title: Using Composer in a multisite installation
How do I manage modules via composer in a multisite architecture? For example, if I want one site to have version 2.3 of a module, and another to have version 2.4, how do I do this?

Do I have a composer file in each site that can inherit from the composer file in the parent Drupal application?

# Answer
Short answer: **you cannot do it The (new Drupal) Composer Way™** (still).

The composer is mostly project-oriented, however, based on the fact that they are projects of the projects, there is a chance that a composer.json could be made that would operate on a subsite level.

As far as we can go would be to hope that something will be done in the coming 9.2 release, somewhere south of Spring 2021. Until then, workaround and search for the best practices and other experiences (however sparsely) seems the only way

#2847218: Improve documentation around the multisite functionality

## The (temporarily and incomplete) solution:

The only thing you are left with is to use the `composer` for the common, shared modules and to use `drush` or manually download modules and themes according to Drupal multisite structure:

```
-- sites
   -- site1
         -- modules           ----> site specific modules
            -- custom
            -- contrib
         -- themes            ----> site specific themes
            -- custom
            -- contrib
         -- files

```

Beside official documentation, you can read this post too: Drupal Multisite Setup: Are There (Still) any Valid Reasons to Use It? Should It Get Removed in Drupal 9.x?
> 1 votes

---
Tags: multi-sites, composer
---


# Question
Title: How to limit the terms of the view to the terms used?
On the product I created a "tags" taxonomy terms field. I have created a hundred "tags".

My products use around 10 "tags".

I created a pageview of my products with an exposed filter criterion "tags".

My problem :

The filter displayed on the product page displays all the terms. I only want to display the terms used by my products. How to do this ?

# Answer
If doing it manually is acceptable you can do it on the Exposed Filter Settings by ticking the `Limit list to selected items` and then selecting only the 10 tags from the list above (hold Ctrl key to add to the selection). This works if you'll always or for long periods of time need only those 10 tags.

---

If you want Views to filter automatically and only show what's within the results without you having to choose the tags manually you have to use the Contextual filter instead of the Exposed regular Filter. Contextual filters are under Advanced options.

Add the Contextual filter for the same field "Tags" and configure it:
`When the filter value is NOT available`
**Display a summary**
`Format` **List**
`Base path` (you *must* enter the Page path if this isn't the first Page Display in your Views)
**Display record count with link**
`More`
**Transform spaces to dashes in URL**

Adjust the options for when the value is not available to your needs (Tags Taxonomy term etc.).

This way you get a list of term IDs that link through to a list of nodes tagged with those terms. That is because the Tags field only stores the TID information, not the term name. When you first load the page you only see the Summary, no results, you have to click through to see the results. But if you create the Summary as Attachment on a Page Display you can get it both ways, the Summary and the Results at the same time (keep the path the same).

But you probably want the term name to be displayed instead of the term ID. In that case remove that Contextual filter, and add the one for Taxonomy term Name, but you need a Relationship first for that information to become available.

Add a Relationship **Taxonomy term referenced from field\_tags** (or whatever the field is called in your case), require it becasue you don't want summary results without tags!

Then add a Contextual filter **Name** from `Taxonomy term` Category, it will use the Relationship we created, and configure it like the above Contextual settings.

---

Alternatively you can use an additional module, this one did it in D7 but not yet ported to D8: Views Selective Filters.

Facets module provides an easy filtering interface from what's in the results.
> 2 votes

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


title: Custom ordering flow

text:
# Question
Title: Custom ordering flow
I was wondering if it's possible to replace the default commerce flow with my own custom flow.

As far as I know the default flow is following:

* Add individual products to cart on Product's detail page or in Products View
* Go to cart and proceed to checkout
* Add shipping & billing information
* Complete the payment

My flow need to be a bit different. I would like to create View of Products *(my products are entry-tickets for an attraction)* where user can select quantity of each Product he would like to purchase. I know this View can be AJAXified to change total price dynamically according to quantity of each product. When customer selects all tickets and quantities I need to send him to second page of my Multi-step webform where he enters shipping & billing information and finally confirms / fullfils the payment. After successful payment confirmation / fullfilment I'd like to display the third page of Multi-step Webform where is only confirmation and "thank you" message.

I've read through Commerce 2 documentation and I know how to change Order & Checkout workflows, but I'm not sure if I can use Multi-step Webform where the steps are following *(as described above)*:

* Step 1: Select quantities of each Product in Products View (10 products in total - ticket types)
* Step 2: Fill shipping and billing information
* Step 3: Display confirmation message

The general idea is to skip the cart step where I need to go to cart page and instead realize whole flow as a 3-step Multi-step Webform.

Thanks!

# Answer
To skip the cart part of the checkout flow, I have been using the patch here. This is the leading patch for decoupling the cart from Commerce (it's a bit hard-wired at present).

If you want to customize the checkout flow with more steps, you can write a custom checkout flow plugin.

To add a custom confirmation message, you can write a checkout pane.
> 2 votes

---
Tags: 8, commerce, webforms
---


# Question
Title: Use HTML tags inside rows of a table in a render array
I'm creating a table within a render array. I can easily create rows within the table like so

```
$rows = [
    'test 1',
    'test 2',
    'test 3',
];
$header = [
    'header 1',
    'header 2',
    'header 3',
];
$render['table'] = [
  '#theme' => 'table',
  '#header' => $header,
  '#rows' => $rows,
];

```

However when I attempt to include html tags within the row like so:

```
$rows = [
    '<a href="test1">test 1</a>',
    '<a href="test2">test 2</a>',
    '<a href="test3">test 3</a>',
];

```

it spits it out with the tags written out. It shows

```
<a href="test1">test 1</a><a href="test2">test 2</a><a href="test3">test 3</a>

```

instead of showing

test 1 test 2 test 3

Is there a way to use html tags inside rows of a table element in a render array?

UPDATE: I've also tried

```
'#rows'    => [
                        'test 1'  => [
                            '#type'  => 'html_tag',
                            '#tag'   => 'h1',
                            '#value' => 'Test 1',
                        ],
                        'test 2'  => [
                            '#type'  => 'html_tag',
                            '#tag'   => 'h1',
                            '#value' => 'Test 2',
                        ],
                        'test 3'  => [
                            '#type'  => 'html_tag',
                            '#tag'   => 'h1',
                            '#value' => 'Test 3',
                        ],
                    ],

```

But that returns a table with 3 rows and 3 columns that say

'html\_tag' 'h1' 'Test 1'

'html\_tag' 'h1' 'Test 2'

'html\_tag' 'h1' 'Test 3'

Instead of actually producing an html tag.

# Answer
Try creating the links using function Drupal::l,

For example,

```
$url = Url::fromUri('http://example.com/');
$link1 = \Drupal::l(t('Link1'), $url);
$url = Url::fromUri('http://example.com/');
$link2 = \Drupal::l(t('Link2'), $url);
$url = Url::fromUri('http://example.com/');
$link3 = \Drupal::l(t('Link3'), $url);
$rows = [
  array(
    $link1,
    $link2,
    $link3,
  ),
];
$header = [
    'header 1',
    'header 2',
    'header 3',
];
$render['table'] = [
  '#theme' => 'table',
  '#header' => $header,
  '#rows' => $rows,
];

```

To add other html tags to table , you can use Drupal markup element and renderer service,

```
$element['#markup'] = '<span>Example Span Tag</span>';
$span_tag = \Drupal::service('renderer')->render($element);

```
> 3 votes

# Answer
You can use the Markup class:

```
Markup::create('<strong>test 1</strong>')

```

Full example with rendering a table can be found here: https://stefvanlooveren.me/blog/how-render-table-drupal-8
> 1 votes

# Answer
In order to avoid HTML tags being escaped, `#rows` items should be defined as arrays with `data` property. For example:

```
$rows = [
  ['data' => '<strong>test 1</strong>'],
  ['data' => '<s>test 2</s>'],
  ['data' => '<div>test 3</div>'],
];
$header = [
  'header 1',
  'header 2',
  'header 3',
];
$render['table'] = [
  '#theme' => 'table',
  '#header' => $header,
  '#rows' => $rows,
];

```

I could not find a reference to this in the documentation. Discovered via trial and error.
> 0 votes

# Answer
None of the above worked for me, but this did:

```
$link = Link::createFromRoute('Test', '<front>');
$row['col1'] = ['data' => [ '#markup' => 'Something (' . $link->toString() . ')']];

```
> 0 votes

---
Tags: forms, 8
---


# Question
Title: How do you programmatically get the current user's status?
I'm trying to get the currently logged-in user's status (active or blocked) in `template_preprocess_user`. I tried the following with no luck.

```
function MYTHEME_preprocess_user(&$variables) {
  $user = $variables['user'];
  $variables['status'] = $user->status();
}

function MYTHEME_preprocess_user(&$variables) {
  $user = $variables['user'];
  $variables['status'] = $user->getStatus();
}

```

# Answer
> 5 votes
Assuming this is Drupal 8, try `$user->isBlocked()`.

If this is Drupal 7, you probably just need to call `user_load($uid)` first in order to get a fully-loaded user object before checking the `$user->status`. Or try `user_is_blocked($name)`.

---
Tags: 8, theming, users
---


# Question
Title: Callback to Drupal site after curl call to 3rd party site doesn't resume authenticated session if more than 120 seconds elapsed since authentication
UPDATED SITUATION:

* A user authenticates on my site.
* The user selects items to purchase and is sent via curl call (see below) to a payment site.
* The payment site does its thing and returns to my site via a callback URL I posted to it. I assume it is also a curl call, since data is posted back.
* Upon return, if less than 120 seconds has elapsed since the user originally authenticated on my site, the user's authenticated session is resumed (good).
* Upon return, if more than 120 seconds has elapsed since the user originally authenticated on my site, a new session is started (bad). The user is effectively signed out.

This behavior is 100% consistent. I can call the 3rd party site and return any number of times within the 120 second window after authentication and the authenticated session is always resumed. But as soon as I return after 120 seconds, a new session is started.

It doesn't matter whether I authenticate, immediately go to the 3rd party site, and then wait there 120 seconds, or if I authenticate, wait at my site 120 seconds, and then go to the 3rd party site, if the return to my site happens more than 120 seconds after original authentication on my site, a new session is started instead of resuming the authenticated session.

What could cause this? Some kind of timer setting, cache setting, etc.? Maybe a module? I'm asking before I begin the process of disabling modules one by one.

My curl call:

```
$ch = curl_init('https://commerce.cashnet.com/404Handler/pageredirpost.aspx');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // $data includes the callback URL
curl_exec($ch);
curl_close($ch);
exit;

```

AN EARLIER VERSION OF THE PROBLEM DESCRIPTION talked about session ids changing, information passed, etc. I removed all that to simplify, as it got too long to leave it in. The original set of comments below are based on that earlier description, which is why they don't seem to make sense now. But they were helpful in guiding me to further testing that revealed the 120-second issue.

# Answer
A callback from a credit card processing site to your Drupal server should *never* have the same session as the paying customer. If it does, then you have a problem.

But I'm not sure that's what you're saying - you are vague when you talk about session ID. If you mean that the paying customer's session ID shouldn't change when your server sends the payment information to the credit card processing site then receives the response, then you are correct. But why even mention credit card processing and posting back in this case, as it's not very relevant? If the paying customer's session ID changes, then you need to investigate how the session ID is invalidated and what your session timeout is. Perhaps your callback is invalidating a cache tag that forces a new session to be generated for that user.
> 1 votes

---
Tags: 8, sessions
---


title: Missing some block fields

text:
# Question
Title: Missing some block fields
I'm working with layout\_builder and page\_manager together and I'm having some issues.

I want to add an existing node to my right sidebar, but I don't see the option anywhere where I can do that.

In D7, all I have to do is click the gear icon \> click existing node \> add the node ID. Done!

Does anyone know what I have to do?

Thank you!

This is all I see

# Answer
I found out layout\_builder doesn't provide you an option to do it. I found this module that lets you do it. https://www.drupal.org/project/entity\_block

Hope this helps anyone who has the same issue as me.
> 0 votes

---
Tags: 8, layout-builder
---


# Question
Title: Twig find if a css class exists in a tag
Is there a way to find out if a css class exists in a specific tag through twig?

For example:

```
<body class="new-class">

```

Then I'm able to do a conditional statement in twig based if `new-class` exists. Is this possible?

# Answer
> 4 votes
You could use **hasClass** to find the CSS class in a specific tag

eg. `{% if body.attributes.hasClass('new-class') %}`

---
Tags: theming
---


title: Problem upgrading via Composer

text:
# Question
Title: Problem upgrading via Composer
I am currently trying to upgrade my site from drupal 8.9 to drupal 9. I ran these commands to give permissions:

```
$ chmod 777 web/sites/default
$ find web/sites/default -name "*settings.php" -exec chmod 777 {} \;
$ find web/sites/default -name "*services.yml" -exec chmod 777 {} \;

```

Then I required the the recommended project for drupal 9 and also the dev:

```
$ composer require drupal/core-recommended:^9.0.0 drupal/core-composer-scaffold:^9.0.0 drupal/core-project-message:^9.0.0 --update-with-dependencies --no-update
$ composer require drupal/core-dev:^9.0.0 --dev --update-with-dependencies --no-update

```

All my modules are up to date and I also ran upgrade status to check for errors. I got one error, which was in tests (I guess that would be OK?) and a couple of warnings for a library that wasn't installed.

Then I ran

```
$ composer update

```

and got the following errors:

```
Problem 1
- drupal/core-recommended 9.0.7 requires drupal/core 9.0.7 -> satisfiable by drupal/core[9.0.7].
- Conclusion: don't install drupal/core 9.0.7
- drupal/core-recommended 9.0.6 requires drupal/core 9.0.6 -> satisfiable by drupal/core[9.0.6].
- Conclusion: don't install drupal/core 9.0.6
- drupal/core-recommended 9.0.5 requires drupal/core 9.0.5 -> satisfiable by drupal/core[9.0.5].
- Conclusion: don't install drupal/core 9.0.5
- drupal/core-recommended 9.0.4 requires drupal/core 9.0.4 -> satisfiable by drupal/core[9.0.4].
- Conclusion: don't install drupal/core 9.0.4
- drupal/core-recommended 9.0.3 requires drupal/core 9.0.3 -> satisfiable by drupal/core[9.0.3].
- Conclusion: don't install drupal/core 9.0.3
- drupal/core-recommended 9.0.2 requires drupal/core 9.0.2 -> satisfiable by drupal/core[9.0.2].
- Conclusion: don't install drupal/core 9.0.2
- drupal/core-recommended 9.0.1 requires drupal/core 9.0.1 -> satisfiable by drupal/core[9.0.1].
- Conclusion: don't install drupal/core 9.0.1
- drupal/core-recommended 9.0.0 requires drupal/core 9.0.0 -> satisfiable by drupal/core[9.0.0].
- Conclusion: don't install drupal/core 9.0.0
- drupal/core-recommended 9.0.0-rc1 requires drupal/core 9.0.0-rc1 -> satisfiable by drupal/core[9.0.0-rc1].
- Conclusion: don't install drupal/core 9.0.0-rc1
- drupal/core-recommended 9.0.0-beta3 requires drupal/core 9.0.0-beta3 -> satisfiable by drupal/core[9.0.0-beta3].
- Conclusion: don't install drupal/core 9.0.0-beta3
- drupal/core-recommended 9.1.0-alpha1 requires drupal/core 9.1.0-alpha1 -> satisfiable by drupal/core[9.1.0-alpha1].
- Conclusion: don't install drupal/core 9.1.0-alpha1
- drupal/core-recommended 9.2.x-dev requires drupal/core 9.2.x-dev -> satisfiable by drupal/core[9.2.x-dev].
- Conclusion: don't install drupal/core 9.2.x-dev
- drupal/core-recommended 9.1.x-dev requires drupal/core 9.1.x-dev -> satisfiable by drupal/core[9.1.x-dev].
- Conclusion: don't install drupal/core 9.1.x-dev
- drupal/core-recommended 9.0.x-dev requires drupal/core 9.0.x-dev -> satisfiable by drupal/core[9.0.x-dev].
- Conclusion: don't install drupal/core 9.0.x-dev
- drupal/core-recommended 9.0.0-beta2 requires drupal/core 9.0.0-beta2 -> satisfiable by drupal/core[9.0.0-beta2].
- Conclusion: don't install drupal/core 9.0.0-beta2
- drupal/core-recommended 9.0.0-beta1 requires drupal/core 9.0.0-beta1 -> satisfiable by drupal/core[9.0.0-beta1].
- Conclusion: don't install drupal/core 9.0.0-beta1
- drupal/core-recommended 9.0.0-alpha2 requires drupal/core 9.0.0-alpha2 -> satisfiable by drupal/core[9.0.0-alpha2].
- Conclusion: don't install drupal/core 9.0.0-alpha2- drupal/core-recommended 9.0.0-alpha1 requires drupal/core 9.0.0-alpha1 -> satisfiable by drupal/core[9.0.0-alpha1].
- Installation request for drupal/core-recommended ^9.0.0 -> satisfiable by drupal/core-recommended[9.0.0, 9.0.0-alpha1, 9.0.0-alpha2, 9.0.0-beta1, 9.0.0-beta2, 9.0.0-beta3, 9.0.0-rc1, 9.0.1, 9.0.2, 9.0.3, 9.0.4, 9.0.5, 9.0.6, 9.0.7, 9.0.x-dev, 9.1.0-alpha1, 9.1.x-dev, 9.2.x-dev].
- Installation request for drupal/upgrade_status ^2.11 -> satisfiable by drupal/upgrade_status[2.x-dev, 2.11.0].

```

My composer.json file looks like this:

```
{
"name": "name",
"description": "decription",
"type": "project",
"license": "",
"authors": [
    {
        "name": "",
        "role": ""
    }
],
"repositories": [
    {
        "type": "composer",
        "url": "https://packages.drupal.org/8"
    }
],
"require": {
    "composer/installers": "^1.7",
    "cweagans/composer-patches": "^1.6",
    "drupal/admin_toolbar": "^2.0",
    "drupal/console": "^1.0.2",
    "drupal/core-composer-scaffold": "^9.0.0",
    "drupal/core-project-message": "^9.0.0",
    "drupal/core-recommended": "^9.0.0",
    "drupal/paragraphs": "^1.2",
    "drupal/paragraphs_edit": "^2.0@alpha",
    "drush/drush": "^10",
    "j7mbo/twitter-api-php": "^1.0",
    "vlucas/phpdotenv": "^2.4",
    "webflo/drupal-finder": "^1.0.0",
    "webmozart/path-util": "^2.3"
},
"require-dev": {
    "drupal/core-dev": "^9.0.0",
    "drupal/upgrade_status": "^2.11"
},
"conflict": {
    "drupal/drupal": "*"
},
"minimum-stability": "dev",
"prefer-stable": true,
"config": {
    "sort-packages": true
},
"autoload": {
    "classmap": [
        "scripts/composer/ScriptHandler.php"
    ]
},
"scripts": {
    "drupal-scaffold": "DrupalComposer\\DrupalScaffold\\Plugin::scaffold",
    "pre-install-cmd": [
        "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
    ],
    "pre-update-cmd": [
        "DrupalProject\\composer\\ScriptHandler::checkComposerVersion"
    ],
    "post-install-cmd": [
        "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
    ],
    "post-update-cmd": [
        "DrupalProject\\composer\\ScriptHandler::createRequiredFiles"
    ]
},
"extra": {
    "drupal-scaffold": {
        "locations": {
            "web-root": "web/"
        }
    },
    "installer-paths": {
        "web/core": ["type:drupal-core"],
        "web/libraries/{$name}": ["type:drupal-library"],
        "web/modules/contrib/{$name}": ["type:drupal-module"],
        "web/profiles/contrib/{$name}": ["type:drupal-profile"],
        "web/themes/contrib/{$name}": ["type:drupal-theme"],
        "drush/contrib/{$name}": ["type:drupal-drush"]
    }
}

```

}

# Answer
> 3 votes
Remove `drupal/console` (`composer remove drupal/console`); it doesnt work on Drupal 9 yet, and it can break composer updates.

If it still doesn't work, delete the `/vendor` directory and `composer.lock`, then try running `composer update` again.

---
Tags: updating, composer, 9
---


title: Content list menus translation

text:
# Question
Title: Content list menus translation
I have a multilingual site and the content list view can be accessed like this:

htttp://www.website.com/{country\_code}/{language\_code}/admin/content

There are only two administration page languages: English and Japanese, and the toolbar is displayed only in these 2 languages regardless the language\_code.

However, the content list menus are displayed in according to the language\_code. For example, in case of French (fr) it looks like this:

What I want to do is to display content list menus only in the administration page language. So I want that the language\_code in the path to be ignored and I have the menus shown only in English or Japanese.

Could you please advise some approaches to solve the issue?

# Answer
> 1 votes
This can be changed on the **Detection and selection** page of the Language settings: `/admin/config/regional/language/detection`.

This page lists the detection methods, and by default, Drupal 8/9 prioritizes the path.

But, here you have two options.

Option 1: You can enable **User** (Follow the user's language preference) and then drag **User** above **Path**, which should give the admin pages in the admin language. This is simple, but the drawback to this approach is that users on the site will see content based on the language set in their account, not the site, which may not be what you want.

Option 2: You can enabled **Account administration pages** and then drag **Account administration pages** above **Path**. This will create a new setting on the user account edit page to set the admin language, so you may have to check all the admin accounts and set the language appropriately. This approach is more complex than the first, but limits the change to admin content only, which is probably what you want.

---
Tags: views
---


# Question
Title: Is there a way to change how a form button looks?
I know how to add a class to a form element and how to add a form submission button, but there are classes that are automatically added to these buttons in my Drupal 8 install.

The form I am editing has two buttons, a submit and a skip button; both the buttons look the same. I would like to add a visual clue to the difference between the buttons. The buttons get an automatic `btn-primary` class but I want the skip button to have a `btn-outline-primary` class. If I add that class with `'#attributes' => ['class' => ['btn-outline-primary']]`, the class gets added, but the `btn-primary` class is still part of the button. The combination of those two classes makes the button text the same color as the button background color, and thus invisible unless you hover over the button.

Is there a way to perhaps not include the button in the template, for example `{{ form.actions.skip }}` but more verbose? In the sense that takes over some of the Drupal 8 automation?

```
<button class="btn btn-outline-primary">{{from.actions.skip.something}}</button>

```

# Answer
> 0 votes
There are two basic ways in Drupal to remove the class, a PHP hook or a Twig template. It's only possible to describe this in a general way because the question doesn't contain details about which theme and templates are in use.

For a PHP solution find out which hook is adding this class and then implement the same hook in your custom theme. If the attributes contain the specific class you've added to the form build, then remove the conflicting class.

For a Twig solution enable Twig debug, find out which template is rendering the button now, and copy it to your theme's templates folder. Then do the same thing as described before in Twig:

```
{% if attributes.hasClass('btn-outline-primary') %}
  <input{{ attributes.removeClass('btn-primary') }} />{{ children }}
{% else %}
  <input{{ attributes }} />{{ children }}
{% endif %}

```

---
Tags: 8, theming, forms
---