# Question
Title: How to add language prefix to form action?
We have a multi lingual site that default is "en".

Sometimes editors are creating content in another language like "de" and than translate it to "en".

My problem is that we use Layout builder visibility rules for blocks.

And the form action attribute that is rendered as example below.

Does not have a language prefix.

And therefore ends up in a 403 response for every content page that is not created in sites default language.

My question is how can I add the language prefix to the action attribute the most drupalish way?

```
/**
   * {@inheritdoc}
   */
  public function buildForm(array $form, FormStateInterface $form_state, SectionStorageInterface $section_storage = NULL, $delta = NULL, $uuid = NULL) {
    $this->sectionStorage = $section_storage;
    $this->delta = $delta;
    $this->uuid = $uuid;

    // Any visibility conditions that have already been added to the block.
    $visibility_conditions_applied_to_block = $this->getCurrentComponent()->get('visibility') ?: [];

    // Visibility condition types that can be added to a block.
    $conditions_available_to_block = [];
    foreach ($this->conditionManager->getFilteredDefinitions('layout_builder', $this->getAvailableContexts($section_storage)) as $plugin_id => $definition) {
      $conditions_available_to_block[$plugin_id] = $definition['label'];
    }

    $items = [];
    foreach ($visibility_conditions_applied_to_block as $visibility_id => $configuration) {
      /** @var \Drupal\Core\Condition\ConditionInterface $condition */
      $condition = $this->conditionManager->createInstance($configuration['id'], $configuration);
      $options = [
        'attributes' => [
          'class' => ['use-ajax'],
          'data-dialog-type' => 'dialog',
          'data-dialog-renderer' => 'off_canvas',
          'data-outside-in-edit' => TRUE,
        ],
      ];
      $items[$visibility_id] = [
        'label' => [
          'data' => [
            'condition_name' => [
              '#type' => 'html_tag',
              '#tag' => 'b',
              '#value' => $condition->getPluginId(),
            ],
            'condition_summary' => [
              '#type' => 'container',
              '#markup' => $condition->summary(),
            ],
          ],
        ],
        'edit' => [
          'data' => [
            '#type' => 'link',
            '#title' => $this->t('Edit'),
            '#url' => Url::fromRoute('layout_builder.add_visibility', $this->getParameters($visibility_id), $options),
          ],
        ],
        'delete' => [
          'data' => [
            '#type' => 'link',
            '#title' => $this->t('Delete'),
            '#url' => Url::fromRoute('layout_builder.delete_visibility', $this->getParameters($visibility_id), $options),
          ],
        ],
      ];
    }

    if ($items) {
      $form['visibility'] = [
        '#prefix' => '<div class="configured-conditions">',
        '#suffix' => '</div>',
        '#theme' => 'table',
        '#rows' => $items,
        '#caption' => $this->t('Configured Conditions'),
        '#weight' => 10,
      ];
    }

    $form['condition'] = [
      '#type' => 'select',
      '#title' => $this->t('Add a visibility condition'),
      '#options' => $conditions_available_to_block,
      '#empty_value' => '',
      '#weight' => 20,
    ];

    // Determines if multiple conditions should be applied with 'and' or 'or'.
    $form['operator'] = [
      '#type' => 'radios',
      '#title' => $this->t('Operator'),
      '#options' => [
        'and' => $this->t('And'),
        'or' => $this->t('Or'),
      ],
      '#default_value' => $this->getCurrentComponent()->get('visibility_operator') ?: 'and',
      // This field is not necessary until multiple conditions are added.
      '#access' => count($items) > 0,
      // If there are two or more visibility conditions, this field appears
      // above the list of existing conditions. If there is only one visibility
      // condition, and a second one is being added, then this field appears
      // between the 'Add a visibility condition' dropdown and the submit
      // button.
      '#weight' => count($items) === 1 ? 30 : 3,
    ];

    // This is a submit button that only appears once two or more visibility
    // conditions are present. This submit button appears so the user can
    // update the visibility operator, a setting that impacts the entire block.
    // This is different than the default submit button/handler for this form,
    // which is used to add a visibility condition to the block.
    $form['update_operator'] = [
      '#type' => 'submit',
      '#access' => count($items) > 1,
      '#weight' => 5,
      '#value' => $this->t('Update operator'),
      '#submit' => ['::updateOperator'],
    ];

    if (count($items) === 1) {
      // If there is only one visibility condition, hide the operator field
      // until a second condition is selected to be added to the block.
      $form['operator']['#states'] = [
        'invisible' => [
          '[name="condition"]' => ['value' => ''],
        ],
      ];
    }

    $form['actions']['#weight'] = 40;
    $form['actions']['submit'] = [
      '#type' => 'submit',
      '#value' => $this->t('Add condition'),
      // Submit button is only visible if a condition is selected.
      '#states' => [
        'invisible' => [
          '[name="condition"]' => ['value' => ''],
        ],
      ],
    ];

    $form['#attributes']['data-layout-builder-target-highlight-id'] = $this->blockUpdateHighlightId($this->uuid);

    if ($this->isAjax()) {
      $form['actions']['submit']['#ajax']['callback'] = '::ajaxSubmit';
      $form['actions']['submit']['#ajax']['event'] = 'click';
      $form['update_operator']['#ajax']['callback'] = '::ajaxSubmit';
      $form['update_operator']['#ajax']['event'] = 'click';
    }

    return $form;
  }

```

**Example won't work:**

```
<form class="layout-builder-configure-visibility" data-layout-builder-target-highlight-id="28411f7a-940c-44a5-bf49-43ca6dfa3acd" data-drupal-selector="layout-builder-configure-visibility" action="/layout_builder/visibility/block/overrides/node.220/1/28411f7a-940c-44a5-bf49-43ca6dfa3acd/user_role?destination=/layout_builder_iframe_modal/redirect" method="post" id="layout-builder-configure-visibility" accept-charset="UTF-8">

```

**Example work:**

```
<form class="layout-builder-configure-visibility" data-layout-builder-target-highlight-id="28411f7a-940c-44a5-bf49-43ca6dfa3acd" data-drupal-selector="layout-builder-configure-visibility" action="/de/layout_builder/visibility/block/overrides/node.220/1/28411f7a-940c-44a5-bf49-43ca6dfa3acd/user_role?destination=/layout_builder_iframe_modal/redirect" method="post" id="layout-builder-configure-visibility" accept-charset="UTF-8">

```

# Answer
Found a solution that works for me. This form above is a modal form rendered as Iframe. So in my .module file. I had to adjust the action attribute itself:

```
/**
 * Implements hook_preprocess_HOOK().
 */
function freitag_layout_visibility_control_preprocess_form(&$variables) {
  if (isset($variables['attributes']['id']) && $variables['attributes']['id'] === 'layout-builder-configure-visibility') {
    $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
    $variables['attributes']['action'] = '/' . $langcode . $variables['attributes']['action'];
  }
}

```

Not the nicest solution but it works.
> 0 votes

---
Tags: 8, forms
---


title: Return a Closure from a Factory

text:
# Question
Title: Return a Closure from a Factory
I have services that depend on request information. I'm trying to create a **Factory Factory** which will have the Dependency Injection container returns a factory (an anonymous function) that will create the services I want. So basically somthing like this:

```
class FooFactoryFactory {
  public static function create(ContainerInterface $container): callable {
     return static function (Request $request) use ($container) {
       $raz = request->get('param_raz');
       return new Bar(
           $container->get(LoggerInterface::class),
           $raz,
       );
     };
  }

}

```

The issue I have is that the `Closure` is properly created, but de Drupal's Dependency Injection Container class tries to set a proprty to the `Closure`. This cannot work and ends in a fatal error:

`Closure object cannot have properties`

Here is the place where it occurs:

```
// Drupal\Component\DependencyInjection\Container::createService() - Line 283-293
if (isset($definition['properties'])) {
  if ($definition['properties'] instanceof \stdClass) {
    $definition['properties'] = $this->resolveServicesAndParameters($definition['properties']);
  }
  foreach ($definition['properties'] as $key => $value) {
     $service->{$key} = $value;  // <-- Will not work for Closure
  }
}
...

```

So the questions I have:

* Is this by design? Meaning is it something thta is not wanted in term of coding practice?
* The error can be avoided if I manage to make sure, that the service I want to create does not have `properties` it it's definition. I just don't know how to achieve this.

Thanks for the help on this matter.

EDIT: This is basically what I'm trying to achieve:

---

```
  closure.factory.service:
    class: Drupal\some_module\ClosureFactoryService
  closure.service:
    class: Closure
    factory: [ '@closure.factory.service', getCallable ]

```

```
class ClosureFactoryService {
  public function getCallable(): Closure {
    return static function (int $arg): string {
      return sprintf('val %d', $arg);
    };
  }
}

```

I get: `Closure object cannot have properties in Drupal\Component\DependencyInjection\Container->createService() (line 288...`

# Answer
In Drupal, the class for a service defined in a module .services.yml file doesn't need to implement `create(ContainerInterface $container)`. It's not even requested to implement a specific PHP interface.

See one of the services Drupal core implements, for example the *path\_alias.manager* service.

```
path_alias.manager:
  class: Drupal\path_alias\AliasManager
  arguments:
   - '@path_alias.repository'
   - '@path_alias.whitelist'
   - '@language_manager'
   - '@cache.data'

```

The `AliasManager` class that implements that service doesn't implement any `create()` method; it just implement the constructor, with the parameters defined in the same order the service arguments are listed.

```
public function __construct($alias_repository, AliasWhitelistInterface $whitelist, LanguageManagerInterface $language_manager, CacheBackendInterface $cache) {
  $this->pathAliasRepository = $alias_repository;
  $this->languageManager = $language_manager;
  $this->whitelist = $whitelist;
  $this->cache = $cache;
}

```

The classes that implement `create(ContainerInterface $container)` and which implement `ContainerInjectionInterface`, for example the `CronForm` class, don't return a closure from `create(ContainerInterface $container)`; they actually only return an instance of themselves. See `CronForm::create()`.

```
public static function create(ContainerInterface $container) {
  return new static($container->get('config.factory'),
    $container->get('state'),
    $container->get('cron'),
    $container->get('date.formatter'),
    $container->get('module_handler')
  );
}

```

If you want to implement a factory service in Drupal, you should take the *cache\_factory* service as example to write your code.

```
cache_factory:
  class: Drupal\Core\Cache\CacheFactory
  arguments:
    - '@settings'
    - '%cache_default_bin_backends%'
  calls:
    - [setContainer, ['@service_container']]

```

A service that uses that service as factory is, for example, the *cache.render* service.

