# Question
Title: How can I create a custom field type for a select with multiple values?
I need a field type with 3 select in it. The field type is created and works like a charm but I'd like one of these select may have multiple values. What must I change? I add '#multiple' =\> TRUE, in the widget. But I can't save my values. I should probably change the type of field in the FieldType but how? Thanks in advance.

```
/**
 * Provides a field type of resource.
 *
 * @FieldType(
 *   id = "resource",
 *   label = @Translation("Resource"),
 *   default_formatter = "resource_formatter",
 *   default_widget = "resource_widget",
 * )
 */
class ResourceItem extends FieldItemBase {

  public static function propertyDefinitions(FieldStorageDefinitionInterface $field_definition) {
    $properties = [];
    $properties['topic'] = DataDefinition::create('string');
    $properties['material'] = DataDefinition::create('string');
    $properties['add_infos'] = DataDefinition::create('string');
    $properties['columns_display'] = DataDefinition::create('string');

    return $properties;
  }

  public static function schema(FieldStorageDefinitionInterface $field_definition) {
    return [
      'columns' => [
        'topic' => [
          'type' => 'varchar',
          'length' => '255',
          'not null' => FALSE,
        ],
        'material' => [
          'type' => 'varchar',
          'length' => '255',
          'not null' => FALSE,
        ],
        'add_infos' => [
          'type' => 'varchar',
          'length' => '255',
          'not null' => FALSE,
        ],
        'columns_display' => [
          'type' => 'varchar',
          'length' => '255',
          'not null' => FALSE,
        ],
      ],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function isEmpty() {
    $value1 = $this->get('topic')->getValue();
    $value2 = $this->get('material')->getValue();
    $value3 = $this->get('add_infos')->getValue();
    $value4 = $this->get('columns_display')->getValue();
    return empty($value1) && empty($value2) && empty($value3) && empty($value4);
  }

}

```

```
/**
 * Plugin implementation of the 'topic_widget' widget.
 *
 * @FieldWidget(
 *   id = "resource_widget",
 *   label = @Translation("Resource default"),
 *   field_types = {
 *     "resource"
 *   }
 * )
 */
class ResourceDefaultWidget extends WidgetBase {

  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $config = \Drupal::config('resources.config');

    $json_topics = file_get_contents($config->get('global_config.url_api') . '/topics');
    $topics = Json::decode($json_topics);
    $options_topics[0] = '--- Choose topic ---';
    foreach ($topics as $key => $topic) {
      $options_topics[$topic['name']] = ucfirst($topic['name']);
    }
    $element['topic'] = [
      '#type' => 'select',
      '#title' => t('Topic'),
      '#description' => t('List of topics from osteoporosis-foundation'),
      '#options' => $options_topics,
    ];

    $json_materials = file_get_contents($config->get('global_config.url_api') . '/materials');
    $materials = Json::decode($json_materials);
    $options_mat[0] = '--- Choose material ---';
    foreach ($materials as $key => $material) {
      $options_mat[$material['name']] = ucfirst($material['name']);
    }
    $element['material'] = [
      '#type' => 'select',
      '#title' => t('Material'),
      '#description' => t('List of materials from osteoporosis-foundation'),
      '#options' => $options_mat,
    ];

    $json_add_infos = file_get_contents($config->get('global_config.url_api') . '/additional-information');
    $add_infos = Json::decode($json_add_infos);
    $options_add_infos[0] = '--- Choose additional information ---';
    foreach ($add_infos as $key => $info) {
      $options_add_infos[$info['name']] = ucfirst($info['name']);
    }
    $element['add_infos'] = [
      '#type' => 'select',
      '#title' => t('Additional Information'),
      '#multiple' => TRUE,
      '#description' => t('List of additional information from osteoporosis-foundation'),
      '#options' => $options_add_infos,
    ];

    $element['columns_display'] = [
      '#type' => 'select',
      '#title' => t('Number of column to display'),
      '#options' => [
        'null'     => '--- Choose column(s) to display ---',
        'col-md-3' => '1 column',
        'col-md-6' => '2 columns',
        'col-md-9' => '3 columns',
        'col-md-12' => '4 columns',
      ],
    ];

    //setting default value to all fields from above
    $childs = Element::children($element);
    foreach ($childs as $child) {
      $element[$child]['#default_value'] = isset($items[$delta]->{$child}) ? $items[$delta]->{$child} : NULL;
    }

    return $element;
  }

}

```

```
/**
 * Plugin implementation of the 'resource_formatter' formatter.
 *
 * @FieldFormatter(
 *   id = "resource_formatter",
 *   label = @Translation("Resource default"),
 *   field_types = {
 *     "resource"
 *   }
 * )
 */
class ResourceDefaultFormatter extends FormatterBase{

  public function viewElements(FieldItemListInterface $items, $langcode) {
    $config = \Drupal::config('resources.config');

    $element = [];

    foreach ($items as $delta => $item) {
      $column_display = $item->columns_display;

      $topics = 'topics=' . str_replace(' ', '+', $item->topic);
      $materials = '&materials=' . str_replace(' ', '+', $item->material);
      $additional_info = '&additional_info=' . str_replace(' ', '+', $item->add_infos);

      $json_all  = file_get_contents($config->get('global_config.url_api').'/all' . '?' . $topics . $materials . $additional_info);

      $all_content       = Json::decode($json_all);

      foreach ($all_content['rows'] as $key => $content){
        $type_explode = explode('-', $content['type']);
        $type = strtolower(str_replace(' ', '_', trim(end($type_explode))));

        switch($type){
          case ('remote_videos'):
            $element[] = [
              '#theme' => 'video',
              '#resource' => $content,
              '#column_display' => $column_display
            ];
            break;
          default:
            $element[] = [
              '#theme' => 'file',
              '#resource' => $content,
              '#column_display' => $column_display
            ];
        }
      }
    }

    return $element;
  }

}

```

# Answer
> 1 votes
I update my code following the 4k4's comment and now it works. Thanks for your help

```
/**
 * Plugin implementation of the 'topic_widget' widget.
 *
 * @FieldWidget(
 *   id = "resource_widget",
 *   label = @Translation("Resource default"),
 *   field_types = {
 *     "resource"
 *   }
 * )
 */
class ResourceDefaultWidget extends WidgetBase {

  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
    $config = \Drupal::config('resources.config');

    $json_topics = file_get_contents($config->get('global_config.url_api') . '/topics');
    $topics = Json::decode($json_topics);
    $options_topics[0] = '--- Choose topic ---';
    foreach ($topics as $key => $topic) {
      $options_topics[$topic['name']] = ucfirst($topic['name']);
    }
    $element['topic'] = [
      '#type' => 'select',
      '#title' => t('Topic'),
      '#description' => t('List of topics from osteoporosis-foundation'),
      '#default_value' => isset($items[$delta]->topic) ? $items[$delta]->topic : NULL,
      '#options' => $options_topics,
    ];

    $json_materials = file_get_contents($config->get('global_config.url_api') . '/materials');
    $materials = Json::decode($json_materials);
    $options_mat[0] = '--- Choose material ---';
    foreach ($materials as $key => $material) {
      $options_mat[$material['name']] = ucfirst($material['name']);
    }
    $element['material'] = [
      '#type' => 'select',
      '#title' => t('Material'),
      '#description' => t('List of materials from osteoporosis-foundation'),
      '#default_value' => isset($items[$delta]->material) ? $items[$delta]->material : NULL,
      '#options' => $options_mat,
    ];

    $json_add_infos = file_get_contents($config->get('global_config.url_api') . '/additional-information');
    $add_infos = Json::decode($json_add_infos);
    $options_add_infos[0] = '--- Choose additional information ---';
    foreach ($add_infos as $key => $info) {
      $options_add_infos[$info['name']] = ucfirst($info['name']);
    }
    $element['add_infos'] = [
      '#type' => 'select',
      '#title' => t('Additional Information'),
      '#multiple' => TRUE,
      '#description' => t('List of additional information from osteoporosis-foundation'),
      '#default_value' => isset($items[$delta]->add_infos) ? unserialize($items[$delta]->add_infos) : NULL,
      '#options' => $options_add_infos,
    ];

    $element['columns_display'] = [
      '#type' => 'select',
      '#title' => t('Number of columns to display'),
      '#default_value' => isset($items[$delta]->columns_display) ? $items[$delta]->columns_display : NULL,
      '#options' => [
        'null'     => '--- Choose column(s) to display ---',
        'col-md-12' => '1 column',
        'col-md-9' => '2 columns',
        'col-md-6' => '3 columns',
        'col-md-3' => '4 columns',
      ],
    ];

    //setting default value to all fields from above
    /*$childs = Element::children($element);
    foreach ($childs as $child) {
      $element[$child]['#default_value'] = isset($items[$delta]->{$child}) ? $items[$delta]->{$child} : NULL;
    }*/

    return $element;
  }

  public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
    if($values[0]['add_infos'] != '0'){
      $values[0]['add_infos'] = serialize($values[0]['add_infos']);
    }

    return $values;
  }

}

```

---
Tags: 8, entities
---


title: HTML is being printed in the output

text:
# Question
Title: HTML is being printed in the output
The output from the below code is printing HTML. How can I make the "p" tags disappear?

> ```
> <p>answer 1</p>
>
> ```

```
{% block paragraph %}
  <div {{ attributes.addClass(classes) }}>
    {% block content %}
      <h1>{{ content.field_accordion_title.0}}</h1>
      {% for grid_item in paragraph.field_accordion %}
        <button class="accordion">{{ grid_item.entity.field_accordion_list_item_headin.value }}</button>
        <div class="panel">
        {{ grid_item.entity.field_accordion_list_item_text.value }}
        </div>
      {% endfor %}
    {% endblock %}
  </div>
{% endblock paragraph %}

```

Note: I don't want to trim the HTML tags but actually render them. Perhaps drupal\_entity() will help to render the output of {{ grid\_item.entity.field\_accordion\_list\_item\_text.value }}. How can this be done?