```
cache.render:
  class: Drupal\Core\Cache\CacheBackendInterface
  tags:
    - { name: cache.bin }
  factory:
    - '@cache_factory'
    - get
  arguments:
    - render

```

The *factory* key defines which service is the factory service and which method is called for that factory service; the *arguments* key define the arguments passed to that method. In this case, it's telling Drupal to instantiate the *cache.render* service by instantiating the *cache\_factory* service and calling `get('render')` on that object.
> 4 votes

---
Tags: dependency-injection, symfony-services
---


title: How do I force the pager to update?

text:
# Question
Title: How do I force the pager to update?
I have a custom form built with the Form API. The general flow is:

1. Build and display form
2. Get user input
3. Rebuild and form
    * query based on user input with added

    ```
    $query = $query
      ->extend('Drupal\\Core\\Database\\Query\\PagerSelectExtender')
      ->limit($values['items']);

    ```

This all works well for the first submission and for paging between submissions, but when a user enters a different value for the query, while the search results change, the pager does not update (it displays the same number of result pages as with the old query and stays on the same page of the query.

So if the first query (e.g. "duck") resulted in 14 pages of results, and I am on the 3rd page of duck results, when I change the query field to "chicken" and submit, the actual results show the right things, but the pager still shows 14 pages instead of the 35 for chicken and it keeps me on the 3rd page instead of taking me to the first page).

How do I force the pager to update?

# Answer
> 2 votes
I figured it out, hopefully this will help someone else with a similar question.

Instead of doing a `$formstate->setRebuild();` in the `submitForm` method, I changed it to

```
$form_state->setRedirect(
    'sliker_drupal_backend.browser',
    [],
    [
      'query'=>[
        'logic'=>$form_state->getValue('logic'),
        'items'=>$form_state->getValue('items'),
        'phrase'=>$form_state->getValue('phrase'),
        'visibility'=>$form_state->getValue('visibility'),
        'ids'=>$form_state->getValue('ids'),
      ],
    ]);

```

the `setRedirect()` method takes three arguments:

* Route machine name
* Arguments (to fill in "placeholders" in the route path)
* Options which are any options that can be passed to a `\Drupal\Core\Url`

By searching code, found options is an associative array and the keys can be any of:

* 'query': An array of query key/value-pairs (without any URL-encoding) to append to the URL.
* 'fragment': A fragment identifier (named anchor) to append to the URL. Do not include the leading '#' character.
* 'absolute': Defaults to FALSE. Whether to force the output to be an absolute link (beginning with http:). Useful for links that will be displayed outside the site, such as in an RSS feed.
* 'attributes': An associative array of HTML attributes that will be added to the anchor tag if you use the \Drupal\Core\Link class to make the link.
* 'language': An optional language object used to look up the alias for the URL. If $options\['language'\] is omitted, it defaults to the current language for the language type LanguageInterface::TYPE\_URL.
* 'https': Whether this URL should point to a secure location. If not defined, the current scheme is used, so the user stays on HTTP or HTTPS respectively. TRUE enforces HTTPS and FALSE enforces HTTP.

I then updated my logic in the form build to look for query parameters and to use that information if it is present.

See https://api.drupal.org/api/drupal/core!lib!Drupal!Core!Form!FormState.php/function/FormState%3A%3AsetRedirect/8.9.x for more information on `setRedirect()`.

---
Tags: 8, forms, paging
---


# Question
Title: RuntimeException: Failed to start the session because headers have already been sent by
New to Drupal, I just created a new custom module in Drupal 9 to see how it works I was trying to test with a minimal piece of code. I just enable this module and got this error, now I can't open anything and getting this error on every page nothing is happening even if I change anything in code. This is my custom module code.

### check\_hookcalls.info.yml

```
name: hook calls checking
description: module for testing hooks
core_version_requirement: ^8 || ^9
type: module

```

### check\_hookcalls.module

```
<?php

function check_hookcalls_node_presave() {
  die;
}

?>

```

The error I get is the following one.

> \[13-Jul-2021 15:34:49 Europe/Berlin\] RuntimeException: Failed to start the session because headers have already been sent by "C:\softwares\xampp\htdocs\d9\_firstexperience\2\modules\check\_hookcalls\check\_hookcalls.module" at line 10. in C:\softwares\xampp\htdocs\d9\_firstexperience\2\vendor\symfony\http-foundation\Session\Storage\NativeSessionStorage.php on line 152

# Answer
Per the Drupal coding standards, the closing php tag should be omitted.

The PHP Code Tags section of the coding standards (as well as this stackoverflow answer) give a good overview of why it's a good practice to omit them in general:

> * Removing it eliminates the possibility for unwanted whitespace at the end of files which can cause "header already sent" errors, XHTML/XML validation issues, and other problems.
> * The closing delimiter at the end of a file is optional.
> * PHP.net itself removes the closing delimiter from the end of its files (example: prepend.inc), so this can be seen as a "best practice."
> 1 votes

---
Tags: hooks
---


# Question
Title: How can I return a 404 error when the contextual filter value is provided in the URL, but the view returns no result?
I'm on building a rest view of nodes using *Serializer* as formatter. This view has a contextual filter on a plain-text field of that content type.

How can I return a 404 error when the contextual filter value is provided in the URL, but the view returns no result?

I've tried various validators, such as *content*, *field*, or *basic validation*, but none of them does what I'm looking for.

# Answer
In the 'No Results Behavior' section for the view, click 'add', and choose 'Response Status Code', and set the value to 404.
> 1 votes

---
Tags: views, 9
---


# Question
Title: Custom field for Search API with multi values
I'm using latest version of SearchAPI (1.18) and SearchAPI Solr (4.1.10).

I've a custom field that I want to have multiple values (I use it for faceted search with Facets module). In the previous version of SearchAPI the second example worked.

If I use this code, SearchAPI save "Array" as value:

```
<?php

namespace Drupal\archivio_utils\Plugin\search_api\processor;

use Drupal\search_api\Datasource\DatasourceInterface;
use Drupal\search_api\Item\ItemInterface;
use Drupal\search_api\Processor\ProcessorPluginBase;
use Drupal\search_api\Processor\ProcessorProperty;

/**
 *
 * @SearchApiProcessor(
 *   id = "periodo",
 *   label = @Translation("Periodo"),
 *   description = @Translation("Periodo"),
 *   stages = {
 *     "add_properties" = 0,
 *   },
 *   locked = true,
 *   hidden = false,
 * )
 */
class Periodo extends ProcessorPluginBase {

  /**
   * {@inheritdoc}
   */
  public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) {
    $properties = [];

    if (!$datasource) {
      $definition = [
        'label' => $this->t('Periodo'),
        'description' => $this->t('Periodo'),
        'type' => 'string',
        'processor_id' => $this->getPluginId(),
      ];
      $properties['search_api_persona_periodo'] = new ProcessorProperty($definition);
    }

    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public function addFieldValues(ItemInterface $item) {
    $entity = $item->getOriginalObject()->getValue();
    /* @var \Drupal\node\Entity\Node $entity */
    /* @var \Drupal\node\Entity\Node $carriera */
    if ($entity->bundle() == 'persona') {
      $fields = $this->getFieldsHelper()
        ->filterForPropertyPath($item->getFields(), NULL, 'search_api_persona_periodo');
      foreach ($fields as $field) {
        if (!$field->getDatasourceId()) {
          $values[] = 'test1';
          $values[] = 'test2';
          $field->addValue($values);
        }
      }
    }
  }
}

```

If I replace code where I wrote values with this:

```
$values[] = 'test1';
$values[] = 'test2';
foreach ($values as $value) {
   $field->addValue($value);
}

```

I obtain this error:

> \[error\] Drupal\search\_api\_solr\SearchApiSolrException while indexing item entity:node/10008:it: Solr endpoint http://solr:8983/ bad request (400). ERROR: \[doc=3igm00-archivio\_indice-entity:node/10008:it\] multiple values encountered for non multiValued field ss\_persona\_periodo: \[test1, test1\] in Drupal\search\_api\_solr\SolrConnector\SolrConnectorPluginBase-\>handleHttpException() (line 1016 of /var/www/html/web/modules/contrib/search\_api\_solr/src/SolrConnector/SolrConnectorPluginBase.php).

How can I add multiple values to this custom field?

# Answer
Try to add

> is\_list =\> TRUE

```
  /**
   * {@inheritdoc}
   */
  public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) {
    $properties = [];

    if (!$datasource) {
      $definition = [
        'label' => $this->t('Periodo'),
        'description' => $this->t('Periodo'),
        'type' => 'string',
        'is_list' => TRUE, // Add this option to the definition
        'processor_id' => $this->getPluginId(),
      ];
      $properties['search_api_persona_periodo'] = new ProcessorProperty($definition);
    }

    return $properties;
  }

```
> 4 votes

# Answer
You can add this:

```
foreach ($fields as $field) {
    $field->addValue($custom_field);
    $field->addValue($custom_field);
}

```
> 1 votes

---
Tags: search
---


title: Remove Configuration Installer (v1.8)

text:
# Question
Title: Remove Configuration Installer (v1.8)
I'm upgrading a site from Drupal 8 to Drupal 9. One of the projects that is deprecated and incompatible with Drupal 9 is Configuration Installer

The "normal" workflow (e.g., `drush pmu` \<module\_name\> doesn't work - perhaps because this thing isn't really a module?) I can't simply remove the project with composer because then `drush cim` fails because it expects the code to be in the base.

It is like *Hotel California* "You can check out any time you like But you can never leave!"

# Answer
Configuration installer is an installation profile, not a module. It's like one of the standard installation profiles that comes with Drupal core, such as Standard or Minimal.

Once the site is installed using an installation profile, you cannot change the used installation profile anymore; it's not like a module that can be uninstalled and replaced with a different module. That's why an installation profile doesn't implement `hook_uninstall()`.

The only way to use a different installation profile for a site is reinstalling Drupal and choose the default installation profile (*Standard*).

Manually changing the installation profile would require to change any reference to the old installation profile in the database with the reference to the new installation profile, execute the new profile `hook_install()` implementation, and eventually reverse the changes done from the old profile `hook_install()` implementation. There is still the configuration added with the configuration files in the config/install and config/optional directories for the installation profiles. (See for example, config/install and config/optional for the *Standard* profile.) The configuration from the old profile should be removed, and the one from the new profile added.
> 3 votes

---
Tags: 8, configuration
---


# Question
Title: What is the new methodology for Form Pre-Render in order to utilize TrustedCallbackInterface
We are upgrading our sites one at a time from Drupal 8 to Drupal 9 and there is one line of code in our custom theme that is the last of our problems.

We get the following error on View that uses an exposed filter:

```
Drupal\Core\Security\UntrustedCallbackException: Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was MYSITE_form_alter_views_exposed_form_MYVIEW_pre_render. See https://www.drupal.org/node/2966725 in Drupal\Core\Render\Renderer->doTrustedCallback() (line 96 of core/lib/Drupal/Core/Security/DoTrustedCallbackTrait.php).

```

In the OURTHEME.theme file, we have this function:

```
/**
 * Custom form alter for events.
 */
function OURTHEME_form_alter_views_exposed_form_events_pre_render($form) {
  $fields = [
    'field_start_date_value',
    'field_end_date_value',
    'field_address_locality',
  ];
  foreach ($fields as $field) {
    $form[$field]['#title_display'] = 'after';
  }
  $form['field_date_range_end_value']['#prefix'] = '<div class="event-exposed-form">';
  $form['field_event_address_locality']['#suffix'] = '</div>';
  return $form;
}

```

And the function is called here (just a snippet of the code in this function):

```
/**
 * These are the alterations to forms variables before they are rendered.
 */
function OURTHEME_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'views_exposed_form' && strpos($form['#id'], 'views-exposed-form-events-') === 0) {
    $form['#pre_render'][] = 'OURTHEME_form_alter_views_exposed_form_events_pre_render';
  }
  return $form;
}

```

From what I could divine from the research I've done so far, it seems that normally whatever class these kinds of functions are utilized in have implemented Drupal's `TrustedCallbackInterface`. Unfortunately, the only information I have found has been throughout the various patches being applied to projects throughout Drupal.org, so I'm trying to cobble together a methodology from random applications of it.

Of course, there's the Drupal API page, but that's not especially helpful when it comes to actually putting the pieces together into a useful methodology without knowing the rest of the API like the back of your hand.

Does anyone know if there's any documentation on how to apply the `TrustedCallbackInterface` to a function that previously used `$form['#pre_render'][]`, especially in THEME.theme which is not set up the same as any old custom class in a Module?

# Answer
> 4 votes
You can do something like this:

in your new module **my\_prerenders** in *my\_prerenders/src/* add a new class:

```
namespace Drupal\my_prerenders;

use Drupal\Core\Security\TrustedCallbackInterface;

class MyPreRenders implements TrustedCallbackInterface {

  /**
   * @inheritDoc
   */
  public static function trustedCallbacks() {
    return ['formAlterViewsExposedFormEventsPreRender'];
  }

  public function formAlterViewsExposedFormEventsPreRender($form) {
    $fields = [
    'field_start_date_value',
    'field_end_date_value',
    'field_address_locality',
    ];
    foreach ($fields as $field) {
      $form[$field]['#title_display'] = 'after';
    }
    $form['field_date_range_end_value']['#prefix'] = '<div class="event-exposed-form">';
    $form['field_event_address_locality']['#suffix'] = '</div>';
    return $form;
  }

}

```

In **OURTHEME.theme** you just have to use:

```
use Drupal\my_prerenders\MyPreRenders;

...
...

$form['#pre_render'][] = [MyPreRenders::class, 'formAlterViewsExposedFormEventsPreRender'];

```

instead of

```
$form['#pre_render'][] = 'OURTHEME_form_alter_views_exposed_form_events_pre_render';

```

---
Tags: theming, forms
---


# Question
Title: How to use drupal_add_html_head() to add the same metatag multiple times?
I have a node which has multiple images attached to it. And each image should also be printed in a `<meta property="og:image" content="image_url" />` metatag. I have tried to use `drupal_add_html_head()` for each image in a `template_preprocess_page()`, but only the last image is printed as metatag.

```
function mytheme_preprocess_page(&$variables) {
...
    // add multiple og:image tags
    foreach ($images as $image) {
        $element = array(
            '#tag' => 'meta',
            '#attributes' => array(
                "property" => "og:image",
                "content" => $image,
            ),
        );
        drupal_add_html_head($element,'facebook_share_image');
    }
}

```

# Answer
> 7 votes
The tags are stored by key, so using a different key for each should do the trick:

```
$delta = 0;
foreach ($images as $image) {
    $element = array(
        '#tag' => 'meta',
        '#attributes' => array(
            "property" => "og:image",
            "content" => $image,
        ),
    );
    drupal_add_html_head($element,'facebook_share_image:' . $delta++);
}

```

# Answer
> 1 votes
For apple's favicons you can use something like this:

```
function mytheme_page_attachments_alter(array &$page) {
      $apple_sizes = [57, 60, 72, 76, 114, 120, 144, 152, 180, 192];

      foreach ($apple_sizes as $size) {
        $favicon = [
          '#type' => 'html_tag',
          '#tag' => 'link',
          '#attributes' => [
            'rel' => 'apple-touch-icon',
            'sizes' => $size . 'x' . $size,
            'href' => '/themes/gov_pt/apple-icon-' . $size . 'x' . $size . '.png'
          ],
        ];
        $page['#attached']['html_head'][] = [$favicon, 'apple-touch-icon' . $size];
      }
}

```

---
Tags: 7, social-network, meta-tags
---


# Question
Title: Simplest way to get a full set of favicons and touch icons
So you've generated a big batch of favicons, touch icons, tiles and whatever to cover the full range of files a broswer might look for, and the generator you used has helpfully given you a whole lot of code to just drop into your HTML `<head>`, something like this:

```
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png">
<link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
<link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="/favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="/android-chrome-192x192.png" sizes="192x192">
<meta name="msapplication-square70x70logo" content="/smalltile.png" />
<meta name="msapplication-square150x150logo" content="/mediumtile.png" />
<meta name="msapplication-wide310x150logo" content="/widetile.png" />
<meta name="msapplication-square310x310logo" content="/largetile.png" />

```

Great. Trouble is, that's not so simple in Drupal, where:

* The root site directory is off limits due to updates.
* Even after, say, find/replacing `content="/` to `content="/sites/all/themes/yourtheme/icons/`, the standard way to add items to `<head>` is one line at a time, through a hook in your `template.php` or similar.

This is a routine task I do for every site. Is there are simpler way than turning every one of those into something like this from a related apple-touch-specific question in a template hook:

```
 $appleIcon = array(
    '#tag' => 'link',
    '#attributes' => array(
       'href' => '/sites/default/files/apple-touch-icon-144x144.png',
       'rel' => 'apple-touch-icon', 'type' => 'image/png'
     ),
  );
  drupal_add_html_head($appleIcon, 'apple-touch-icon');

```

Best I can think of is overriding my `html.tpl.php` file, but I'd prefer not to override it if possible, in case Core or my base theme update it due to some new feature or best practice.

Everything I can find online seems to be only interested in one favicon and one Apple icon, which isn't a problem.

There are custom modules for this, like Responsive Favicons, but they have issues reporting that some icons don't get picked up, and it seems an overcomplicated approach to simply adding some icons.

# Answer
> 7 votes
If you use the metatag module you can use the -favicon and -mobile submodules.

If you visit `admin/config/search/metatags` (Configuration \> Search and Metadata \> Metatags), you can alter a metatag set. And you'll get this section:

Here you can enter the paths to the files relative to your Drupal root. eg. `sites/default/files/metatags/favicon.ico`. Depending on where you've uploaded these files. (You need FTP for this.)

The -mobile submodule will add MS Application icons and in another section.

# Answer
> 0 votes
You can use something like this in your `.theme` file:

```
function mytheme_page_attachments_alter(array &$page) {
      $apple_sizes = [57, 60, 72, 76, 114, 120, 144, 152, 180, 192];

      foreach ($apple_sizes as $size) {
        $favicon = [
          '#type' => 'html_tag',
          '#tag' => 'link',
          '#attributes' => [
            'rel' => 'apple-touch-icon',
            'sizes' => $size . 'x' . $size,
            'href' => '/themes/gov_pt/apple-icon-' . $size . 'x' . $size . '.png'
          ],
        ];
        $page['#attached']['html_head'][] = [$favicon, 'apple-touch-icon' . $size];
      }
}

```

---
Tags: 7, theming, meta-tags
---


# Question
Title: How to import Json file from Feeds module
I am using Feeds import module with Feeds extensible parsers module, I am getting following error. I am not getting what is wrong with the json and settings. Can anyone help me to resolve this issue.

Thanks in advance,

My json look like,

\[ { "lcia\_id": , "name": "", "company\_name": "", "company\_id": , "net\_weight": , "country": "", "address": "--", "serving\_size": "-", "composition": \[\], "type": "", "field\_ingredientimpactcarboningm": , "field\_ingredientaggimpactbiosli": , "field\_ingredientaggimpactwaterle": , "field\_ingredientaggimpactwaterpo": , "field\_processingimpactcarboningm":
}, \]

and in Feeds setting I have used,

# Answer
You need to provide a value for the `lcia_id` key.

In your Feeds Type mapping, we can see that the entity's `ID (nid)` is mapped to the JSON file's `lcia_id`, but, in your sample JSON file, the `lcia_id` value is missing.

You could also consider using Feeds Tamper to set a default value when no value is available for `lcia_id`. Here is an example of how to use it.
> 0 votes

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


# Question
Title: InvalidArgumentException: Field field_message_header is unknown. in Drupal\Core\Entity\ContentEntityBase->getTranslatedField()
At a total loss as to what is the cause of this error. The field was added to a Message Notify template entity. It is basically used as a token in emails sent using that module. The only place in my custom code that i use this field is to set its value from a value collected in a modal form. When submitting the modal; this error occurs.

The crazy part of this is that i have removed the field from the entity (so no longer exists in visible config in the site). I have also commented out the 1 line of code that refers to this field. After a db search the only tables to reference this field are config\_snapshot and config\_import. There were entries there for the field which i removed and the only records which remain are for the bundles which used to hold this field. Can't find any reference to what these tables are for but guessing they are only records of past import and not actively used.

To add to the crazy, this all works fine on my local dev copy of the site.

I have run cron and cr numerous times.

Any hints?

# Answer
I restored an old db (from the live site) and reran drush cim to get the config which should have been in the staging site (which was showing this error) - and this solved our problem. Very odd that i couldn't find a reference to this field in the db or in code and odd that cim didnt fix it until i ran it on an older db.
> 0 votes

---
Tags: 8
---


title: Get path (alias) from SQL query

text:
# Question
Title: Get path (alias) from SQL query
I have a SQL query to get all nodes with their ID, title, publish date, change date, etc.

Additionally I need to get path to each of them (probably from path\_alias.alias).

Now I have following (without alias):

```
SELECT MIN(node_field_data.nid) AS nid,node_field_data.type, node_field_data.status, node_field_data.title, node_field_data.langcode AS node_field_data_langcode, node_field_data.created, node_field_data.changed
FROM
node_field_data
INNER JOIN node ON node_field_data.nid = node.nid
GROUP BY node.nid, node_field_data.changed, node_field_data_langcode
ORDER BY node_field_data.nid DESC;