Note: I don't want to trim the HTML tags but actually render them. Perhaps drupal\_entity() will help to render the output of {{ grid\_item.entity.field\_accordion\_list\_item\_text.value }}. How can this be done?

# Answer
> 0 votes
Try `{{ grid_item.entity.field_accordion_list_item_text.processed }}` instead of `{{ grid_item.entity.field_accordion_list_item_text.value }}`

i.e. replace `value` with `processed`

# Answer
> -1 votes
I assume the string `<p>answer 1</p>` is escaped and printed but you want to actually render the HTML tags.

In that case `{{ grid_item.entity.field_accordion_list_item_text.value | raw }}` should do the trick, **assuming the variable is safe**. If the value was entered by a user, take a look at this: How to safely render node body on a custom variable?.

---
Tags: theming
---


title: Get the value of the "src" attribute

text:
# Question
Title: Get the value of the "src" attribute
I am having hard time with getting the value of YouTube video thumbnail URL, in order to use it as background image in a template file.

I created a video content type and added a remote video field (*field\_url\_vid2*). The output format is *thumbnail*.

`{{content.field_url_vid2}}` gives the full HTML markup, but I just want the value of the *src* attribute.

# Answer
> 1 votes
To get the YouTube video thumbnail URL in twig!
Try with:

```
{{ file_url(content.field_url_vid2.0['#media'].thumbnail.0.entity.uri.value) }}

```

---
Tags: 8
---


title: Get user ids of group members

text:
# Question
Title: Get user ids of group members
I want to get a list of all users that are members of a group.

I can get the members using getMembers():

```
$members = $group->getMembers();
  foreach ($members as $member) {
    var_dump($member);
  }

```

But this returns not User objects but GroupMembership objects:

```
object(Drupal\group\GroupMembership)#2609 (1) {
  ["groupContent":protected]=>
  object(Drupal\group\Entity\GroupContent)#2667 (28) {
    ["values":protected]=>
    array(12) {
      ["id"]=>
      array(1) {
        ["x-default"]=>
        string(1) "1"
      }
      ["type"]=>

```

So how do I get the User IDs from the GroupMembership objects? Or is there an easier way?

# Answer
Found the answer myself minutes after posting the question... so it goes :).

```
  $members = $group->getMembers();
  foreach ($members as $member) {
    $user = $member->getUser();
    $userids[] = $user->id();
  }

```
> 3 votes

---
Tags: group
---


# Question
Title: How is the hash for the files calculated?
I am taking an HTML snapshot of a node in Drupal 8 every day at 4 am. Every night a Cron job kicks off this process. I have a service that handles the entire process. Everything works for now, but I am worried that the referenced CSS and JavaScript files will break due to the filenames changed by the aggregation process.

How does Drupal 8 decide the name of the aggregated files? How can I reliably point the references to the right filenames?

# Answer
> 0 votes
The name of the aggregated files is the hash calculated from `CssCollectionOptimizer::generateHash()`.

```
protected function generateHash(array $css_group) {
  $css_data = [];
  foreach ($css_group['items'] as $css_file) {
    $css_data[] = $css_file['data'];
  }
  return hash('sha256', serialize($css_data));
}

```

The method is called by `CssCollectionOptimizer::optimize()`.

Without knowing to which group a resource is part of, and what other resources are part of that group, you cannot know the name of the file where the resources are aggregated.

There should not be any need to do that, as Drupal core takes care of removing any reference to aggregate files that don't exist anymore, and invalidate all the necessary cache bins.
The markup produced by Drupal core should never contain a reference to an aggregate file that doesn't exist anymore. If that happens, it's either a bug in Drupal core or in a third-party module.

---
Tags: 8, css-js-aggregation
---


# Question
Title: Is there a way to get the controller class from a Request object or any other service class?
My controller class holds some not-so-easy logic to receive some data from a route parameter I need in a block plugin. As this block will only be rendered on this specific route, I would like to simply get the route controller route with this block which would receive its data from the controller.

Is there any way to get the controller class from any of the services like *current\_route\_match*?
I can get the route object or the route name, but I didn't find a way to get the controller class.

# Answer
You find the controller class in a request attribute:

```
$controller = \Drupal::request()->attributes->get('_controller');

```

You need to instantiate the controller and run the code a second time. For *not-so-easy logic* it might be a better idea to refactor the code to a service which then caches the result for the second run, as @Hudri commented.

Or take a different approach. Place a custom block with a static placeholder on the page and replace it by attaching bubbleable metadata to the controller output. See Add an attribute to $variables from a Controller

Instead of a render array you can also replace the placeholder in a lazy-builder callback. This depends on the structure of the data in controller and block and how dynamic this is. At the end this is all about caching performance.
> 1 votes

---
Tags: 8, routes, page-controller
---


# Question
Title: "Process 'Apache web server' failed to start. Port 8083 didn't open"
I'm trying to install Acquia Deve Desktop 2 for my windows 10 PC. When it's finished installing and I run the program, an error pop up message shows up saying *Process 'Apache web server' failed to start. Port 8083 didn't open.*

>

I should point out that I do have XAMPP installed in my PC, but I also read in the documentation that even if you have XAMPP installed, it won't interfere.

What am I doing wrong here?

I just want my Drupal websites to load faster because on XAMPP they're pretty slow.

# Answer
Sounds like there is a port conflict or a hiccup in Acquia Dev Desktop.

* Try a reboot. This might fix an Acquia hiccup.
* Since you already have XAMPP configured and working the way you want change, I'd suggest changing the Acquia Dev Desktop port.

Here's how:

1. Open Acquia Dev Deskop
2. On the menu bar, click "Acquia Dev Desktop", then "Preferences...."
3. Click on the "Ports" tab (2nd tab)
4. Change the "Apache port" to another another number. Eg. "8087"
5. Click "OK"
6. You will need to restart the Apache server. You could click the "Stop" -\> "Start" button. I prefer to close and re-open Acquia Dev Desktop.

No need to learn/install another DEV environment or change an already setup one (XAMPP)
> 0 votes

---
Tags: installation, acquia-dev-desktop
---


title: I can't override the node template

text:
# Question
Title: I can't override the node template
I have installed Barrio Bootstrap (`8.x-4.33`) and it worked so far. But I can't override a template for a specific node type. I copied the original template into my `subtheme/template` folder and named it like suggested in the FILE NAME SUGGESTION (debug mode). E.g.: `bs-2col-bricked--node-cuba-casa-particular-full.html.twig`

This doesn't work.

Only when I name it like the original file `bs-2col-bricked.html.twig` it works.

I tried also `5.1.4`, but it's the same. Anything wrong with the FILE NAME SUGGESTIONS?

In my Bootstrap3 theme it worked.

Can anybody help, please.

# Answer
> 0 votes
My solution was to turn off the layout ('Manage display' --\> 'Select a layout' --\> 'none'). Now the debug mode FILE NAME SUGGESTIONS showed the correct suggestions. I was able to override the 'node.html.twig' in my subtheme (in my case with 'node--CONTENT-TYPE--full.html.twig')from 'themes/bootstrap\_barrio/templates/content/'.

Neither the FILE NAME SUGGESTIONS for the DS (8.x-3.9) nor the Bootstrap Layouts (8.x-5.2) were working (the one you see in debug mode, when one of those layouts is selected in 'Manage display').

Maybe there is a better way ...

---
Tags: 8, theming, nodes, bootstrap-theme
---


# Question
Title: Ajax Form Not Working in some Some Regions
I created an ajax based contact form in my module.Then I made a block view for the form. I tried putting that block to several regions. When I put the block to 'Sidebar Second' the form works as desired.But when I put the same block to 'contact' Region (custom region) , the form's ajax part does not work .

This is the code I used to print the block .

```
$contact = render(block_get_blocks_by_region('contact'));
print  $contact;

```

When I inspect the element the form-id is 'myform' as given by me . Still the ajax part is not working .

# Answer
> 0 votes
I got the solution for this . Just want to tell the answer for anyone who might come across this problem. The problem was :

I was printing it in `html.tpl.php`.

The solution is

print it on either `page.tpl.php` or `page--xxxx.tpl.php` and print it as

```
<?php
     print render($page['contact']);
 ?>

```

# Answer
> 0 votes
There are many reasons which impact Form Ajax, would suggest check once below points

1. HTML structure after rendering from Sidebar Second
2. Is there any Javascript error in your page?
3. Refer https://www.drupal.org/forum/support/module-development-and-code-questions/2019-06-19/why-is-my-ajax-not-working

---
Tags: 7, forms, ajax
---


title: Unlimited TextFields with Form API

text:
# Question
Title: Unlimited TextFields with Form API
I'm creating a Block Plugin with a form. I'm able to create the standard form with various input field types. Like so.

```
    $form['text_field_1'] = array(
        '#type'          => 'textfield',
        '#title'         => $this->t('Entry 1'),
        '#default_value' => $this->configuration['text_field_1_submit'],
        '#size'          => 60,
        '#maxlength'     => 10,
    );

    $form['text_field_2'] = array(
        '#type'          => 'textfield',
        '#title'         => $this->t('Entry 2'),
        '#default_value' => $this->configuration['text_field_2_submit'],
        '#size'          => 60,
        '#maxlength'     => 10,
    );

```

This works but I can't anticipate how many entries the user may need, so I'd like users to be able to add multiple field entries in the same way that you can in a content type field.

Is this possible?

# Answer
This is not a form API level feature, it's field/widget API.

For a custom form, you have to build it yourself with an add more button that uses #ajax to add more elements. A full code example would be too complicated for an answer, but you have to keep track of the count in $form\_state, on pressing of the button increaes it, rebuild the form and then return the new elements.

See https://api.drupal.org/api/drupal/core%21core.api.php/group/ajax/8.2.x for more documentation, a quick tutorial that I found: https://www.sitepoint.com/using-ajax-forms-drupal-8/
> 5 votes

# Answer
Here's the example from the examples module found here

```
use Drupal\Core\Form\FormStateInterface;

/**
 * Implements the ajax demo form controller.
 *
 * This example demonstrates using ajax callbacks to add people's names to a
 * list of picnic attendees.
 *
 * @see \Drupal\Core\Form\FormBase
 * @see \Drupal\Core\Form\ConfigFormBase
 */
class AjaxAddMore extends DemoBase {

  /**
   * Form with 'add more' and 'remove' buttons.
   *
   * This example shows a button to "add more" - add another textfield, and
   * the corresponding "remove" button.
   */
  public function buildForm(array $form, FormStateInterface $form_state) {
    $form['description'] = [
      '#type' => 'item',
      '#markup' => $this->t('This example shows an add-more and a remove-last button.'),
    ];

    // Gather the number of names in the form already.
    $num_names = $form_state->get('num_names');
    // We have to ensure that there is at least one name field.
    if ($num_names === NULL) {
      $name_field = $form_state->set('num_names', 1);
      $num_names = 1;
    }

    $form['#tree'] = TRUE;
    $form['names_fieldset'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('People coming to picnic'),
      '#prefix' => '<div id="names-fieldset-wrapper">',
      '#suffix' => '</div>',
    ];

    for ($i = 0; $i < $num_names; $i++) {
      $form['names_fieldset']['name'][$i] = [
        '#type' => 'textfield',
        '#title' => $this->t('Name'),
      ];
    }

    $form['names_fieldset']['actions'] = [
      '#type' => 'actions',
    ];
    $form['names_fieldset']['actions']['add_name'] = [
      '#type' => 'submit',
      '#value' => $this->t('Add one more'),
      '#submit' => ['::addOne'],
      '#ajax' => [
        'callback' => '::addmoreCallback',
        'wrapper' => 'names-fieldset-wrapper',
      ],
    ];
    // If there is more than one name, add the remove button.
    if ($num_names > 1) {
      $form['names_fieldset']['actions']['remove_name'] = [
        '#type' => 'submit',
        '#value' => $this->t('Remove one'),
        '#submit' => ['::removeCallback'],
        '#ajax' => [
          'callback' => '::addmoreCallback',
          'wrapper' => 'names-fieldset-wrapper',
        ],
      ];
    }
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Submit'),
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'form_api_example_ajax_addmore';
  }

  /**
   * Callback for both ajax-enabled buttons.
   *
   * Selects and returns the fieldset with the names in it.
   */
  public function addmoreCallback(array &$form, FormStateInterface $form_state) {
    return $form['names_fieldset'];
  }

  /**
   * Submit handler for the "add-one-more" button.
   *
   * Increments the max counter and causes a rebuild.
   */
  public function addOne(array &$form, FormStateInterface $form_state) {
    $name_field = $form_state->get('num_names');
    $add_button = $name_field + 1;
    $form_state->set('num_names', $add_button);
    // Since our buildForm() method relies on the value of 'num_names' to
    // generate 'name' form elements, we have to tell the form to rebuild. If we
    // don't do this, the form builder will not call buildForm().
    $form_state->setRebuild();
  }

  /**
   * Submit handler for the "remove one" button.
   *
   * Decrements the max counter and causes a form rebuild.
   */
  public function removeCallback(array &$form, FormStateInterface $form_state) {
    $name_field = $form_state->get('num_names');
    if ($name_field > 1) {
      $remove_button = $name_field - 1;
      $form_state->set('num_names', $remove_button);
    }
    // Since our buildForm() method relies on the value of 'num_names' to
    // generate 'name' form elements, we have to tell the form to rebuild. If we
    // don't do this, the form builder will not call buildForm().
    $form_state->setRebuild();
  }

  /**
   * Final submit handler.
   *
   * Reports what values were finally set.
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $values = $form_state->getValue(['names_fieldset', 'name']);

    $output = $this->t('These people are coming to the picnic: @names', [
      '@names' => implode(', ', $values),
    ]
    );
    $this->messenger()->addMessage($output);
  }

}

```
> 3 votes

# Answer
I found this tutorial for Drupal 7 useful from Rapid Development Group. Their code below.

```
function custom_registration_form($form, &$form_state) {
  $form_state['storage']['participants'] =
    isset($form_state['storage']['participants']) ? $form_state['storage']['participants'] : 0;

  $form['name'] = array(
    '#title' => t('Name'),
    '#type' => 'textfield',
  );

  $form['participants'] = array(
    '#type' => 'container',
    '#tree' => TRUE,
    '#prefix' => '<div id="participants">',
    '#suffix' => '</div>',
  );

  if ($form_state['storage']['participants']) {
    for ($i = 1; $i <= $form_state['storage']['participants']; $i++) {
      $form['participants'][$i] = array(
        '#type' => 'fieldset',
        '#tree' => TRUE,
      );

      $form['participants'][$i]['name'] = array(
        '#title' => t('Name'),
        '#type' => 'textfield',
      );
    }
  }

  $form['add_participant'] = array(
    '#type' => 'button',
    '#value' => t('Add A Participant'),
    '#href' => '',
    '#ajax' => array(
    'callback' => 'custom_registration_ajax_add_participant',
    'wrapper' => 'participants',
   ),
  );

  $form['submit'] = array(
    '#value' => t('Register'),
    '#type' => 'submit',
  );

  $form_state['storage']['participants']++;

  return $form;
}

function custom_registration_ajax_add_participant($form, $form_state) {
  return $form['participants'];
}

```
> 1 votes