```

Any idea how to get it?

# Answer
> 2 votes
If you want to access Drupal entities, then you should use EntityTypeManager's `getStorage()` method to return a storage controller for nodes:

```
// Get a storage handler reference for Nodes.
$node_storage = \Drupal::entityTypeManager()->getStorage("node");
// Load an arbitrary node, as identified by the $nid variable.
$node = $node_storage->load($nid);

```

Being that a node is a type of content entity, you'll have the entire API as defined by Drupal\node\NodeInterface, to work with. This includes the ability to call:

```
// Get internal path, path alias if exists, for an entity.
$node->toUrl()->toString();

```

For more insight on how to work with Entities in Drupal, please see this post, from which I borrowed the above example: https://www.drupal.org/docs/drupal-apis/entity-api/working-with-the-entity-api

---
Tags: 8, nodes, database, path-aliases
---


title: Webform one-time submission token+URL

text:
# Question
Title: Webform one-time submission token+URL
I have two webforms:

1. Email webform: asks for the user's email address.
2. Voting webform: contains an entity selection list from which the user can select one and submit their vote.

In the email webform, there is a confirmation email sent to the submitted email address. In this confirmation email, I want to have an URL that points to the voting webform, and I want this to be a one-time-URL, as I want the users to access the voting webform in this way to validate that the submitted email is live and functioning.

What is the best solution for this?

# Answer
> 0 votes
Webform has numerous capabilities for limiting submissions, and doesn't require arbitrary links: https://www.drupal.org/node/3080869

---
Tags: webforms
---


# Question
Title: How can I programmatically get a list of orders purchased by a specific user?
how can i get list of commerce order purchased by specific user programatically?

i want to create function for it so that other developers can use it in further development by simply calling that function. i want to get name of orders purchased by user based on uid.

i have used drupal commerce module for it,i am not getting any table column in database where i can get relevant data.

# Answer
to get ALL orders of a user - get user ID ($user\_id) then

```
$orders = \Drupal::entityTypeManager()
  ->getStorage('commerce_order')
  ->loadByProperties(['uid' => $user_id]);

```
> 2 votes

# Answer
Drupal 8 has view called **"User Orders"** with contextual filters already configured

So you can get that view results with this line of code.

```
$orders = views_get_view_result('commerce_user_orders', 'order_page', $uid);

```
> 0 votes

---
Tags: 8, commerce
---


# Question
Title: Adding an HTML data attribute to rows in Views
I've tried rewriting the row and also theming the Views row, but I'm not having any luck. Maybe I'm doing something wrong.

I have the format of my view as 'Unformatted View', and in the format settings there is an option to specify the 'Row Class', which is then added to each row. However, I need to add a data-attribute to my rows in addition to a class. The data-attribute needs to be one of the fields - the Taxonomy Term name field (in lower case).

For instance, my field is Taxonomy Term Name. Currently, the HTML markup of each row looks like this:

```
<div class="my-row">Term</a>

```

However, I need it to look like this:

```
<div class="my-row data-attribute=".term">Term</a>

```

I am finding this fairly difficult to accomplish, and can't find much about it online. Could anyone be of help?

# Answer
> 2 votes
The easiest way that I found to create unique attribute per views row is to override the template file to exclude the outer div and output each row using `Global: Custom text` in the view excluding from display all fields and including them in the `custom text` field.

Here is in more detail

1. go to your view and click `Advanced > theme > information`
2. in `style output` line the bolded file name is the currently used template (let assume `views-view-unformatted.tpl.php`)
3. get the name next to the bolded file name (could be something like this `views-view-unformatted--VIEWNAME.tpl.php`)
4. copy `/all/modules/views/theme/views-view-unformatted.tpl.php` to your `THEMENAME/views-view-unformatted--VIEWNAME.tpl.php`
5. edit it and modify so it does not output the outer row div. It could look like this for unformatted style

```
<?php if (!empty($title)): ?>
  <h3><?php print $title; ?></h3>
<?php endif; ?>
<?php foreach ($rows as $id => $row): ?>
    <?php print $row; ?>
<?php endforeach; ?>

```
6. edit all view field and check `Exclude from display`
7. add `Global: Custom text` and add all fields in the content using replacement pattern
8. your outer div in `Custom text` could look like this

```
<div class="views-row my-row" data-attribute=".[field_FIELDNAME]">[field_FIELDNAME]</div>

```
9. refresh the cache and make sure in steps 1,2, your new template is used

# Answer
> 0 votes
not seeing that your problem is views module specific. Maybe here is a solution for your problem outside of views formatting: https://www.drupal.org/node/1462436#comment-5674366

# Answer
> 0 votes
You can do this by overriding the field's tpl.php file .. The needed template and the proper file name can be found at view's setting page \>\> advanced \>\> information

# Answer
> 0 votes
I just had to do something similar; I added a `lang` attribute to rows in a search result. Here's what I ended up doing:

Created an override template for the rows in my View of interest. In my case the name was something like "views-view-unformatted--*my-view*.tpl.php" I copied the existing base "views-view-unformatted.tpl.php" code into that, and made this modification to the tag printed inside the `foreach ($rows as $id => $row)` loop:

```
<div<?php if(isset($view->result[$id]->entity->language)): ?> lang="<?php echo $view->result->entity->language; ?>"<?php endif; ?>...

```

If you want to use data from a field you're pulling (whether included in the display or not), you can also get the info out of `$view->result[$id]->_entity_properties`. (In my case I didn't need to explicitly capture that field.)

---
Tags: 7, views, theming
---


# Question
Title: Get the value of a field to do an if statement Twig
I am trying to generate a PDF with *Entity Print*. Until then all is well.

In my Twig page, I try to make conditional displays. But I can’t get the conditions to work.

I render my fields using ***{{ content.field\_custom }}*** and that also works fine.

But the condition don't work , when I do something like :

```
{% if content.field_custom == 'John' %} ...

```

or

```
{% set field = content.field_custom %}
{% if field == 'John' %}
   <p>Hello</p>
{% endif %}

```

I need to do this in the fields twig template, can someone help me?

Many thanks

# Answer
> 1 votes
I recommend the Twig Field Value module, which provides a `field_value` filter that you can apply directly to a field:

`{{ content.field_name|field_value }}`

Also, while this doesn't specifically answer your question, I would be remiss not to mention the handy and useful Twig Tweak module. It rocks! :)

---
Tags: theming, 8
---


# Question
Title: Programmatically create a new image style
I'm creating my own module and I need to programmatically create an image style to use with a new media type.

I found the core/profile/standard/config/optional/image.style.max\_1300x1300.yml file whose content is the following one.

```
name: max_1300x1300
label: 'Max 1300x1300'
effects:
  04caae9a-fa3e-4ea6-ae09-9c26aec7d308:
    id: image_scale
    data:
      width: 1300
      height: 1300
      upscale: false
    weight: 1
    uuid: 04caae9a-fa3e-4ea6-ae09-9c26aec7d308
langcode: en
dependencies:
  module:
    - responsive_image
  enforced:
    module:
      - responsive_image

```

I take I need to create a file in config/install, named `image.style.<image_style_id>.yml`, with those attributes.

What UUID values should I use?

# Answer
In answering this question, I assume that you have generated your configuration via UI, and then exported it, as Kevin mentioned in his comment. This is the best way to create the initial config for inclusion in your project.

*Note that all examples are shown using procedural code for simplicity's sake; be sure to follow best practices and inject your services when building your project.*

---

## ImageStyle entity

Once that configuration file is installed, it becomes an **ImageStyle** configuration entity, and can be manipulated like any configuration entity.

```
// Get the storag ehandler for ImageStyle entities.
$image_style_storage = \Drupal::entityTypeManager()->getStorage("image_style");
// Get an instance of our ImageStyle entity.
$my_image_style = $image_style_storage->load("my_image_style");

```

The effects that are specified in the ImageStyle definition are plugins managed by the `plugin.manager.image.effect` plugin manager service.

As luck would have it, the **ImageStyle** entity offers the `addImageEffect()` public method, which accepts an array of effects info. This method actually takes care of generating and assigning the UUID, which is then returned to you.

```
public function addImageEffect(array $configuration) {
    $configuration['uuid'] = $this->uuidGenerator()->generate();
    $this->getEffects()->addInstanceId($configuration['uuid'], $configuration);
    return $configuration['uuid'];
  }

```

So, using your `image.style.max_1300x1300` example, assigning the image effect would look like:

```
$effect_uuid = $my_image_style->addImageEffect([
  'id' => 'image_scale',
  'data' => [
      'width' => '1300',
      'height' => '1300',
      'upscale' => FALSE,
   ],
   'weight' => 1,
]);

```

You can find all of the image effects registered on your site by executing: `\Drupal::service('plugin.manager.image.effect')->getDefinitions();`
> 1 votes

---
Tags: 8, media
---


# Question
Title: How do I automatically add a title to imported entities?
I have a site with a lot of audio files (using core's **Media audio** media type).

On the **Manage form display** admin page (`/admin/structure/media/manage/audio/form-fields`), I have set the **Name** field to **Disabled**.

This way, when I add a media audio entity in the UI (at `/media/add/audio`), then I don't have to add the title, and the entity name will automatically be set to the file name.

Now I want to automate media audio entity creation with the Feeds module. I configured a feed type + a feed for my media audio entities. I'm importing CSV files from a directory.

I used the following mappings:

* File ID + File Description for the media field `field_media_audio_file`
* Code for the text field `field_import_id` (for which I set the *unique* option to keep track of imports)

However, when I try to import the feed, I get this error:

> Name (name): This value should not be null.

How can I disable this validation (checking for the Name field) by the Feeds module for media audio entities?

As a workaround, I can create a column in the CSV file and list all the file names, but this results in duplicate information and presents the risk of typos.

# Answer
> 1 votes
Why not use Feeds Tamper to assign a default Name?

# Answer
> 0 votes
There is certainly a more elegant way to do this, but for now I decided to patch the validator itself in `/feeds/src/Feeds/Processor/EntityProcessorBase.php`:

```
if ($label || $label === '0' || $label === 0) {
  $messages[] = $this->t('The @entity %label failed to validate with the following errors: @errors', $args);
  if (mb_strtolower($this->entityTypeLabel()) === 'media') {
    // Media will automatically have the title set to filename, so allow this.
    return;
  }
}