# Answer
For those wanting to add multiple text field values in Drupal 8/9 theme settings (via - `hook_form_system_theme_settings_alter()` here is some code.

Based off a combination of:

```
use Drupal\Core\Form\FormStateInterface;

/**
 * Implements hook_form_system_theme_settings_alter().
 */
function mytheme_form_system_theme_settings_alter(&$form, FormStateInterface $form_state) {
  // Some existing field set.
  $form['my_fieldset'] = [
    '#type' => 'details',
    '#title' => t('My existing fieldset'),
    '#description' => t('My existing description'),
  ];
  // My item settings.
  $form['my_fieldset']['myitem_settings'] = [
    '#type' => 'details',
    '#title' => t('My item settings'),
    '#description' => t('My description'),
  ];
  // Gather the items list in the form state already.
  // Key 'myitems' must be same as array key.
  $form_state_values = $form_state->getValues();
  $myitems = isset($form_state_values['myitems']) ? $form_state_values['myitems'] : NULL;
  // If NULL, try theme settings.
  if ($myitems === NULL) {
    $myitems = theme_get_setting('myitems');
  }
  // We have to ensure that there is at least one item.
  if ($myitems === NULL) {
    $myitems = [''];
  }
  $form['my_fieldset']['myitem_settings']['myitems_fieldset'] = [
    '#type' => 'fieldset',
    '#title' => t('My item list'),
    '#prefix' => '<div id="myitems-fieldset-wrapper">',
    '#suffix' => '</div>',
  ];
  $form['my_fieldset']['myitem_settings']['myitems_fieldset']['myitems'] = [
    // Required for correct inputs to be generated.
    '#tree' => TRUE,
  ];
  foreach ($myitems as $key => $html_cache_headers_url) {
    $form['my_fieldset']['myitem_settings']['myitems_fieldset']['myitems'][$key] = [
      '#type' => 'textfield',
      '#title' => t('A single item'),
      '#description' => t('My single item description.'),
      // Key 'myitems' must be same as parent key.
      '#default_value' => theme_get_setting('myitems.' . $key),
    ];
  }
  $form['my_fieldset']['myitem_settings']['myitems_fieldset']['actions'] = [
    '#type' => 'actions',
  ];
  $form['my_fieldset']['myitem_settings']['myitems_fieldset']['actions']['add_item'] = [
    '#type' => 'submit',
    '#value' => t('Add one more'),
    '#submit' => ['__mytheme_form_system_theme_settings_alter__add_one_item'],
    '#ajax' => [
      'callback' => '__mytheme_form_system_theme_settings_alter__add_more_callback',
      'wrapper' => 'myitems-fieldset-wrapper',
    ],
  ];
  // If there is more than one item, add the remove button.
  if (count($myitems) > 1) {
    $form['my_fieldset']['myitem_settings']['myitems_fieldset']['actions']['remove_item'] = [
      '#type' => 'submit',
      '#value' => t('Remove one'),
      '#submit' => ['__mytheme_form_system_theme_settings_alter__remove_callback'],
      '#ajax' => [
        'callback' => '__mytheme_form_system_theme_settings_alter__add_more_callback',
        'wrapper' => 'myitems-fieldset-wrapper',
      ],
    ];
  }
}

/**
 * Submit handler for the "add-one-more" button.
 *
 * Increments the amount of items and causes a rebuild.
 */
function __mytheme_form_system_theme_settings_alter__add_one_item(&$form, FormStateInterface $form_state) {
  $form_state_values = &$form_state->getValues();
  $paths_field = isset($form_state_values['myitems']) ? $form_state_values['myitems'] : [];
  $paths_field[] = '';
  $form_state_values['myitems'] = $paths_field;
  // Since our form() method relies on the value of 'myitems'
  // to generate 'item' form elements, we have to tell the form to rebuild.
  // If we don't do this, the form builder will not call buildForm().
  $form_state->setRebuild();
}

/**
 * Callback for both ajax-enabled buttons.
 *
 * Selects and returns the fieldset with the paths in it.
 */
function __mytheme_form_system_theme_settings_alter__add_more_callback(&$form, FormStateInterface $form_state) {
  return $form['my_fieldset']['myitem_settings']['myitems_fieldset'];
}

/**
 * Submit handler for the "remove one" button.
 *
 * Decrements the amount of items from the bottom and causes a form rebuild.
 */
function __mytheme_form_system_theme_settings_alter__remove_callback(&$form, FormStateInterface $form_state) {
  $form_state_values = &$form_state->getValues();
  $paths_field = isset($form_state_values['myitems']) ? $form_state_values['myitems'] : [];
  if ($paths_field > 1) {
    array_pop($paths_field);
    $form_state_values['myitems'] = $paths_field;
  }
  // Since our buildForm() method relies on the value of
  // 'myitems' to generate 'item' form elements, we have to
  // tell the form to rebuild. If we don't do this, the form builder will
  // not call buildForm().
  $form_state->setRebuild();
}

```
> 1 votes

---
Tags: forms, 8
---


title: How can I update core to 8.9.10?

text:
# Question
Title: How can I update core to 8.9.10?
I'm trying to apply the security update for core by updating it to 8.9.10 with the following command:

```
composer update drupal/core

```

But this only brings back the following notice:

> Nothing to install or update

What am I doing wrong? How can I update core to 8.9.10?

# Answer
Thanks to @leymannx

```
composer update drupal/core drupal/core-dev --with-dependencies

```

did it
> 6 votes

---
Tags: 8, composer
---


# Question
Title: Better code to output a pdf downloaded by the browser
In a submit function of a custom form, I would like to output a pdf which can be downloaded by the user/browser when clicking on 'Get PDF'.

The following code is doing the job **only once**, because after clicking on the 'Get PDF' button, all the buttons of the form does not work anymore. Clicking on any of them doesn't produce any effect.

Any Idea?

```
  static public function submitPdf(array &$form, FormStateInterface $form_state) {
    if ($pdf_content = my_function_to_output_a_pdf_as_string()) {
      $response = new Response($pdf_content);
      $disposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, 'my_pdf.pdf');
      $response->headers->set('Content-type', "application/pdf");
      $response->headers->set('Content-Disposition', $disposition);
      //$response->headers->set('Content-Transfer-Encoding', 'binary');
      $response->headers->set('Content-length', strlen($pdf_content));
      $form_state->setResponse($response);
      //Thanks to kiamlaluno, it is working slighty better if I remove the following line (setRebuild())
      //$form_state->setRebuild(TRUE);
    }
  }

```

**Edit to add in order to provide more context**: The form is made of +/- 30 numeric fields and the user can play with them to produce some calculated results. If he wants, he can click at any time on the "get pdf" button to generate a pdf which will contains all his inputs and the calculated result. In other words, he can fill the form-\>get the pdf-\>continue to fill-\>get another pdf-\> etc

# Answer
Provide a controller to download the PDF as discussed in the comments:

https://stefvanlooveren.me/blog/serve-pdf-download-controller-drupal-8

> ```
> <?php
> namespace Drupal\MYMODULE\Controller;
>
> use Drupal\Core\Controller\ControllerBase;
> use Symfony\Component\HttpFoundation\BinaryFileResponse;
>
> /**
>  * Class PdfGeneratorController.
>  */
> class PdfGeneratorController extends ControllerBase {
>
>   public function Render($uuid) {
>
>     // In my case, I render a file by UUID
>     // This actually does not matter too much here
>     // String below contains the url of the file
>     $uri = 'private://'.$uuid.'.pdf';
>
>     $headers = array(
>       'Content-Type'     => 'application/pdf',
>       'Content-Disposition' => 'attachment;filename="download"');
>
>     return new BinaryFileResponse($uri, 200, $headers, true);
>   }
> }
>
> ```

Then add to the button link the HTML5 Download Attribute to download the file in the background without redirecting.

See https://stackoverflow.com/questions/20830309/download-file-using-an-ajax-request

If the PDF file is created dynamically this can be integrated in a Drupal Ajax form workflow by generating the file on user request and providing the button link to the custom built PDF file via Ajax.
> 6 votes

---
Tags: 8, forms
---


# Question
Title: How to set role on the registration form programmatically
I'm trying to create multiple registration forms with a role assigned to each.

It seems that my default value for the role is not keeped, but it works with other fields

Here is my code

```
$form = $this->entityFormBuilder->getForm($account, 'mycustomdisplay');
$form['account']['roles']['#default_value'][] = 'mycustomrole';

```

Thank you.

# Answer
> 1 votes
You need to do this in a form alter hook, not after the form has already been built.

```
function module_form_user_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($condition) {
    $form['account']['roles']['#default_value'][] = 'mycustomrole';
  }
}

```

---
Tags: users, forms
---


# Question
Title: File structure of libraries folder and detection of module external plugins
The module CKeditor anchor link require a CKEditor plugin. Can this plugin be placed in subfolder of the /libraries folder or does it have imperatively to be placed at the root of /libraries ?

More generally, does drupal parse recursively the libraries folder when intenting to detect external plugins ?

# Answer
> 1 votes
The libraries folder is no longer managed by Drupal. The project Libraries doing this jobs in older Drupal versions seems to be deprecated in favor of a composer based concept. Modules still using the libraries folder use their own logic and you have to follow their instructions on the project page or README.

---
Tags: 8, plugins
---


# Question
Title: How to have a field displayed depending on user's role in Views?
I use Views module to display the content of a custom entity with Page view (not Block view).
I'd like to have one field displayed only if the user has a certain role.
What is the best way to do that?

# Answer
> 0 votes
If this is a custom entity you may consider overriding the checkFieldAccess method of Drupal\Core\Entity\EntityAccessControlHandler.

Then assign your own handler as handlers/access in @ContentEntityType.

But it's only me who prefers being in coding hell instead of configuration hell :-)

# Answer
> 0 votes
If it's a custom Entity maybe this module will works for you

https://www.drupal.org/project/field\_permissions

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

Thanks!.

---
Tags: views, 8
---


title: Custom block disable caching?

text:
# Question
Title: Custom block disable caching?
I've created a custom module to show On This Days in a block but they are not changing each day until I flush the caches.

I call the entity:

```
public function build() {
    $query = \Drupal::entityQuery('node');
    $query->condition('status', 1);
    $query->condition('type', 'on_this_day');
    $query->condition('field_filter_date', '-' . date("m-d"), 'CONTAINS');
    $entity_ids = $query->execute();

```

...

and then return from the build function like this:

```
return array(
        '#markup' => $content,
        '#cache' => array(
            'max-age' => 0,
        ),

```

Any ideas? I'm thinking entity cache or something but I'm quite new to this and not too sure

# Answer
The way to invalid the Cache in a Block is with

```
  /**
   * {@inheritdoc}
   */
  public function getCacheMaxAge() {
    return 0;
  }

```

This comes from BlockBase
> 0 votes

---
Tags: 8, entities, blocks, caching
---


title: Install Issues with OS and Composer 2

text:
# Question
Title: Install Issues with OS and Composer 2
I am stuck on trying to do an OS install and following the install guide found here.

When attempting to use Composer2 to fetch I get the following errors.

```
  Problem 1
    - drupal-composer/drupal-scaffold is locked to version 2.6.1 and an update of this package was not requested.
    - drupal-composer/drupal-scaffold 2.6.1 requires composer-plugin-api ^1.0.0 -> found composer-plugin-api[2.0.0] but it does not match the constraint.
  Problem 2
    - oomphinc/composer-installers-extender is locked to version v1.1.2 and an update of this package was not requested.    - oomphinc/composer-installers-extender v1.1.2 requires composer-plugin-api ^1.0 -> found composer-plugin-api[2.0.0] but it does not match the constraint.
  Problem 3
    - drupal-composer/drupal-scaffold 2.6.1 requires composer-plugin-api ^1.0.0 -> found composer-plugin-api[2.0.0] but it does not match the constraint.
    - goalgorilla/open_social 9.4.0 requires drupal-composer/drupal-scaffold ^2.5.0 -> satisfiable by drupal-composer/drupal-scaffold[2.6.1].
    - goalgorilla/open_social is locked to version 9.4.0 and an update of this package was not requested.

You are using Composer 2, which some of your plugins seem to be incompatible with. Make sure you update your plugins or report a plugin-issue to ask them to support Composer 2.

```

In reading though several bug reports and various different posts I see this isn't a uncommon problem to have due to the last update of composer from V1 to V2.

It was recommended in a bug report that the submitter downgrade Composer to V1 so I did that and got a different set of results as follows.

```
    PS C:\> composer self-update 1.4.1
Upgrading to version 1.4.1 (stable channel).

Unable to write "C:\ProgramData\ComposerSetup\bin\composer.phar". Access is denied.
Complete this operation with Administrator privileges [Y,n]? y
Operation succeeded.
Use composer self-update --rollback to return to version 2.0.7
PS C:\> composer create-project goalgorilla/social_template:dev-master DIR --no-interaction
Warning from https://packagist.org: You are using an outdated version of Composer. Composer 2.0 is now available and you should upgrade. See https://getcomposer.org/2
Installing goalgorilla/social_template (dev-master dd01e6827fb19f29b3245fa893ac1f5911c72200)
  - Installing goalgorilla/social_template (dev-master master): Cloning master from cache
Created project in DIR
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file

  [ErrorException]
  "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"

```

The only thing I can find on that was on stack which basically said, yeah no way that's going to work.

Its my understanding that the next release will address the Composer2 changes required but is anyone aware of detailed documentation that would help me presently in navigating the scaffold issues? I am seeing all sorts of posts about patches and work arounds where what is being described is way way over my head.

I am way out of my league here in working this out but stubborn enough to learn with the right glints of information.

# Answer
I can see in your output that you are trying to update to a specific version of Composer and it also prompting an "Access Denied" shortly after:

```
PS C:\> composer self-update 1.4.1
Upgrading to version 1.4.1 (stable channel).

Unable to write "C:\ProgramData\ComposerSetup\bin\composer.phar". Access is denied.

```

So it looks like that command already failed. You may have to manually install Composer on your machine if you run in such permission errors and move the `composer.phar` executable to the appropriate directory.

## PHP 7.3

Please also see this GitHub issue for the `ErrorException` that you are facing: PHP 7.3 breaks composer with continue/targeting error (solution: downgrade to 7.2) #7783

> \[ErrorException\]
> "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"?

In that issue it states that you will need at least Composer version `v1.6.0` or up to be compatible with PHP 7.3.

## Composer v1

Is there any reason why you need an old `v1.4.1` version? If not then for now I suggest you rollback to the latest stable version of Composer `v1` as per @Kevin's comment, which you can do by running:

```
composer self-update --1

```

Which should currently give you Composer v1.10.17, or again if that fails download the latest v1 manually.
> 2 votes

---
Tags: installation
---


# Question
Title: Programmatically get View Custom Image filed url
I have:

```
$view = Views::getView('ads');

$view->setDisplay('block_9');

$view->execute();
$view_result = $view->result;

foreach ($view_result as $data) {
  $entity = $data->_entity;
  kint($entity->get('field_image_ads')->getValue());

}

```

A screenshot of Output Kint:

But I want the image URL also. Thanks.

# Answer
> 1 votes
Your `field_image_ads` looks like an entity reference field, so try this:

```
$entity->field_image_ads->entity->getFileUri();

```

---
Tags: views
---


title: Unable to edit checkout flow settings

text:
# Question
Title: Unable to edit checkout flow settings
When attempting to configure Checkout Flow instances (eg, `/admin/commerce/config/checkout-flows/manage/default`) clicking on the 'Settings' (cog) icon for any of the panes generates an '*AssertionError*' and the settings cannot be altered.

```
AssertionError: The container was serialized. in assert() (line 28 of /app/web/core/lib/Drupal/Core/DependencyInjection/Container.php)
#0 /app/web/core/lib/Drupal/Core/DependencyInjection/Container.php(28): assert(false, 'The container w...')
#1 [internal function]: Drupal\Core\DependencyInjection\Container->__sleep()
#2 /app/web/core/lib/Drupal/Component/Serialization/PhpSerialize.php(14): serialize(Array)
#3 /app/web/core/lib/Drupal/Core/KeyValueStore/DatabaseStorageExpirable.php(80): Drupal\Component\Serialization\PhpSerialize::encode(Array)
#4 /app/web/core/lib/Drupal/Core/Form/FormCache.php(197): Drupal\Core\KeyValueStore\DatabaseStorageExpirable->setWithExpire('form-GQXUq0kLih...', Array, 21600)
#5 /app/web/core/lib/Drupal/Core/Form/FormBuilder.php(459): Drupal\Core\Form\FormCache->setCache('form-GQXUq0kLih...', Array, Object(Drupal\Core\Form\FormState))
#6 /app/web/core/lib/Drupal/Core/Form/FormBuilder.php(437): Drupal\Core\Form\FormBuilder->setCache('form-GQXUq0kLih...', Array, Object(Drupal\Core\Form\FormState))
#7 /app/web/core/lib/Drupal/Core/Form/FormBuilder.php(629): Drupal\Core\Form\FormBuilder->rebuildForm('commerce_checko...', Object(Drupal\Core\Form\FormState), Array)
#8 /app/web/core/lib/Drupal/Core/Form/FormBuilder.php(321): Drupal\Core\Form\FormBuilder->processForm('commerce_checko...', Array, Object(Drupal\Core\Form\FormState))
#9 /app/web/core/lib/Drupal/Core/Controller/FormController.php(91): Drupal\Core\Form\FormBuilder->buildForm(Object(Drupal\commerce_checkout\Form\CheckoutFlowForm), Object(Drupal\Core\Form\FormState))
#10 [internal function]: Drupal\Core\Controller\FormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch))
#11 /app/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array)
#12 /app/web/core/lib/Drupal/Core/Render/Renderer.php(573): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#13 /app/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#14 /app/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)
#15 /app/vendor/symfony/http-kernel/HttpKernel.php(151): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#16 /app/vendor/symfony/http-kernel/HttpKernel.php(68): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#17 /app/web/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#18 /app/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#19 /app/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#20 /app/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#21 /app/web/core/modules/ban/src/BanMiddleware.php(50): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#22 /app/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\ban\BanMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#23 /app/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(52): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#24 /app/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#25 /app/web/core/lib/Drupal/Core/DrupalKernel.php(708): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#26 /app/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#27 {main}

```

This behaviour is not seen on other Drupal forms across the site, including other pieces of Commerce, so the assumption is that the cause is the Checkout module. Where similar errors have been reported elsewhere in Drupal, it's usually down to the Controller class not using `DependencySerializationTrait`, but this seems to be implemented in */commerce/modules/checkout/src/Controller/CheckoutController.php*

The bad news is that I cannot replicate it: rolled another quick site using just Drupal 8.9.9 and Commerce 8.x-2.21 and the expected behaviour is working correctly.

## Proposed resolution

I've no idea what's causing this, and whether it is a config issue, or an issue with the code. As with every other Drupal site, there are lots of other modules, but it's knowing where to start...

# Answer
> 1 votes
In my case it was due to a problem with mail\_login module.

Patch at https://www.drupal.org/project/mail\_login/issues/3161437

Seems to be a recurring problem with modules that are missing DependencySerializationTrait

---
Tags: commerce
---


# Question
Title: How do I spawn additional instances with the same configuration?
I have the following scenario:

I will develop an application based on Drupal. Everything will be developed on a local instance. Composer files, configuration and so on will be kept in a `git` repository. The repository will be hosted on GitLab. I will use the CI/CD features over there. I will need one test instance.

The project starts with one production instance. In the future, there will be additional production instances. They all should have exactly the same configuration, but different content.

I already did something like this, where I copied the initial database from my local install to my test and production server. Afterwards, my CI/CD scripts could load the configuration from `git` to the different instances. But there, I only hat one production server.

If I remember correctly, configuration is bound to an ID of the initial database. So, I can't just set up a new instance and load the configuration from the old one.

Since they all will have exactly the same configuration, I would love to have a `develop` branch for delivering to the test server and a `master` branch to deliver to all production servers. If there are better solutions, I'm also open for them.

What would be the best workflow to add additional instances in the future that use the same config and can receive updates from the same CI/CD?

Would this workflow be completely incompatible in the case that, somewhere in the future, one instance would start getting additional configuration?

# Answer
> 0 votes
> Would this workflow be completely incompatible in the case that, somewhere in the future, one instance would start getting additional configuration?

If having one instance with divergent configuration is a concern, it is probably worth considering setting it all up as a distribution.

While rolling your own distribution may be overkill, this provides the most "future-proofing" long term because you will have a base configuration in the distribution that can be overridden on a per-site basis if it becomes necessary.

Rough documentation on configuration in distributions

With a distribution, in addition to default configuration, you can even include default content.

---
Tags: version-control, 9, staging
---


# Question
Title: how to migrate multiple taxonomy terms with entity lookup plugin
Im using the code below to migrate a taxonomy term with multiple values and I get this error below. is there a way to migrate multiple taxonomy terms with this plugin? :

> InvalidArgumentException: Placeholders must have a trailing \[\] if they are to be expanded with an array of values. in \[error\] /var/www/html/docroot/core/lib/Drupal/Core/Database/Connection.php:744

```
field_states_operating_in:
    - plugin: entity_lookup
      source: field_states_operating_in
      entity_type: taxonomy_term
      value_key: name
      bundle_key: vid
      bundle: states_operating

```

# Answer
> 4 votes
The field that you're migrating has multiple values and you're trying to run entity\_lookup as though it has only one. I think you just need to make sure you're iterating over the values with the sub\_process plugin.

Using this issue post as a reference, along with the docs for entity\_lookup:

```
field_farbzuordnung:
    plugin: sub_process
    source: field_farbe
    process:
        target_id:
        plugin: entity_generate
        source: value
        value_key: name
        bundle_key: vid
        bundle: alle_farben
        entity_type: taxonomy_term
        ignore_case: true

```

...I think you'd want to do something like

```
field_states_operating_in:
    -
      plugin: sub_process
      source: field_states_operating_in
      process:
        target_id:
          plugin: entity_lookup
          source: target_id
          entity_type: taxonomy_term
          bundle: states_operating
          bundle_key: vid
          value_key: target_id

```

I'm not entirely sure that the source and value\_key are correct but I think this should get you most of the way there.

---
Tags: migrations
---


# Question
Title: Why is the test runner not picking up tests for a contrib module?
I recently added tests to Cache Register, but the test runner on drupal.org doesn't seem to be picking them up. The tests are all located in tests/src/Kernel (repo) but aren't queuing up in the issue queue for either patches or merge requests. Am I missing something?

EDIT: Current answer references the namespace of the base test class, but that's no longer relevant. I refactored that Base class into a testing Trait instead and made sure that the remaining "real" tests use the proper namespace. Everything runs locally but still not getting picked up by the runner as far as I can tell.

# Answer
> 2 votes
If I look at https://www.drupal.org/project/cache\_register/issues/3184391 , there is no option for me to test/retest a patch.

That tells me that you don't have testing configured for your project. To do that, you need to go to https://www.drupal.org/node/3183102/qa and choose "Add test / retest", then configure a test with the Drupal version, PHP version, database type/version that you want and choose when the test gets run. Once you submit that new test, it should immediately run. If you select "issue testing default" when you configure the test, then that configuration will run for Needs Review patches in your issue queue, and that will be the configuration that will run if someone in the issue queue manually triggers a test.

I don't see anything obviously wrong with the tests themselves, but it is clear that you don't have tests configured to run so it doesn't matter if the tests are working or not ...

---
Tags: testing, community-official-site
---


# Question
Title: Display price on Views for product variation
I'm confused, how to display on Views just one price for product with variations? I have product with 2 variation, and both prices are displayed, like: Price: 1-Price for 1-Variation-Product , Price: 2-Price for 2-Variation-Product

I mean the created from me some custom view-page, like "/all-products" (like some catalog page) where are displayed all of products or goods with their prices. And for the products with variations I see, that there will be displayed all of prices of this product.

In the Settings of View-Page ("/all-products") I have in **Format section**: "*Show:Fields | Settings*".

In **RELATIONSHIPS**: *Variations: Product variation*

*(Variations: Product variation) Product: Product*

And in **Fields** I have: *(Variations: Product variation) Product variation relationship: Price*

where in the Setting I have: "*Use entity field rendering*"

There are no Setting to handle multiple values.

If I check out "*Use entity field rendering*" then will be shown some settings for handling of multiple values, but in this case it will be no price displayed on view-page (/all-products), because the prices are rendering from product entity, as I understand.

So, this is the problem

In addition: the product with variation has all the same price, not different prices for different variation.

What is teh best way to handle it?

I have **Drupal 9**, **Commerce 2**

Thanks

# Answer
> 1 votes
I think I found a solution, in "**Fields**" just instead

"*(Variations: Product variation) Product variation relationship: Price*"

need to use:

"*Product datasource: Variations*", and there are some settings to handle multiple values.

In "**Formatter**" need to set "*Rendered entry*", instead default "*Label*"

# Answer
> 0 votes
It depends on how your view is configured, but here is a basic setup that will only show one price.

Create a view of **Products** with the **Default** view mode.

Then configure the **Default** view mode at `/admin/commerce/config/product-types/MY_PRODUCT_TYPE/edit/display`.

For **Variations**, you can change the **Format** to **Add to cart form**, which will show a dropdown for selecting the variations and the price of the current variation only. You can check out the other options too; one of them may be better for your use case.

---
Tags: views, commerce
---


# Question
Title: How can I use Drush in a project installed with Composer?
I have installed Drupal 8.5 using `composer create-project drupal-composer/drupal-project:8.x-dev my_site_name_dir --stability dev --no-interaction`.

This command installs many files. I found drush-files in the root and the file vendor/drush. It looks like Drush is available, but I have no idea how I can run drush. Trying command like "drush cr" was not successful. I get the following error.

> -bash: drush: command not found.

I don't want to be able to use Drush from everywhere.

How can I use Drush only from my\_site\_name\_dir?

# Answer
Basically, you need to follow steps on http://docs.drush.org/en/master/install and get Drush installed globally. It's possible to invoke Drush installed within Composer context together with Drupal 8 indicating the exact path something like `/path-to-website-home/vendor/bin/drush`. However, if you want Drush available anywhere in the system then get Drush Launcher installed.

Here is direct quote from http://docs.drush.org/en/master/install:

> Optional. To be able to call drush from anywhere, install the Drush Launcher. That is a small program which listens on your $PATH and hands control to a site-local Drush that is in the /vendor directory of your Composer project. If you skip this step, run Drush from Drupal root via ../vendor/bin/drush. In that case Drush's bash integration and custom prompt won't work.

You might also want to read How to get Drush to work with Composer and What is the right way of installing Drupal 8?
> 5 votes

# Answer
I got it by myself. There is no need to install drush globally. The composer command
composer require drush/drush
install all the necessary files for using drush. To make Drush run you need an alias to this file in your .bash\_profile (mac users). I only add in the .bash\_profile alias drush='vendor/drush/drush/drush'
And Drush works!
And there is also no need to have trouble with different drupal versions, because composer install the version you need.
> 3 votes

# Answer
Just an addition for windows users.

lesley n. answer above works just fine for Windows users as well.

Just edit `C:\Users\your_username\.bash_profile` and add one line:

```
alias drush='vendor/bin/drush'

```

Restart your Git Bash, go to your drupal site home folder and try:

```
drush version

```

It should work

I was able to make composer-installed Drupal Console to work with only "drupal" command also with one line addition to `C:\Users\your_username\.bash_profile` as well:

```
alias drupal='vendor/bin/drupal'

```

Restart your Git Bash, go to your drupal site home folder and try:

```
drupal --version

```

This should work as well.

These two solutions are much easier for me than installing Drush Launcher and Console Launcher on my Windows platform.

Please, note that due to the relative alias paths this only works when you call `drush` and `drupal` commands from inside your project root.
> 2 votes

# Answer
> Drush only supports one install method. It requires that your Drupal site be built with Composer and Drush be listed as a dependency.

That means after you added Drush via `composer require drush/drush` to your project you then call Drush via `vendor/bin/drush cr` or `vendor/drush/drush/drush cr` from inside the project root.

If you are working on many Drupal (7, 8 and 8+) projects or if you are simply preferring to call a global `drush` command like you are used to you can install the Drush Launcher and then only have to type `drush cr` again from anywhere inside the project. The Drush Launcher simply picks up the local Drush in each project. Which is especially nice when you have projects requiring different versions of Drush.

See the new docs for more info and for a Drupal Compatibility chart.
> 0 votes

---
Tags: 8, drush, composer
---


# Question
Title: How to get the input value with preprocess from a Fulltext Search Filter exposed form
For **Drupal 7** I found a workaround to a similar situation here, when combining Core search block forms and search api contextual filters. This "workaround" won't work when using Search API, if you don't want the Contextual Filter in your view.

**My current setup:**
I am using Search API, with a database server, and displaying the results with a Views page. I am using **Search: Fulltext search (exposed)** and **Exposed form in block:Yes** for the search block form.

**What I am trying to achive:**
I would like to put *what was searched for* in the Header of the view, and also at the top of No Results Behavior like this:

"*You searched for **bananas***"

**The problem:**
When using **Search: Fulltext search (exposed)**, the replacement patterns for the input value are not available in the **Global Text Area**. They are only available by adding a Fulltext Search **Contextual Filter**. There is an issue for this with a patch for Drupal 8 here.

**My question:**
Is there a `views_pre_render` or some other hook that can be used for the Header or No Results region to output the value that was input into the **Search: Fulltext search (exposed)** form?

There is a dev module to create a token, but it only works for the Results Summary.

# Answer
Maybe not exactly what you're asking for, but the one way to approach this is to use `hook_preprocess_views_view(&$variables)` and modify the contents of the header, or add a variable containing the string you want and then it in above/below the header in a views-view.tpl.php template override. If the search string isn't available through `$variables`, you can probably grab it from the url since it's likely included as a query string.

To get the query string from the url and add it to the template variables you'd do something like the following in your module or theme:

```
/**
 * Implements hook_preprocess_hook()
 */
function my_module_preprocess_views_view(&$variables) {
  // Get the query string from the url.
  // it will be on something like ?the_search_string=big+banana.
  $search_string_raw = $_GET['the_search_string'];

  // Decode the url to remove special chars
  $search_string_decoded = urldecode($search_string_raw);

  // Add it to $variables so it's available in views-view.tpl.php
  $variables['search_string'] = $search_string_decoded;
}

```

This will make the search\_string available in views-view.tpl.php. You can then print it in there with

```
<?php if($search_string): ?>
  <?php print $search_string ?>
<?php endif; ?>

// or

<?php

if($search_string) {
  print $search_string;
}

```

To clarify how hook\_preprocess\_hook works -- the first "hook" is your module name, and the second is the name of the template that you're targeting. Since we are targeting views-view.tpl.php, we use hook\_preprocess\_views\_view.

In general, the easiest way to get started inspecting php variables is to dump them to the screen. For Drupal 7, I'd recommend installing https://www.drupal.org/project/kint on your site. This will let you print variables to the screen to help you dig into their values and see what's in there. You'd do like:

```
function my_module_preprocess_views_view(&$variables) {
  kint($variables);
  // or
  kpr($variables['header'])
}

```

Then you can see what's actually inside of `$variables` and grab/modify the values in there.
> 1 votes

# Answer
I am accepting the above answer, but adding this as it's helpful for anyone trying to accomplish the same type of thing. This preprocess function is for the general `views-view.tpl.php` file which will affect **all** views.

```
  function MY_MODULE_preprocess_views_view(&$variables) {
  // Get the query string from the url.
  // it will be on something like ?THE_SEARCH_STRING=big+banana.
  $search_string_raw = $_GET['THE_SEARCH_STRING'];

  // Decode the url to remove special chars
  $search_string_decoded = urldecode($search_string_raw);

  // Add it to $variables so it's available in views-view.tpl.php
  $variables['search_string'] = $search_string_decoded;
}

```

Since this is trying to get `THE_SEARCH_STRING` on all views, this will result in an undefined index messages in the log on all view pages **except** the one where the search string exists.

I found if you want to write a preprocess function for a specific view, the preprocess function would look like this:
`function MY_MODULE_preprocess_views_view__MY_VIEW__page(&$variables)`

There is a problem though... in Drupal 7 there is an issue where Specific preprocess functions for theme hook suggestions are not invoked. There is a workaround for it here which should allow you to write view specific preprocess functions for any views\_view.tpl.php templates:

```
function MY_MODULE_preprocess_views_view(&$vars) {
  if (isset($vars['view']->name)) {
    $function = 'MY_MODULE_preprocess_views_view__' . $vars['view']->name . '__' . $vars['view']->current_display;

    if (function_exists($function)) {
      $function($vars);
    }
  }
}

```

I wonder if the set of variables in the initial answer could be simply parented under some thing like:
`if ($view->name == 'my_view_name' && $view->current_display == 'my_display_id')`
> 0 votes

---
Tags: 7, views, hooks
---


# Question
Title: How to pass different parameters to the same form function based on different urls
I have a custom model containing two paths. Each path goes to the same function. I wanna to send to each page arguments specific parameter and reception on the function then pass the hidden value to submit function.

```
  $items['parkingcalculator_normal'] = array(
    'title' => t('Parking calculator'),
    'description' => 'Parking Calculator Page',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('parkingcalulator_form',0),
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  $items['parkingcalculator_valet'] = array(
    'title' => t('Parking calculator'),
    'description' => 'Parking Calculator Page',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('parkingcalulator_form',0 ),
    'access callback' => TRUE,
  );
function parkingcalulator_form($form, &$form_state , $type){...}

```

but the function does not take the parameter and does not pass the value in the hidden form type to

```
function parkingcalulator_form_submit($form, &$form_state ,$type)

```

# Answer
> 0 votes
Remove $form from the submit function and just keep the $form\_state.

The function would look like

```
function parkingcalulator_form_submit(&$form_state ,$type)

```

# Answer
> 0 votes
In `parkingcalulator_form($form, &$form_state, $type)`, create a hidden form element to store the data you need for your submit function:

```
$form['type'] = array('#type' => 'hidden', '#value' => $type);

```

Then in your submit function `parkingcalulator_form_submit($form, &$form_state)` you can access that value:

```
$type = $form_state['values']['type'];

```

---
Tags: 7, forms
---


# Question
Title: How to update Drupal custom module after changing .install file
I am working on a pre-created Drupal 8 project that has a custom module called CCA(named out of project title). I have done the below update in the .install file to add a new column to the backend via Drupal.

```
function cca_update_8902 (&$sandbox) {
  db_add_field('cca_findings', 'cca_topic_id', array(
    'type' => 'float',
    'not null' => FALSE,
    'description' => 'interim fields addition',
  ));

```

How do I update the module in Drupal after this change has been made? Can someone guide on next steps to update my custom module in Drupal so that this change will be implemented? Thanks!

# Answer
Visit `/update.php` on your site when logged in as admin, or use `drush updatedb`

Note that in addition to changing the table in the `hook_update_N()`, you must also change the schema of the `cca_findings` table in `hook_schema()` so that new installs of your module will have the proper table structure. Update functions are not used on new installs of your module.
> 5 votes

---
Tags: database, hooks, drush
---


# Question
Title: Is it possible to call a custom ajax event after removing a file from a managed_file field?
I have a custom form with a managed\_file field element. I'd like to call an ajax event after removing a file (clicking the REMOVE button).

Is there a way to expand the existing ajax callback for the remove button?

What I'm trying to do is fire a custom ajax event after clicking the REMOVE button on a managed\_file element to remove an element from the dom.

# Answer
> 1 votes
I tried to do the same in D7 a while ago and I discovered a JS only solution is not possible. You need to add an ajax command to the Drupal callback.

Here's a similar question to yours. This one is about the upload button and you want the remove button.

In D7, the upload and remove button were handled by the same function and when I look at the D8 class of the managed file I also see only one callback: uploadAjaxCallback. So it might be worth checking that out.

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


# Question
Title: Which hook to use to detect new members added to group?
What is the best way to make a hook that only fires when new members are added to a group?

I have a function that exports group memberships to moodle course enrolments. Right now I have it bound to \_user\_presave:

```
function mymodule_user_presave (User $user) {

  // Gather data.
  $userid = $user->id();
  $group_memberships = \Drupal::service('group.membership_loader')->loadByUser($user);
  foreach ($group_memberships as $group_membership) {
    $group = $group_membership->getGroup();
    $groupid = $group->id->value;
    $roles = $group_membership->getRoles();
    // Get roles.
    foreach ($roles as $rolename => $value) {

```

I bound it to user\_presave after I realized that adding members to a group also calls this hook. But this seems unnecessarily inefficient, since it always returns all group memberships of the user, instead of just the latest one.

Is there a way to detect a new GroupMembership directly and hook into that?

# Answer
this works:

```
function tm_mymodule_group_content_presave(Drupal\group\Entity\GroupContent $entity) {
  $group_content_type = $entity->getGroupContentType();
  if ($group_content_type->get('content_plugin') == 'group_membership') {
    $groupid = $entity->gid->getValue()[0]['target_id'];
    $userid = $entity->entity_id->getValue()[0]['target_id'];
    $group = \Drupal::entityTypeManager()->getStorage('group')->load($groupid);
    $user = \Drupal::entityTypeManager()->getStorage('user')->load($userid);
    $membership = $group->getMember($user);
    $roles = $membership->getRoles();

     // Do something
   }
}

```
> 0 votes

---
Tags: 8, users, hooks, group
---


# Question
Title: Error: Maximum function nesting level of '512' reached when injecting custom service to webform (6.x) handler
I'm trying to use my custom service in the handler like this (in webform 6.0-beta1):

```
class TriggerAutomationWebformHandler extends WebformHandlerBase {

  /**
   * Ecomail.
   *
   * @var \Drupal\ecomail_automation\EcomailInterface
   */
  protected $ecomail;

  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition);
    $instance->ecomail = $container->get('ecomail_automation.ecomail');
  }
?>

```

`mymodule.services.yml` file looks like this:

```
services:
  ecomail_automation.ecomail:
    class: Drupal\ecomail_automation\Ecomail
    arguments: [ '@config.factory', '@logger.factory' ]

```

My `Drupal\ecomail_automation\Ecomail` class in constructed like this (`\Ecomail` class is different class in a global namespace - see https://packagist.org/packages/ecomailcz/ecomail):

```
  public function __construct(ConfigFactoryInterface $config, LoggerChannelFactoryInterface $logger_factory) {
    $this->config = $config->get('ecomail_webform.settings');
    $this->logger = $logger_factory;
    $this->ecomail = new \Ecomail($this->config->get('api_key'));
  }
?>

```

This leads to error (shortened to important parts):

```
Error: Maximum function nesting level of '512' reached, aborting! in Drupal\Component\Plugin\PluginBase->__construct() (line 53 of core/lib/Drupal/Component/Plugin/PluginBase.php).

Drupal\Component\Plugin\PluginBase->__construct(Array, 'trigger_automation', Array) (Line: 141)
Drupal\webform\Plugin\WebformHandlerBase::create(Object, Array, 'trigger_automation', Array) (Line: 43)
Drupal\ecomail_automation\Plugin\WebformHandler\TriggerAutomationWebformHandler::create(Object, Array, 'trigger_automation', Array) (Line: 21)
Drupal\Core\Plugin\Factory\ContainerFactory->createInstance('trigger_automation', Array) (Line: 76)
Drupal\Component\Plugin\PluginManagerBase->createInstance('trigger_automation', Array) (Line: 81)
Drupal\Core\Plugin\DefaultLazyPluginCollection->initializePlugin('trigger_automation') (Line: 35)
Drupal\webform\Plugin\WebformHandlerPluginCollection->initializePlugin('trigger_automation') (Line: 80)
Drupal\Component\Plugin\LazyPluginCollection->get('trigger_automation') (Line: 40)
Drupal\webform\Plugin\WebformHandlerPluginCollection->initializePlugin('trigger_automation') (Line: 80)
Drupal\Component\Plugin\LazyPluginCollection->get('trigger_automation') (Line: 40)
Drupal\webform\Plugin\WebformHandlerPluginCollection->initializePlugin('trigger_automation') (Line: 80)
Drupal\Component\Plugin\LazyPluginCollection->get('trigger_automation') (Line: 40)
...

```

What am I doing wrong?

# Answer
> 1 votes
The problem is that you're instanciating the `Ecomail` object into your Ecomail constructor `$this->ecomail = new \Ecomail($this->config->get('api_key'));` which is kind of a fork bomb.

Your Ecomail is creating an Ecomail itself creating another Ecomail, etc. That's an infinite loop

---
Tags: webforms
---


# Question
Title: Turn off template suggestion for specific fields
I have the problem, that the theme / template suggestion comments destroy the html when they are outputted as values.

```
{% set img_uri = "fields.img.value"%}

{{ dpm(img_uri)
style="backround:url({{ createMyImagePathCustomTwigFunction(img_uri) }});"

```

Results in:

```
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'views_view_field' -->
<!-- BEGIN OUTPUT from 'core/themes/stable/templates/views/views-view-field.html.twig' -->
public://img/person/joshua-ness-117255-unsplash_0.jpg
<!-- END OUTPUT from 'core/themes/stable/templates/views/views-view-field.html.twig' -->

<!-- END OUTPUT from 'core/themes/stable/templates/views/views-view-fields.html.twig' -->

```

..as wrong uri.

I know that I could dive deeper into the rendered array to find other versions.

However: To change production templates in general only for enabling a developing environment seems wrong to me.

Better would be a hook that would remove field tpl suggestions in general as I don't need them.

I know I can write handler functions... that is what I do in the moment.

But cleaner would be to turn the suggestions off for views fields. How this can be done?

# Answer
> 2 votes
As it seems, that there is no solid alternative that works for field values I have written a Twig-Filter which returns the value via this php function:

```
public function removeHtmlComments($string) {

  $output = preg_replace(array('/<!--(.|\s)*?-->\s*/', '/\t+/', '/\n+/', '/[\r\n]/', '/[\n\r]/'), '', $string);

  return $output;
}

```

# Answer
> 2 votes
You try this code :

```
{% set img_uri = "fields.img.value"%}

{{ dpm(img_uri)
style="backround:url({{ createMyImagePathCustomTwigFunction(img_uri) |render|striptags}});"

```

use |render|striptags

# Answer
> 0 votes
For me what worked well in the Twig was to use : `field | render | striptags | trim`

* striptags : remove the suggestions (or any other html tag)
* trim : remove the white-spaces left after striptags

# Answer
> -1 votes
Try the following.

```
{{ file_url(fields.img.content|striptags|trim) }}

```

---
Tags: 8, theming
---


title: Add a new column to the backend

text:
# Question
Title: Add a new column to the backend
I am trying to add a new column to a table and I added the column using `hook_update_N()`.

```
function cca_update_8902(&$sandbox) {
  db_add_field('cca_findings', 'cca_topic_id', array(
    'type' => 'float',
      'not null' => FALSE,
      'description' => 'interim fields addition',
    ));
  \Drupal::entityDefinitionUpdateManager()->applyUpdates();
}

```

My field is also defined in the `cca_findings` class as property.

```
class cca_findings extends ContentEntityBase {

  use EntityChangedTrait;

  /**
  * {@inheritdoc}
  */
  public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
    $fields = parent::baseFieldDefinitions($entity_type);

    $fields['cca_topic_name'] = BaseFieldDefinition::create('string_long')
      ->setSettings(['max_length' => 2047]);
    $fields['meanvalue'] = BaseFieldDefinition::create('float')
      ->setLabel(t('meanvalue'));

    $fields['cca_topic_id'] = BaseFieldDefinition::create('float')
      ->setLabel(t('cca_topic_id'));

    return $fields;
  }

}

```

So, the column has been created correctly, but the values are not going on the backend. I feel I am missing something.

What is missing in the code I wrote?

# Answer
As described in Support for automatic entity updates has been removed, when a module needs to update its own entity, and the update must change the database schema, the module needs to implement `hook_post_update_NAME()`. That is what the Taxonomy module does in `taxonomy_post_update_make_taxonomy_term_revisionable()` to make its entity revisionable.

The key code lines in that hook, which show how a new entity field is added, are the following ones.

```
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
$last_installed_schema_repository = \Drupal::service('entity.last_installed_schema.repository');
$entity_type = $definition_update_manager->getEntityType('taxonomy_term');
$field_storage_definitions = $last_installed_schema_repository->getLastInstalledFieldStorageDefinitions('taxonomy_term');
$field_storage_definitions['revision_id'] = BaseFieldDefinition::create('integer')
  ->setName('revision_id')
  ->setTargetEntityTypeId('taxonomy_term')
  ->setTargetBundle(NULL)
  ->setLabel(new TranslatableMarkup('Revision ID'))
  ->setReadOnly(TRUE)
  ->setSetting('unsigned', TRUE);
$field_storage_definitions['revision_default'] = BaseFieldDefinition::create('boolean')
  ->setName('revision_default')
  ->setTargetEntityTypeId('taxonomy_term')
  ->setTargetBundle(NULL)
  ->setLabel(new TranslatableMarkup('Default revision'))
  ->setDescription(new TranslatableMarkup('A flag indicating whether this was a default revision when it was saved.'))
  ->setStorageRequired(TRUE)
  ->setInternal(TRUE)
  ->setTranslatable(FALSE)
  ->setRevisionable(TRUE);
$definition_update_manager->updateFieldableEntityType($entity_type, $field_storage_definitions, $sandbox);

```

In your case, the code for `hook_post_update_NAME()` would be similar to the following one.

```
$definition_update_manager = \Drupal::entityDefinitionUpdateManager();
$last_installed_schema_repository = \Drupal::service('entity.last_installed_schema.repository');
$entity_type = $definition_update_manager->getEntityType('entity_machine_name');
$field_storage_definitions = $last_installed_schema_repository->getLastInstalledFieldStorageDefinitions('entity_machine_name');
$field_storage_definitions['meanvalue'] = BaseFieldDefinition::create('float')
  ->setLabel(t('meanvalue'));
$field_storage_definitions['cca_topic_id'] = BaseFieldDefinition::create('float')
  ->setLabel(t('cca_topic_id'));
$definition_update_manager->updateFieldableEntityType($entity_type, $field_storage_definitions, $sandbox);

```

Replace `'entity_machine_name'` with the machine name of the entity.
> 2 votes

---
Tags: 8, entities
---


# Question
Title: How do I programmatically update the order status?
After Payment is accepted, I need to update the order status to "Completed" from the page controller.

How do I do this, on Drupal 8?

I find no documentation about this; there is an example for Drupal 7.

```
// Updating Order status.
$orderObj = commerce_order_load($orderID);
commerce_order_status_update($orderObj, 'canceled', TRUE, 'Order Voided');
$orderObj->log = 'Order cancelled programatically';
commerce_order_save($orderObj);

```

# Answer
> 9 votes
You want to use the State Machine methods of the Commerce Order class.

It would be something like this, but it will depend on what you called your order states.

```
$order_state = $orderObj->getState();
$order_state_transitions = $order_state->getTransitions();
$order_state->applyTransition($order_state_transitions['complete']);

$orderObj->save();

```

If you aren't sure, you can always check the `$order_state_transitions` array to see what options you have.

# Answer
> 2 votes
I think you are looking to "place" the order. You need to subscribe to the Event handler for this event: commerce\_order.order.paid

and with this handler code:

```
  public function paymentCompletedHandler($event) {
    $order = $event->getOrder();
    $order->getState()->applyTransitionById('place');
    return;
  }

```

# Answer
> 0 votes
This code did the job for me. You need to know the ID of the transition. In my case, it's '**cancel**'

```
$order = \Drupal\commerce_order\Entity\Order::load($order_id);
$order_state = $order->getState();
$order_state->applyTransitionById('cancel');
$order->save();

```

# Answer
> -2 votes
You can simply use set method.

```
$order->set('state', 'completed');
$order->save();

```

---
Tags: 8, commerce, payment-gateways
---


# Question
Title: how do I specify a render cache context as universal?
I want to a render array in my page to be cached, and I know that it's the same for every user in every circumstance.

How do I specify that its cache context is universal, rather than anything else?

# Answer
There is no *universal* cache context. This is the default for a render array if you don't specify any cache context.

Render contexts are merged upstream. Additionally you can configure required cache contexts which are added to all render arrays before they are rendered.

Out of the box Drupal requires these three contexts:

*core.services.yml*

```
parameters:
  renderer.config:
    required_cache_contexts: ['languages:language_interface', 'theme', 'user.permissions']

```

You can override the parameter in */sites/default/services.yml* (use *default.services.yml* as template).
> 3 votes

---
Tags: caching
---


title: How can I query by node title?

text:
# Question
Title: How can I query by node title?
In Drupal 7 I had this code to query node fields and its respective title:

```
$query = db_select('node', 'n');
$query->join('field_data_field_internal_institute_paper_i', 'iipi', 'n.nid = iipi.entity_id');
$query->fields('n', array('nid'));
// some other conditions
$query->fields('n', array('title')); // <- working fine for D7
$result = $query->execute()->fetchall();

```

which was working fine. I know imported to D9 and I need to rewrite this accordingly:

```
$db = \Drupal::database();
$query = $db->select('node', 'n');
$query->join('node_revision__field_internal_institute_paper_i', 'iipi', 'n.nid = iipi.entity_id');
$query->fields('n', array('nid'));
// some other conditions
$query->fields('n', array('title')); //<- not working for D9
$result = $query->execute()->fetchall();

```

for some reason `array('title')` isn't a field anymore as seen above. How can I get the title here?

# Answer
This works fine in Drupal 9 for titles only from the `node_field_data` table:

```
$ drush php
Psy Shell v0.10.4 (PHP 7.4.13 — cli) by Justin Hileman
>>> $db = \Drupal::database();
=> Drupal\Core\Database\Driver\mysql\Connection {#767
     +"_serviceId": "database",
   }
>>> $query = $db->select('node_field_data', 'n');
=> Drupal\Core\Database\Query\Select {#4281}
>>> $query->fields('n', ['title']);
=> Drupal\Core\Database\Query\Select {#4281}
>>> $result = $query->execute()->fetchall();
=> [
     {#4254
       +"title": "Foo",
     },
     {#4257
       +"title": "Bar",
     },
   ]

```

Or for only an array of titles use `fetchCol()`:

```
>>> $result = $query->execute()->fetchCol();
=> [
     "Foo",
     "Bar",
   ]

```

**Node Field Data table:**

```
mysql> describe node_field_data;
+-------------------------------+------------------+------+-----+---------+-------+
| Field                         | Type             | Null | Key | Default | Extra |
+-------------------------------+------------------+------+-----+---------+-------+
| nid                           | int(10) unsigned | NO   | PRI | NULL    |       |
| vid                           | int(10) unsigned | NO   | MUL | NULL    |       |
| type                          | varchar(32)      | NO   | MUL | NULL    |       |
| langcode                      | varchar(12)      | NO   | PRI | NULL    |       |
| status                        | tinyint(4)       | NO   | MUL | NULL    |       |
| uid                           | int(10) unsigned | NO   | MUL | NULL    |       |
| title                         | varchar(255)     | NO   | MUL | NULL    |       |
| created                       | int(11)          | NO   | MUL | NULL    |       |
| changed                       | int(11)          | NO   | MUL | NULL    |       |
| promote                       | tinyint(4)       | NO   | MUL | NULL    |       |
| sticky                        | tinyint(4)       | NO   |     | NULL    |       |
| default_langcode              | tinyint(4)       | NO   |     | NULL    |       |
| revision_translation_affected | tinyint(4)       | YES  |     | NULL    |       |
+-------------------------------+------------------+------+-----+---------+-------+
13 rows in set (0.00 sec)

```
> 5 votes

# Answer
If you want to get a node entity, you can use the loadByProperties method in the node storage.

```
  $nodes = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->loadByProperties(['title' => $title]);
    // Load the first node returned from the database.
    $node = reset($nodes);

```
> 1 votes

---
Tags: nodes, database, 9
---


# Question
Title: How can I get the parent entity in a media preprocess hook?
I have a paragraph type with a media entity reference field `field_paragraph_image_ref`.

I need to modify the media Twig template depending on a field value of the parent, which is a paragraph entity.

There are ways to get the parent entity of a paragraph, but media entities don't have a `getParentEntity()` method. Also with `_referringItem` I am unable to get up to the parent paragraph itself.

How can I get the field value from the parent paragraph in the media preprocess?

```
/**
 * Implements hook_preprocess_HOOK().
 */
function hook_preprocess_media__picture__image_without_link(&$variables) {
  $media = $variables['elements']['#media'];
  // A method to get the parent entity, that I cannot find in
  // var_dump(get_class_methods($media));
  // and finally get a field value from the parent paragraph entity.
}

```

# Answer
I passed the parent entity "manually" to the media instance from one hook to the other.

```
/**
 * Implements hook_preprocess_HOOK().
 */
function MYTHEME_preprocess_paragraph__picture(&$variables) {
  $paragraph = $variables['paragraph'];

  $media = $paragraph->field_paragraph_image_ref->entity;

  // Storing the parent paragraph as an attribute of the media instance.
  $media->parent_paragraph = $paragraph;
}

/**
 * Implements hook_preprocess_HOOK().
 */
function MYTHEME_preprocess_media__picture__image_without_link(&$variables) {
  $media = $variables['elements']['#media'];

  if (isset($media->parent_paragraph)) {
    $paragraph = $media->parent_paragraph;

    // Now the field of the paragraph can be accessed and pass to the media
    // Twig template.
    $variables['my_field'] = $paragraph->my_field;
  }
}

```
> 2 votes

# Answer
i have ended up doing:

```
function hook_preprocess_media__picture__image_without_link(array &$variables) {
   $media = $variables['elements']['#media'];
   $parent = Drupal::entityTypeManager()->getStorage('paragraph')->loadByProperties([
    'field_paragraph_image_ref' => $media->id()
  ]);
   $parent = reset($parent);
   var_dump($parent->get("field_paragraph_image_link_page")->getValue();
}

```
> -1 votes

---
Tags: entities, media, paragraphs
---