```

# Answer
> 0 votes
Feeds has `presave` and `prevalidate` events. So another way to approach this is to add an event subscriber (sample code from the maintainer).

In this case, validation can be overridden with `PROCESS_ENTITY_PREVALIDATE`.

---
Tags: feeds, 9
---


# Question
Title: composer require fails because it can't delete default.services.yml
Using composer with Drupal (7, 8 & 9), `composer require drupal/<package-name>` returns the following error.

> Installation failed, reverting ./composer.json to its original content.
>
> \[RuntimeException\]
> Could not delete web/sites/default/default.services.yml

How can I fix this error?

# Answer
## Make your "local" machine work as intended, and maintain the security of your live site.

Since you want to use `composer require` command only on non-production environments, the following steps affect only on the machines you deliberately set up. Drupal's recommended configuration will be preserved on all other machines, including production servers.

Don't make this change to settings.php to avoid having it on PROD or propagating it silently to other developers' machines.

### Steps

1. enable settings.local.php (here are the instructions from the docblock in settings.local.php):

```
 * To activate this feature, copy and rename it such that its path plus
 * filename is 'sites/default/settings.local.php'. Then, go to the bottom of
 * 'sites/default/settings.php' and uncomment the commented lines that mention
 * 'settings.local.php'.
 *
 * If you are using a site name in the path [... read about exceptions in file]

```
2. set file permissions to allow *user* and *group* to write to the file on your local machine:

```
$ chmod ug+w {name_of_docroot}/sites/default

```

### How this approach matches up with the established community approach

By default, settings.local.php contains the following line:

```
$settings['skip_permissions_hardening'] = TRUE;

```

This line tells Drupal to avoid resetting permissions on the `default` folder *only* on your local, and allows you to work more smoothly with composer on your local without weakening permissions on any other copy of the codebase.
> 24 votes

# Answer
This command will fix it temporarily:

```
chmod u+w web/sites/default

```

But Drupal will harden permission again soon. To turn it off add this to `settings.php`:

```
$settings['skip_permissions_hardening'] = TRUE;

```

Source: https://www.drupal.org/docs/develop/using-composer/starting-a-site-using-drupal-composer-project-templates#s-troubleshooting-permission-issues-prevent-running-composer
> 16 votes

# Answer
I think you need to use

```
chmod ug+w web/sites/default

```

Without the g (group write permission) twig can't create it's tmp directories in files/php/twig and the site will throw a warning.
> 5 votes

# Answer
The issue is due to write permission. I resolved it by running the following commands.

```
chmod u+w sites/default
composer update
composer require drupal/mail_safety

```
> 0 votes

---
Tags: composer
---


# Question
Title: Unable to delete a tempstore that contains an en dash or an em dash
I am trying to delete a shared temporary storage for a key containing an en dash or an em dash.

```
$keyword = '2020–2021';
$tempstore = \Drupal::service('tempstore.shared')->get('my_module_name');
$tempstore->delete($keyword);

```

It throws this exception.

> Drupal\Core\Database\DatabaseExceptionWrapper: SQLSTATE\[HY000\]: General error: 1267 Illegal mix of collations (ascii\_general\_ci,IMPLICIT) and (utf8mb4\_general\_ci,COERCIBLE) for operation '=': `DELETE FROM {key_value_expire} WHERE ("name" IN (:db_condition_placeholder_0)) AND ("collection" = :db_condition_placeholder_1);` Array ( \[:db\_condition\_placeholder\_0\] =\> 2020—2021 \[:db\_condition\_placeholder\_1\] =\> tempstore.shared.my\_module\_name ) in Drupal\Core\KeyValueStore\StorageBase-\>delete() (line 52 of core/lib/Drupal/Core/KeyValueStore/StorageBase.php).

As far as I can tell, it's not an issue with the database, but rather with having the en dashes or em dashes in the storage key. I've tried escaping it with `Html::escape()` and `utf8_encode()`, but it didn't resolve the issue.

EDIT: I checked what my local database collation is and it returns UTF8.

> mysql\> SELECT DEFAULT\_CHARACTER\_SET\_NAME, DEFAULT\_COLLATION\_NAME -\> FROM INFORMATION\_SCHEMA.SCHEMATA WHERE SCHEMA\_NAME = 'drupal9'; +----------------------------+------------------------+ | DEFAULT\_CHARACTER\_SET\_NAME | DEFAULT\_COLLATION\_NAME | +----------------------------+------------------------+ | utf8 | utf8\_general\_ci | +----------------------------+------------------------+

EDIT2:

Running the following queries fixed the issue:

```
ALTER TABLE `key_value_expire` CHANGE `name` `name` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'The key of the key/value pair.';

ALTER TABLE `key_value_expire` CHANGE `collection` `collection` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'A named collection of key and value pairs.';

```

# Answer
> 2 votes
That happens because the character set the database is using isn't *utf8mb4* or the collation isn't *utf8mb4\_unicode\_ci* (or *utf8mb4\_general\_ci*). Check also which collation the single database tables and the fields they contain use, and change it when necessary.

Install Drupal / Step 3: Create a database suggests those values for the database used from Drupal.

> Note: The database should be created with UTF-8 (Unicode) encoding (*utf8mb4*) and either the *utf8mb4\_unicode\_ci* or the *utf8mb4\_general\_ci* collation. The difference between the two collations relates to how fast they are in character comparison and sorting. *utf8mb4\_general\_ci* is slightly faster and *utf8mb4\_unicode\_ci* is more accurate for a wider range of characters. If you are unsure use *utf8mb4\_unicode\_ci*.

If you are using UTF-8 characters for values that are saved in the database, you will have issues, if the database is set to use ASCII as character code for its tables.

---
Tags: 9
---


# Question
Title: How to access webform field labels in a twig template?
The YAML below represents a webform. Theming is simple using the twig template also found below, but the label for email is inline with the input field by default. How can the labels in the webform be accessed through twig for further theming?

**Webform YAML**

```
name:
  '#title': Name
  '#type': textfield
  '#required': true
  '#default_value': '[current-user:display-name]'
email:
  '#title': Email
  '#type': email
  '#required': true
  '#default_value': '[current-user:mail]'
subject:
  '#title': Subject
  '#type': textfield
  '#required': true
  '#test': 'Testing contact webform from [site:name]'
message:
  '#title': Message
  '#type': textarea
  '#required': true
  '#test': 'Please ignore this email.'
actions:
  '#type': webform_actions
  '#title': 'Submit button(s)'
  '#submit__label': 'Send message'

```

**webform--contact.html.twig**

```
<div class="container">
    <form{{ attributes }}>
        <div class="row">
            <div class="col-md-6">
            {{ element.elements.name }}
            {{ element.elements.email }}
            {{ element.elements.subject }}
            </div>
            <div class="col-md-6">
            {{ element.elements.message }}
            {{ element.form_token }}
            {{ element.form_build_id }}
            {{ element.form_id }}
            {{ element.elements.actions }}
            </div>
        </div>
    </form>
</div>

```

# Answer
> 3 votes
Your last comment:

> Well that isn't very intuitive. It would be nice to just access everything directly in the twig template.

OK, then try different templates:

When the form theme wrapper is executed the inside of the wrapper is already rendered in `{{ children }}`. Don't try to render the form again, use this template only for the form tag and the outside container:

**webform--contact.html.twig**

```
<div class="container">
   <form{{ attributes }}>
   {{ title_prefix }}
   {{ children }}
   {{ title_suffix }}
   </form>
</div>

```

Use for the inside of the form the #theme template itself:

**webform-submission-form--contact.html.twig**

```
    <div class="row">
        <div class="col-md-6">
        {{ form.name }}
        {{ form.email }}
        {{ form.subject }}
        </div>
        <div class="col-md-6">
        {{ form|without('name', 'email', 'subject') }}
        </div>
    </div>

```

Finally you can theme the form element in **form-element--webform-email.html.twig**

# Answer
> 1 votes
you are very close !

all you need to do is this

```
<label>
  {{ element.elements.name["#title"] }}
</label>

// just run to get all possible element, array values  {{ dump(element.elements.email) }}

```

# Answer
> 0 votes
Create a tempalte

```
webform-submission-form--{webform_machine_name}.html.twig
Ex. webform-submission-form--contact-us.html.twig

{{ form.elements.field_machine_name }}
Ex. {{ form.elements.your_name }}
    {{ form.elements.email_address }}

    {{ form.elements.actions }}
    {{ form.form_build_id }}
    {{ form.form_token }}
    {{ form.form_id }}

```

Make sure that you added also form\_token, form\_build\_id and form\_id

```
    {{ form.form_build_id }}
    {{ form.form_token }}
    {{ form.form_id }}

```

---
Tags: 8, theming, webforms
---


# Question
Title: Is there a way to set a <div> wrapper around a webform without customizing the webform?
I would like to add a `<div>` wrapper around a webform. Is there a way to define the wrapper without customizing the webform?

# Answer
> 3 votes
You do this via the YAML source

```
'#prefix': '<div class="custom-wrapper">'
'#suffix': '</div>'
textfield:
  '#type': textfield
  '#title': textfield

```

I did find a bug that I created a ticket for in the Webform issue queue and posted a patch. I recommend using the above approach with the patch.

# Answer
> 0 votes
It's a bit difficult to tell what you mean by "without customizing the webform", but if you mean "without editing the webform configuration of each webform," then you can theme webforms like any other entity in Drupal.

If you check the `webform/templates` directory, you will see the file `webform.html.twig`. You can copy this file into your site's theme `templates` directory and add the `<div>` wrapper in this file.

After you rebuild the site's cache, all webforms will now have the `<div>` wrapper that you added to `webform.html.twig`.

---
Tags: webforms
---


# Question
Title: How can I allow anonymous users to see the file for the exported webform submission data?
On Drupal 9.2.1, I have a data export set up for webform submission fields in a XML file which is imported by another site.

When I am logged-in, I can view the .xml without issues. Since the permission to view webform submissions is only given to administrator users, the anonymous users see an empty page.

How can I allow anonymous users to see the file for the exported webform submission data?

# Answer
> 0 votes
For using submission data in a view is controlled by the "View submission data" permissions for the webform. Exposing the data opens the results page to the anonymous user which is not desired.

A solution that I found is the Webform Content Creator module. This will allow you to map webform submission data to a content type so it can be used in a view or xml file.

Its not the perfect solution but is a solution if anyone else is having this issue.

---
Tags: webforms, 9
---


# Question
Title: site redirecting to core/install.php after migration
I have migrated my site to different server and I am redirected to install.php page.

Here is the steps I have done:

1. zip whole site and extract it in new server.
2. export database and import it to new database (using phpmyadmin)
3. modify database credential in site/defaults/setting.php

any idea why drupal redirects to install page?

# Answer
I encountered the same issue today (my site kept redirecting to install.php after migration to new host) and spent half-a-day troubleshooting. The db connection was OK. I double-checked that the db-name, db-user, and db-user-pass are correct in the site/defaults/setting.php In the end, it turned out that when I exported the database from my previous hosting, the names of the tables were prepended with a prefix. After importing the tables in the new database, I didn't specify the prefix in the settings.php file. Therefore, drupal was not able to locate the correct tables, because it looked for the *users* table but in the db, that table was actually named *prefix\_users* and so on.

$databases\['default'\]\['default'\] = array ( 'database' =\> '', 'username' =\> '', 'password' =\> '', **'prefix' =\> '!!!',** 'host' =\> 'localhost', 'port' =\> '', 'namespace' =\> 'Drupal\Core\Database\Driver\mysql', 'driver' =\> 'mysql', );

Hope it helps!
> 1 votes

# Answer
Maybe it's file permission problem. Try to set the owner of the web-root of Drupal installation:

```
chown -R YOUR-USER:WEBSERVER-USER .

```

Especially it's file permission problem of the settings.php. If your web server can't read this file, the new install process is started and redirects to /core/install.php

If it helps so you can go on with more secure file permission setting described here: https://www.drupal.org/node/244924
> 0 votes

---
Tags: 8
---


# Question
Title: How can I customize the 403 page for specific routes?
On a D9 site, with an existing custom 403 page twig. I've been requested to show a different, variable, message from the "standard one" for a couple of specific routes.

I've tried with `theme_preprocess_page__403(&$variables)` but I couldn't determine the original route.

E.g. using `\Drupal::routeMatch()->getRouteName()` I got *system.403* instead of the route name I need to check. I've checked solutions to find the refer route but none of them seemed to work.

Actually the two routes that need this specific 403 are created programmatically with a **routing.yml* and relative controller in a custom module.

I wonder if it is possible somehow to specify the redirect path if the route *requirements* fails. I didn't find any documentation about, but that would another way to implements this requirement.

# Answer
The 403 error page is not a redirect, so there is no referer. It's rendered in a sub-request which by default is using the route `system.403`.

From inside of the sub-request you can get the route name of the original request with

```
\Drupal::routeMatch()->getMasterRouteMatch()->getRouteName()

```
> 6 votes

---
Tags: theming, routes, 9
---


title: psr/log requires PHP 8

text:
# Question
Title: psr/log requires PHP 8
I'm running Drupal 8.9.16 with PHP 7.4.12 While attempting to run composer update today I saw this error for the first time:

```
  Problem 1
    - Root composer.json requires psr/log dev-master -> satisfiable by psr/log[dev-master].
    - psr/log dev-master requires php >=8.0.0 -> your php version (7.4.12) does not satisfy that requirement.
  Problem 2
    - psr/log dev-master requires php >=8.0.0 -> your php version (7.4.12) does not satisfy that requirement.
    - backupmigrate/core dev-master requires psr/log dev-master -> satisfiable by psr/log[dev-master].
    - Root composer.json requires backupmigrate/core dev-master -> satisfiable by backupmigrate/core[dev-master].

```

I'm not sure what these mean; do I need to update to PHP 8? According to `https://www.drupal.org/docs/system-requirements/php-requirements` it is not supported by Drupal 8. This sounds like a good time to update to 9, which I planned on doing soon anyway. Are there issues I will be running up against if I upgrade?

# Answer
> 3 votes
> Root composer.json requires psr/log dev-master

Well, that's not something that Drupal requires. Drupal specifies `"psr/log": "^1.0"` in both Drupal 8.x and Drupal 9.x. If dev-master is in your composer.json, then you had to put it there yourself.

# Answer
> 2 votes
That composer.json file requires the Backup and Migrate Core library which, in its composer.json file, is identified as *backupmigrate/core*. That library requires psr/log dev-master, while Drupal 8 in its composer.json file requires psr/log ^1.0.

Probably that library is added in that composer.json file because it's required from the Backup and Migrate for Drupal 8 module, but it's not required from Drupal core.

The *Backup and Migrate Core* library and the *Backup and Migrate for Drupal 8* module haven't been update in at least 4 years. Probably, at the time of the last commit, the psr/log (dev-master) library didn't require PHP 8.
They should update their dependencies and require a different version of psr/log.

The Backup and Migrate module hosted on drupal.org doesn't have that problem, as its composer.json file doesn't require a version of the psr/log library different from the version required by Drupal core. The Backup and Migrate Core library is included together the module and it uses the same version of psr/log required from Drupal core.
If you need the *Backup and Migrate* module, you should use the version hosted on drupal.org, not the version hosted on github.com.

---
Tags: installation
---


title: Example hook_pathauto_pattern_alter

text:
# Question
Title: Example hook_pathauto_pattern_alter
I do not understand the hook. I would expect, that "pattern\_alter" would allow me to "alter" the "pattern". But this seems to be not the case.

I tried also to alter the alias... which also does not seem to have an effect.

Could somebody show me a working example please?

```
function xxx_pathauto_pattern_alter(\Drupal\pathauto\PathautoPatternInterface &$pattern, array $context) {

  /* //////////////////////////////////////////////////////////////////////////////////
  ////    article_type - override path logic for *archived* nodes ('/archiv/[node::title]')
  /* ///////////////////////////////////////////////////////////////////////////////////*/
  if( $context['op'] === "update" && $context['bundle'] === "news") {

    $node = $context['data']['node'];
    $archived = $node->get('field_archived')->getString() === "1";
    if ($archived) {

      $pattern->setPattern('/archive/[node::title]');
      dpm($pattern); //WORKS !!! in object only. Pattern will not change in real world.
    }
  }
}

function xxx_pathauto_alias_alter(&$alias, array &$context) {
  /* //////////////////////////////////////////////////////////////////////////////////
    ////    article_type - override path logic for *archived* nodes ('/archive/[node::title]')
    /* ///////////////////////////////////////////////////////////////////////////////////*/
  if ($context['op'] === "update" && $context['bundle'] === "news") {

    $node = $context['data']['node'];
    $archived = $node->get('field_archived')->getString() === "1";
    if ($archived) {
      $alias = "/archive/nope";
      dpm($alias); //WORKS !!! in function only. Alias will not change in real world.
    }
  }

```

# Answer
> 4 votes
`hook_pathauto_pattern_alter()` is only invoked when:

* The entity has a *path* field
* Pathauto processing is enabled
* For entities that support revisions, the entity is using the default revision
* A default pattern has been set for that entity
* `$entity->toUrl()->getInternalPath()` doesn't throw a `EntityMalformedException`, `UndefinedLinkTemplateException`, or `UnexpectedValueException` exception

The shown hook is also only invoked when an entity is updated, not when an entity is created.
When the Pathauto module has been set not to change an existing path alias, even if `hook_pathauto_pattern_alter()` were invoked, the path alias wouldn't be changed.

As side note, the hook could should first check the entity for which the hook is invoked is a node, which is what the example hook in pathauto.api.php does.

```
/**
 * Alter the pattern to be used before an alias is generated by Pathauto.
 *
 * This hook will only be called if a default pattern is configured (on
 * admin/config/search/path/patterns).
 *
 * @param \Drupal\pathauto\PathautoPatternInterface $pattern
 *   The Pathauto pattern to be used.
 * @param array $context
 *   An associative array of additional options, with the following elements:
 *   - 'module': The module or entity type being aliased.
 *   - 'op': A string with the operation being performed on the object being
 *     aliased. Can be either 'insert', 'update', 'return', or 'bulkupdate'.
 *   - 'source': A string of the source path for the alias (e.g. 'node/1').
 *   - 'data': An array of keyed objects to pass to token_replace().
 *   - 'bundle': The sub-type or bundle of the object being aliased.
 *   - 'language': A string of the language code for the alias (e.g. 'en').
 *     This can be altered by reference.
 */
function hook_pathauto_pattern_alter(\Drupal\pathauto\PathautoPatternInterface $pattern, array $context) {
  // Switch out any [node:created:*] tokens with [node:updated:*] on update.
  if ($context['module'] == 'node' && ($context['op'] == 'update')) {
    $pattern->setPattern(preg_replace('/\[node:created(\:[^]]*)?\]/', '[node:updated$1]', $pattern->getPattern()));
  }
}

```

The code for the shown hook would be similar to the following one.

```

use Drupal\pathauto\PathautoPatternInterface;

function mymodule_pathauto_pattern_alter(PathautoPatternInterface $pattern, array $context) {
  if ($context['module'] == 'node' && $context['op'] === "update" && $context['bundle'] === "news") {
    $node = $context['data']['node'];
    $archived = $node->get('field_archived')->getString() === "1";
    if ($archived) {
      $pattern->setPattern('/archive/[node::title]');
    }
  }
}

```

Objects are already passed by reference; it's not necessary to define the first parameter as `&$pattern`.

I would also verify there aren't other modules implementing `hook_pathauto_pattern_alter()` for which their implementation is invoked after the implementation shown in the question, and that is altering the pattern for the same entity and the same bundle.

### References

---
Tags: hooks, path-aliases
---


# Question
Title: How to change the order of fields in the Drupal Commerce Checkout Form
I'm using Drupal Commerce 7.x. I have added some fields to the checkout form in the customer profile. Specifically I've added 'Title' and 'Organization'. I'd like to move some of the fields around because they aren't in the order I'd like, but I can't figure out how to move them.

For example, right now the order is: 1. Country (I def. don't want that first) 2. Full name 3. Address etc.

I want it like this:

1. Full Name
2. Title (new field)
3. Organization (new field)

I tried using a module that does this (just as an example, obviously, since only two fields are listed here). Am I on the right track?

```
<?php
function CommerceAlter_form_commerce_checkout_form_alter(&$form,
&$form_state, &$form_id) {
   $order = array('edit-customer-profile-billing-field-title',
'addressfield-container-inline');
    foreach ($order as $key => $value){
      if (isset($form[$value])){
        $form[$value]['#weight'] = $key;
      }
    }
}

```

But it didn't do anything.

Note: I was unsure how to reference the fields. The first one above called 'field-title' is the ID for that field and the second listed for addressfield (which is in the form by default) is by class .addressfield-container-inline).

# Answer
Changing field order on the checkout form can be done by going to admin/commerce/config/checkout

Then just drag the items up and down to arrange them in the order you wish.
> 2 votes

# Answer
Per Commerce module maintainer, there's no good way to move the pieces of the Address composite field. https://www.drupal.org/project/commerce/issues/3016940. The maintainer suggested CSS, but any solution that changes the display but not the code (e.g., flexbox) can be problematic from a semantic and accessibility standpoint. For example, reordering elements visually can create confusion when using screenreaders https://www.w3.org/TR/css-flexbox-1/#order-accessibility.

It's also worth noting that country is intentionally the first field. Some countries use Last name and then First name. So, changing the country to Japan, for example, changes the order of the name fields.
> 0 votes

# Answer
You have to make sure they are in the order you want in the render array. When setting #weight does not work, you can change the order by removing and re-adding items from the render array.

```
$shipping_profile = $variables['elements']['shipping_profile'];
unset($variables['elements']['shipping_profile']);
$variables['elements']['shipping_profile'] = $shipping_profile;

```

This removes the element 'shipping\_profile' from its current place in the render array and places it back at the end of the render array, causing it to be shown last on the checkout pane you are editing. I myself used this on a hook\_preprocess\_commerce\_checkout\_pane\__shipping\_information hook to alter the order of some items inside the shipping information in my checkout flow.
> 0 votes

---
Tags: commerce
---


title: Change View head title programmatically

text:
# Question
Title: Change View head title programmatically
I have a view of taxonomy terms with exposed filter. Main view page: site.com/view

I have a text field with 16 different values and urls:

* site.com/view/1
* site.com/view/2
* site.com/view/...
* site.com/view/16

Depending on passed argument I change View title like this:

```

use \Drupal\views\ViewExecutable;
function theme_views_pre_render(ViewExecutable $view)
{

  if( $view->id() == 'MY_VIEW_ID' && $view->current_display === 'VIEW_DISPLAY' && $view->args[0] != 'All')
  {
    $view->setTitle(gamesGenreTitle($view->args[0]));
  }
}

function gamesGenreTitle($val)
{
  $options = options_allowed_values(\Drupal::service('entity_field.manager')->getFieldStorageDefinitions('taxonomy_term')['field_genre']);
  return $options[$val];
}

```

gamesGenreTitle() is getting labels of my field in order to put them to the title.

It works, but it is not changing the head `<title>` tag!

I've tried `theme_preprocess_html(&$variables)` with this code:

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

  $view = \Drupal\views\Views::getView($view_id);

```

But it only gets the `view id` and I can't access args there in order to change title on only needed pages.

My second guess, which I haven't tried yet, is to validate and explode to array current path, using `\Drupal::service('path.current')->getPath();`, get the last digit and pass it to `gamesGenreTitle()`.

Or maybe there is better way?

# Answer
> 1 votes
Don't necessarily need to access the view object ($view) to get the arguments. You can check all arguments by doing so

```
$params = Drupal::routeMatch()->getParameters();

```

Usually you'll find that if you are accesing a view **with contextual filters/parameters** there will be "arg\_0, arg\_1" parameter keys

```
var_dump($params);
// object(Symfony\Component\HttpFoundation\ParameterBag)#323 (1) { ["parameters":protected]=> array(4) { ["view_id"]=> string(18) "sample_view" ["display_id"]=> string(6) "page_1" ["arg_0"]=> string(26) "251" } }

```

Then you can do

```
$params = Drupal::routeMatch()->getParameter('arg_0');

```

---
Tags: 8
---


# Question
Title: How to hide a form element when a datetime widget is filled using #states
The following code is working well to hide a button when a textfield is filled, but it is not working when a datetime widget is encoded:

```
$form['my_button'] = [
  '#type' => 'container',
  'submit' => [
    '#type' => 'submit',
    '#value' => t("Click on me"),
    '#submit' => ['submit_me']),
    '#states' => [
      'visible' => [
        ':input[data-drupal-selector=selector-of-my-text-field]' => [
          'filled' => FALSE,
        ],
      ],
    ],
  ],
];

```

Any hint?

# Answer
> 1 votes
"filled" won't work for date elements, but you can check if it is not empty with:

`['!value' => '']`

---
Tags: forms
---


# Question
Title: Display field label (not key) as views page title in contextual filter
In continuation of these questions:

I have taxonomy terms of games and a View representing them. Each game has a select-type of field called "genre" with "key|label" format. There are 16 genres, stored like that (default language is russian):

Then I have configured my View's **Contextual filter** like this:

Tried with "**RAW value from URL**" - no changes.

And it works fine with exposed filter as well as accessing URLs like `/game/2` or `/games/13`. But it displays page title as field KEY, as a number.

All I want to do is to output corresponding LABEL.

Theoretically I could use just values in this field, but it will provide two more problems:

1. I can't change field's storage options without losing current data.
2. Genres are in Russian, so there will be URL issues like this - `.../?field_genre_value=%D0%90+%D1%8D%D1%82%D0%BE+%D1%82%D1%80%D0%B5%D1%82%D0%B8%D0%B9`

Is there a way to solve this?

# Answer
> 0 votes
Finally figured it out! Posting my answer for future generations.

All we need is `YOUR_TEMPLATE.theme` file for this.

Below is my code with comments. It might not be perfect, so if anyone will correct some things I will appreciate that.

```
use \Drupal\views\ViewExecutable;

// Changing views title. It does not change HEAD <title> tag!
function YOUR_THEME_NAME_views_pre_render(ViewExecutable $view)
{
  // checkRoute() and checkArg() are custom functions and described below
  if(checkRoute('view.VIEW_ID.VIEW_DISPLAY_ID') && checkArg())
  {
    // This changes view title, as well as setting $variables['page']['#title'] to the same value.
    // gamesGenreTitle() is custom function and described below.
    $view->setTitle(gamesGenreTitle($view->args[0]));
  }
}

// Here we can change HEAD <title>
function YOUR_THEME_NAME_preprocess_html(&$variables)
{
  // checkRoute() and checkArg() are custom functions and described below
  if (checkRoute('view.VIEW_ID.VIEW_DISPLAY_ID') && checkArg() && isset($variables['head_title']))
  {

    // Unnecessary piece, tokens are needed for my purpose
    $token = Drupal::token();

    // $variables['page']['#title'] was changed in views_pre_render(), so we can change HEAD <title>.
    // I use [current-page:page-number] token to uniqueize the title
    // To improve this, we can add logic to inlcude current page number only if there is more than 1 page
    $variables['head_title'] = $variables['page']['#title'] . " | Page " . $token->replace('[current-page:page-number]');
  }
}

// In case you're using current page title in breadcrumbs, might want to change it too.
function YOUR_THEME_NAME_preprocess_breadcrumb(&$variables)
{
  // checkRoute() and checkArg() are custom functions and described below
  if(checkRoute('view.VIEW_ID.VIEW_DISPLAY_ID') && checkArg() && isset($variables['breadcrumb']['2']['text']))
  {
    // You might want to var_dump($variables) before doing this trick in order to find your piece of breadcrumb.
    $variables['breadcrumb']['2']['text'] = gamesGenreTitle(getArg_0());
  }
}

// Getting allowed values of field (labels) used to make title
function gamesGenreTitle($val)
{
  $options = options_allowed_values(\Drupal::service('entity_field.manager')->getFieldStorageDefinitions('taxonomy_term')['field_NAME']);

  // Check if we are passing correct data
  if(is_numeric($val) && $val <= count($options))
  {
    return $options[$val];
  }
}

// Check if needed argument is set and numeric.
function checkArg()
{
  $arg = Drupal::routeMatch()->getParameter('arg_0');
  // In my case argument from views was passed to arg_0
  // It may vary, so try to var_dump($arg) or ksm($arg) to check if it is what you need

  return isset($arg) && is_numeric($arg);
}

// Checking current route, we need exact view and display, otherwise title will be changed on every page.
function checkRoute($check)
{
  $route = \Drupal::routeMatch()->getRouteName();
  return $route == $check;
}

// Getting arguments, passed to views.
function getArg_0()
{
  // And again, arg_0 might not be your argument, double check it with var_dump() or ksm()
  return Drupal::routeMatch()->getParameter('arg_0');
}

```

And another method, if you don't have a lot of field labels, you can use this in views title override field (twig is supported there):

`{% if arguments.field_NAME_value == 1 %} YOUR TITLE 1 {% elseif arguments.field_NAME_value == 2 %} YOUR TITLE 2 {% endif %}`

Hope this will help someone!

---
Tags: views
---


# Question
Title: Use hook_entity_presave to convert multiple lines in a field to separate values in a multi-value field?
I have a field defined as 'long text' that allows infinite number of values. The difficulty is that users are entering everything in one iteration of the field. So, I need to get the value they have entered, explode it and create separate multi-value field entries. But... my approach isn't working:

```
function builder2020_entity_presave(EntityInterface $entity){
  switch ($entity->bundle()) {
    case 'ec_topics':
      $count = count($entity->field_ec_subtopics);//check if the user has only used one field
      if ($count == 1){ //user has put everything in one field value
        $values = array(explode('\n',$entity->field_ec_subtopics->value)); create array from the field value
          $entity->field_subtopics->value = $values; //feed the array to the field
      }
      $entity->field_sub_topic_count->value = $count; //set the number of ec_topics
      break;

```

I 'think' I'm close, but I can't seem to figure out where I'm falling down.

# Answer
```
case 'ec_topics':
      $count = count($entity->field_ec_subtopics);
      if ($count == 1){
        $values = $entity->field_ec_subtopics->getValue();
        $content = $values[0]['value'];
        $items = explode(PHP_EOL,$content);
        $count = count($items);
        $entity->field_ec_subtopics = $items;
      }
      $entity->field_sub_topic_count->value = $count;
      break;

```
> 0 votes

---
Tags: hooks
---


# Question
Title: How do I programmatically update the allowed values of a list field?
I have created a *field\_time\_zone* field for the *Article* content type. I want to set the allowed values for that field to the values returned from `system_time_zones()`.

For this, I implemented `hook_form_alter()` using the following code.

```
$zones = system_time_zones();
$entityManager = \Drupal::service('entity_field.manager');
$fields = $entityManager->getFieldStorageDefinitions('node', 'local_market');
$options = options_allowed_values($fields['field_time_zone']);

if(empty($options)) {
$options =  $zones;
$form['field_time_zone']['widget']['#options'] = $options;
}

```

The code adds the desired values, but the node cannot be saved, as it throws the following error.

> The value you selected is not a valid choice.

How can I set the allowed values for a *text (list)* field?

# Answer
> 23 votes
You can't do this in a form alter hook, because the entity field validation will fail.

You have to add a function to the field settings. This is not in the field UI, so you have to export the configuration and change the field in *field.storage.node.field\_time\_zone.yml*:

```
type: list_string
settings:
  allowed_values: {  }
  allowed_values_function: 'mymodule_allowed_values_function'

```

Reimport the configuration. Then you can implement this function in *mymodule.module* to set the options dynamically:

```
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\field\Entity\FieldStorageConfig;

  function mymodule_allowed_values_function(FieldStorageConfig $definition, ContentEntityInterface $entity = NULL, $cacheable) {
    $options = [
      ...
    ];
    return $options;
  }

```

See https://chromatichq.com/blog/dynamic-default-and-allowed-values-list-fields-drupal-8

---

For the question added later:

**How can I set allowed value options to a field of type text(list) and save it accordingly?**

The question originally was what to do with the code which doesn't work in form alter, where you can place it instead.

If you mean with this question you have a static allowed value list, then you can copy and paste the list in the field settings UI and save it:

And now it is stored in the mentioned yaml file of the exported configuration here:

```
  allowed_values: {  }

```

# Answer
> 5 votes
After many hours i finally found solution. I dynamically created options for multi select field and got error message on submit that choosen select in wrong option.

It requires add new options to allowed\_values for that field. Here is the solution:

```
 //load your field
 $field_purchasers = FieldStorageConfig::loadByName('user', 'field_xx');
 //subscribe new options to this field
$field_purchasers->setSetting('allowed_values_function','module_name_allowed_values_function' );
//save configuration
$field_purchasers->save();

```

In your .module file write in callback function :

```
function module_name_allowed_values_function(FieldStorageConfig $definition, ContentEntityInterface $entity = NULL, $cacheable) {
  $options = [
    1 => 'My new option 1',
    2 => 'My new option 2',
    3 => 'My new option 3',
   ];
  return $options;
}

```

# Answer
> 0 votes
For me getting the actual options and altering them did the work

```
$options = $form['field_name']['widget']['#options'];
unset($options['key']);
$form['field_name']['widget']['#options'] = $options;

```

# Answer
> -3 votes
You should override the allowed values of the storage in your form alter:

```
// Retrieve the storage.
$fieldStorage = \Drupal\field\Entity\FieldStorageConfig::loadByName('node', 'local_market');

// Retrieve the current allowed field values.
$allowedValues = $fieldStorage->getSetting('allowed_values');

// Set your new allowed field values.
$allowedValues['field_time_zone'] = $zones;
$fieldStorage->setSetting('allowed_values', $allowedValues);

// Save.
$fieldStorage->save();

```

# Answer
> -4 votes
Thanks, @Gun5m0k3. This works great. Here's a slightly adapted, more generic version.

In your form\_alter:

```
// Define your options.
$my_options = ['foo' => 'foo', 'bar' => 'bar'];

// Add the options to the field widget.
$form['field_my_field']['widget']['#options'] = array_merge(
  $form['field_my_field']['widget']['#options'],
  $my_options
);

// Ensure that the new options are also added to the allowed_values list
$fieldStorage = \Drupal\field\Entity\FieldStorageConfig::loadByName('node', 'field_my_field');
$fieldStorage->setSetting('allowed_values', $my_options);
$fieldStorage->save();

```

Is there a good reason why setting fieldStorage within a form\_alter is a bad idea? It seems to work perfectly, so I wonder why this isn't the go-to solution as it's the easiest and most straightforward to implement.

J.

---
Tags: 8, nodes
---


# Question
Title: Drush make, git repository checkout specific subdirectory
I've got a make file in which I want to pull in a remote Git repository and only fetch a subdirectory. I've tried as following:

```
projects[example_module][type] = "module"
projects[example_module][download][type] = "git"
projects[example_module][download][url] = "git@bitbucket.org:team/example_modules.git"
projects[example_module][download][subtree] = "example_module_subdir"

```

Though, this creates a `example_module` folder where I expect it to be, though it contains the entire repository. What am I overlooking? Is this impossible? (using `Drush 7.0.0`)

# Answer
> 1 votes
The `[subtree]` only works if the download is an archive. See Project download options page for drush 7.x.

# Answer
> 0 votes
If you are working with public repo you can play with the zip file generated by the repository

You need to open the zip file to get the structure of files inside the zip. And reproduce the same structure in the *subtree* parameter(github for example add a prefix with the tag to the directory inside the zip)

Example

```
libraries[views_civicrm_documents][destination] = "modules/contrib"
libraries[views_civicrm_documents][directory_name] = "views_civicrm_documents"
libraries[views_civicrm_documents][download][type] = "get"
libraries[views_civicrm_documents][download][url] = "https://github.com/CiviCooP/org.civicoop.documents/archive/refs/tags/v1.2.zip"
libraries[views_civicrm_documents][download][subtree] = "org.civicoop.documents-1.2/drupal/views_civicrm_documents"

```

---
Tags: 7, version-control, drush
---


# Question
Title: How can I receive and process form data submitted from an external site?
I'm working on a CRM implementation in Drupal for a client and they have an existing website with forms on for people to make enquiries and so on. They would like the data submitted via those forms to automatically become entities in the CRM.

I could replace the forms with webforms from the Drupal site but that would be clunky, as they would have to either be in iframes, or users would be taken to a separate site which would have to be styled the same and so on.

So ideally I would like to have their existing forms on the remote site POST the data to the Drupal server and then use that data to populate Drupal entities.

The only way that comes to mind is to have a PHP script on the server which processes the POST data and then bootstraps Drupal and creates the entity. But that seems somewhat clunky too. I'm wondering if there is a more Drupally way to do it.

Could Feeds be relevant I wonder? Could it be a custom feed type?

I'm interested in any ideas people have. Thanks!

# Answer
> 0 votes
## Feeds

If you want to consume external data and produce entities from those data, then Feeds is the way to go. This is it's primary use case. Feeds is also a mature and well-known module with many tutorial resources on the Internet. Here is one that I think is suitable to your needs: https://www.drupal.org/docs/contributed-modules/feeds/creating-and-editing-import-feeds

## REST API

The one "gotcha" to this solution is that Feeds relies on pulling data. If, instead, you must originate the request on the remote server, then Feeds won't help. Instead, you'll need to implement Drupal's REST API. Here is a reference: https://www.drupal.org/docs/8/core/modules/rest/3-post-for-creating-content-entities

## Summary

The Feeds solution is faster and easier to implement, so, to whatever degree that you have control, I recommend making the remote data available via URL (e.g. via RSS) and then consuming it with Feeds, which can be set to execute on a regular basis. There are also a number of handy companion modules for Feeds, such as Feeds Tamper and Feeds Extensible Parsers.

---
Tags: 8
---


# Question
Title: Integrating jQuery Auto Height with Views Infinite Scroll
I have a views block with an infinite scroll (using Views Bootstrap and Views Infinite Scroll modules). The block displays cards and I want them to have the same height. jQuery Auto Height does that well. However, it only happens for the initial load. Auto Height has no way of knowing to fire on subsequent Ajax calls. What is the best way to integrate them so that Auto Height is called on each infinite scroll Ajax call?

# Answer
> 0 votes
If you take a look at the source for the jQuery Auto height module, there appears to be an `AutoHeight()` method that you can call on a given jQuery object.

```
$(drupalSettings.auto_height.selectors).AutoHeight();

```

And in the source for Views Infinite Scroll, we can see that an event, `scroll.views_infinite_scroll`, is available to listen in on. The portion of Views Infinite Scroll's code that invokes this event is:

```
$window.on(scrollEvent, debounce(function () {
  if (isLoadNeeded()) {
    $pager.find('[rel=next]').click();
    $window.off(scrollEvent);
  }
}, 200));

```

Using the above as a template, I think you could invoke the `AutoHeight()` method every time a new view is added.

---
Tags: 8, views
---


# Question
Title: Bulk user creation and email notification
I want to bulk create about 2-300 users with Drush on a Drupal 8 site. I want each of them to receive a welcome email and be forced to set up their own passwords. This can be done trivially with the "Notify user of new account" option through the UI but I cannot seem to make it work with Drush 9.

I can run a script that reads from a CSV and creates the user, then gives them the needed roles, however, the only option I can find for notifying the users: '--notify' throws a `notify-send command failed` error that appears to be related to Ubuntu notifications?

Is there some way to send a new account an email that I am missing?

# Answer
> 0 votes
This is probably not the "right" way to do this, but it solved my problem.

Drush wont email on your behalf but it will generate the one time link.

You can see details here, the basic format is:

`drush user:login --mail=user@example.org`

One downside is that the link generated appears to not use the name of the domain generating it. So instead of links starting with `https://my=site.com/user...` you get: `http//default/user`

There is probably some environmental variable that could be changed to fix this but it seemed easier to just cut the first 13 chars with a script and replace them with the correct domain.

If you're bulk importing you can have whatever script you have written to submit the new users also generate this link and then re-write it correctly before outputing it all to a csv file (or format of your choice.)

Then you can create your own emails in whatever bulk email system you wish with a mail merge.

This solution is not ideal but it is reasonably quick and easy and not a lot can go wrong.

---
Tags: drush
---


title: Custom translation function

text:
# Question
Title: Custom translation function
I need own translation function in my custom module where i have defined language codes ('en','ja','de'....etc) Now i just wanted to pass word and language code as a parameter and it returns translation of that word according to language code.

I am trying this inside my translation but it doesn't work it is returning 'yes' instead i don't know why.

```
 $japanese_value = t('yes', array(), array('langcode' => 'ja'));
 print_r($japanese_value);

```

And please let me know if there is a better way to do this or any other translation module.

# Answer
> 0 votes
Requiring `t()` to translate the string in a specific language is perfectly fine. The function will return a translation, if the Locale module is installed and enabled, and that string is present in the site; it doesn't use a remote service to translate the string passed as first argument.

*Present in the site* means:

* The translation has been added using the form on admin/config/regional/translate
* The translation has been imported using the form on admin/config/regional/translate/import
* The settings.php file contains a custom translation in the `$conf['locale_custom_strings_ja']` array (for Japanese). For example, the following array would allow to get the Italian translation for *Forum* and *node*. (I used Italian just because I know how to translated those words.)

```
$conf['locale_custom_strings_it'][''] = array(
  'Forum' => 'Bacheca discussioni',
  'node' => 'contenuto',
);

```

Note that in the latter case, the Local module doesn't need to be enabled.

---
Tags: 7, i18n-l10n
---