title: Alter the login form

text:
# Question
Title: Alter the login form
I am new to Drupal and I need to alter the login form add extra validation fields with adding two more date of birth and email id using ***hook\_form\_alter***. How do i do this. and how to find the login form ***$form\_id***.

# Answer
> 1 votes
Here you go, this is an example of a login form alter. Just adding some extra buttons here. This is just an example as to how to go about the alter hook, about the validation fields I am not sure.

```
/**
 * Implements hook_form_FORM_ID_alter() for login.
 */
function THEMENAME_form_user_login_form_alter(&$form, &$form_state) {
  $form['reset_password'] = [
    '#type' => 'link',
    '#title' => t('Forgot your password?'),
    '#url' => Url::fromRoute('user.pass'),
    '#id' => 'login-reset-password',
    '#weight' => 99,
  ];
  $form['register_user'] = [
    '#type' => 'link',
    '#title' => t('Create one.'),
    '#url' => Url::fromRoute('user.register'),
    '#id' => 'login-user-register',
    '#weight' => 100,
  ];
  $form['register_user']['#prefix'] = "<div class=\"form-footer\"> <span>" . t("Don't have an account?") . "</span>";
  $form['register_user']['#suffix'] = "</div>";
  $form['title_page'] = [
    '#type' => 'label',
    '#title' => t('Log in'),
    '#weight' => -99,
  ];
}

```

---
Tags: 8, forms
---


title: Accessing User Fields in Rules

text:
# Question
Title: Accessing User Fields in Rules
I have added a custom field (taxonomy reference) to my users. Now I want to run a rule based on the values in that field, but the field does not show up in the available items on the "data selection".

Any ideas on why the field does not show up in rules or how to make it show up in rules is greatly appreciated.

field configuration:

```
langcode: en
status: true
dependencies:
  config:
    - field.storage.user.field_workbench_access_groups
    - taxonomy.vocabulary.intranet_units_committees_and_gr
  module:
    - user
id: user.user.field_workbench_access_groups
field_name: field_workbench_access_groups
entity_type: user
bundle: user
label: 'User's Workbench Access Groups'
description: ''
required: false
translatable: false
default_value: {  }
default_value_callback: ''
settings:
  handler: 'default:taxonomy_term'
  handler_settings:
    target_bundles:
      intranet_units_committees_and_gr: intranet_units_committees_and_gr
    sort:
      field: name
      direction: asc
    auto_create: false
    auto_create_bundle: ''
field_type: entity_reference

```

Reaction Rule:

```
langcode: en
status: true
dependencies: {  }
id: sync_existing_user_workbench_access
label: 'Sync Existing User --> Workbench Access'
events:
  -
    event_name: 'rules_entity_update:user'
description: ''
tags: {  }
config_version: '3'
expression:
  id: rules_rule
  conditions:
    id: rules_and
    conditions:
      -
        id: rules_condition
        context_values:
          type: user
        context_mapping:
          entity: user
        context_processors:
          type:
            rules_tokens: {  }
        provides_mapping: {  }
        condition_id: rules_entity_is_of_type
        negate: false
      -
        id: rules_condition
        context_values:
          field: field_workbench_access_groups
        context_mapping:
          entity: user
        context_processors:
          field:
            rules_tokens: {  }
        provides_mapping: {  }
        condition_id: rules_entity_has_field
        negate: false
  actions:
    id: rules_action_set
    actions: {  }

```

# Answer
As @anonymous pointed out, it is answered in Access user profile data. Since that post is not well labeled in connection with rules, I will also post the answer here. In short, instead of verifying Entity is of Type, verify that entity is of bundle, specifying that both type and bundle is user. Entity of Type should work, but that it does not is (apparently) a known bug with Rules 8.x-3.x as of this time.
> 2 votes

---
Tags: 8, rules
---


# Question
Title: How to update multiple fields using ajax?
In content type there are three field . Each field are node reference to different content. Here I want to restrict value and create dependency on these field. For example: I have one auto complete field "Country". On change of "Country", select list(i.e. State) field value is updated. On change of "State", "county" field is updated. Everything is working fine.

When I change value of "Country", "State" value get change But "county" value hold previous value. How should I achieve this. How should I reset value of county

My code snippet is like

```
function module_form_alter(&$form, &$form_state, $form_id) {
  $form['field_country'][LANGUAGE_NONE]['#ajax'] = array(
    'callback' => '_state_list_callback',
    'event'    => 'change',
    'wrapper' => 'state-list',
    'progress' => array('type' => 'throbber', 'message' =>  'Please wait...'),
);
  $form['field_country']['#prefix'] = '<div id="state-list">';
  $form['field_country']['#suffix'] = '</div>';

  $form['field_state'][LANGUAGE_NONE]['#ajax'] = array(
    'callback' => '_county_list_callback',
    'event'    => 'change',
    'wrapper' => 'county-list',
    'progress' => array('type' => 'throbber', 'message' =>  'Please wait...'),
);
  $form['field_county']['#prefix'] = '<div id="county-list">';
  $form['field_county']['#suffix'] = '</div>';
}

function _county_list_callback(&$form, &$form_state) {
  return $form['field_county'];
}

function _state_list_callback(&$form, &$form_state) {
  return $form['field_state'];
}

```

# Answer
You can use `ajax_command_replace()` when replacing more than one element/field. Check this ans. The answer says as:

> Instead of returning the HTML of the single element to update, your ajax callback can return an array of ajax commands. So it can return two ajax\_command\_replace to replace each element.
> 0 votes

# Answer
It seems to me that the wrapper is the issue.

> To create an Ajax-enabled form, you:
>
> Mark a form element as an Ajax-enabled using the #ajax property. This form element will now trigger a background Ajax call when it is changed or clicked. The #ajax\['wrapper'\] property includes the HTML ID of a page section that should be replaced (or altered in some other way). The #ajax\['callback'\] tells the Form system what callback should be called after the Ajax call happens and the form is rebuilt.
>
> https://www.drupal.org/docs/7/api/javascript-api/ajax-forms-in-drupal-7

I suggest creating a wrapper around country and state fields and referencing the wrapper'id in the ajax as follows:

```
function module_form_alter(&$form, &$form_state, $form_id) {

    $form['wrapper']    = array(
        '#type' => 'markup',
        '#markup' => "<div id='wrapped-elements'>",
    );

    $form['field_country'][LANGUAGE_NONE]['#ajax'] = array(
        'callback' => '_state_list_callback',
        'event'    => 'change',
        'wrapper' => 'wrapped-elements',
        'progress' => array('type' => 'throbber', 'message' =>  'Please wait...'),
    );
    $form['field_country']['#prefix'] = '<div id="state-list">';
    $form['field_country']['#suffix'] = '</div>';

    $form['field_state'][LANGUAGE_NONE]['#ajax'] = array(
        'callback' => '_county_list_callback',
        'event'    => 'change',
        'wrapper' => 'wrapped-elements',
        'progress' => array('type' => 'throbber', 'message' =>  'Please wait...'),
    );
    $form['field_county']['#prefix'] = '<div id="county-list">';
    $form['field_county']['#suffix'] = '</div>';

    $form['wrapper_close'] = array(
        '#type' => 'markup',
        '#markup' => '</div>',
    )
}

function _county_list_callback(&$form, &$form_state) {
    return $form;
}

function _state_list_callback(&$form, &$form_state) {
    return $form;
}

```
> 0 votes

# Answer
You can create a form container element, add both county and state to that container. Add your wrapper id to the container, and then replace the container in your callback function.
> 0 votes

---
Tags: hooks, ajax
---


title: How do I create a derivative?

text:
# Question
Title: How do I create a derivative?
I would like to create a queue derivative, where I can use a single `QueueWorker` class to process multiple queues, but I am not able to achieve it. Any help would be greatly appreciated.

The module structure is the following.

```
queue_examples/
├── queue_examples.info.yml
├── queue_examples.routing.yml
└── src
    ├── Form
    │   └── QueueDataImportForm.php
    └── Plugin
        ├── Derivative
        │   └── QueueDataProcessorDerivative.php
        └── QueueWorker
            └── QueueDataProcessor.php

```

The code I am using is the following.

### QueueDataImportForm.php

```
namespace Drupal\queue_examples\Form;

use Drupal\Core\Batch\BatchBuilder;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\ClientInterface;
use Drupal\Core\Url;
use Drupal\Core\Link;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Queue\QueueWorkerManager;
use Drupal\Core\Queue\QueueFactory;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Component\Datetime\Time;
use Drupal\Component\Utility\Unicode;

/**
 * Configure queue_examples settings for this site.
 */
class QueueDataImportForm extends FormBase {

  /**
   * The HTTP client to fetch the feed data with.
   *
   * @var \GuzzleHttp\ClientInterface
   */
  protected $httpClient;

  /**
   * Batch Builder.
   *
   * @var \Drupal\Core\Batch\BatchBuilder
   */
  protected $batchBuilder;

  /**
   * Drupal\Component\Datetime\Time instance.
   *
   * @var \Drupal\Component\Datetime\Time
   */
  public $time;

  /**
   * Drupal\Core\Queue\QueueFactory instance.
   *
   * @var \Drupal\Core\Queue\QueueFactory
   */
  protected $queueFactory;

  /**
   * The module handler service.
   *
   * @var \Drupal\Core\Extension\ModuleHandlerInterface
   */
  protected $moduleHandler;

  /**
   * LocationsBatchImportForm constructor.
   */
  public function __construct(ClientInterface $http_client, QueueFactory $queue_factory, QueueWorkerManager $queue_manager, ModuleHandlerInterface $module_handler, Time $time) {

    $this->httpClient = $http_client;
    $this->batchBuilder = new BatchBuilder();
    $this->queue_factory = $queue_factory;
    $this->queue_manager = $queue_manager;
    $this->moduleHandler = $module_handler;
    $this->time = $time;

  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('http_client'),
      $container->get('queue'),
      $container->get('plugin.manager.queue_worker'),
      $container->get('module_handler'),
      $container->get('datetime.time')

    );
  }

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

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

    $form['help'] = [
      '#markup' => $this->t('This form is used to get the location data from remote URL and push data to queue in Batches.'),
    ];

    $sourceUrl = 'https://raw.githubusercontent.com/dr5hn/countries-states-cities-database/master/countries.json';

    $link = Link::fromTextAndUrl('here', Url::fromUri($sourceUrl, ['attributes' => ['target' => '_blank']]));

    $locations = [
      'countries' => $this->t('Countries'),
      'states' => $this->t('States'),
      'cities' => $this->t('Cities'),
      'cities_one' => $this->t('Cities One'),
    ];

    $form['locations_list'] = [
      '#title' => $this->t('Select Location Type.'),
      '#type' => 'select',
      '#options' => $locations,
      '#empty_option' => $this->t('Choose a Location'),
      '#required' => TRUE,
    ];

    $form['actions'] = ['#type' => 'actions'];
    $form['actions']['run'] = [
      '#type' => 'submit',
      '#value' => $this->t('Import Locations'),
      '#button_type' => 'primary',
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    // Check whether the Location Type is valid or not.
    $location = $form_state->getValue('locations_list');
    if (!in_array($location, ['countries', 'states', 'cities'], TRUE)) {
      $form_state->setErrorByName('locations_list', $this->t('The selected location type %location is invalid.', ['%location' => $location]));
    }
  }

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

    $data = [];

    $link = Link::fromTextAndUrl('here', Url::fromRoute('queue_examples.queue_data_import_form'));

    $location = $form_state->getValue('locations_list');

    if (!empty($location)) {

      $remoteUrl = 'https://raw.githubusercontent.com/dr5hn/countries-states-cities-database/master/' . $location . '.json';

      $data = $this->fetchData($remoteUrl);

      if (!empty($data)) {

        $decodedData = Json::decode($data);

        $this->batchBuilder
          ->setTitle($this->t('Processing @location Batch...', ['@location' => Unicode::ucfirst($location)]))
          ->setInitMessage($this->t('Initializing Batch...'))
          ->setProgressMessage($this->t('Completed @current of @total. Estimated remaining time: @estimate.'))
          ->setErrorMessage($this->t('An error has occurred.Click @link to return to form', ['@link' => $link->toString()]));
        $this->batchBuilder->addOperation([$this, 'processItems'], [$location, $decodedData]);
        $this->batchBuilder->setFinishCallback([$this, 'finished']);
        batch_set($this->batchBuilder->toArray());
      }
    }

  }

  /**
   * {@inheritdoc}
   */
  public function fetchData(string $url) {
    $data = [];
    try {

      // @todo check whether implementation of 'timeout' => 600
      // is correct or not in httpClient.
      $response = $this->httpClient->get($url, ['headers' => ['Content-Type' => 'application/hal+json']]);
      if ($response->getStatusCode() == 200) {
        $data = (string) $response->getBody();
      }

    }
    catch (RequestException $exception) {

      $this->messenger()->addError('Failed to download JSON data from URL due to an error check logs for more details.');

      $this->logger('queue_examples')->warning('Failed to download JSON data from URL due to "%error".', ['%error' => $exception->getMessage()]);
    }
    return $data;
  }

  /**
   * Processor for batch operations.
   */
  public function processItems($location, $items, array &$context) {
    // Elements per operation.
    $limit = 50;

    // Set default progress values.
    if (empty($context['sandbox']['progress'])) {
      $context['sandbox']['progress'] = 0;
      $context['sandbox']['max'] = count($items);
    }

    // Save items to array which will be changed during processing.
    if (empty($context['sandbox']['items'])) {
      $context['sandbox']['items'] = $items;
    }

    $counter = 0;
    if (!empty($context['sandbox']['items'])) {
      // Remove already processed items.
      if ($context['sandbox']['progress'] != 0) {
        array_splice($context['sandbox']['items'], 0, $limit);
      }

      foreach ($context['sandbox']['items'] as $item) {
        if ($counter != $limit) {
          $this->processItem($location, $item);
          $counter++;
          $context['sandbox']['progress']++;

          $context['message'] = $this->t('Now Processing Data Item :progress of :count', [
            ':progress' => $context['sandbox']['progress'],
            ':count' => $context['sandbox']['max'],
          ]);

          // Increment total processed item values. Will be used in finished
          // callback.
          $context['results']['processed'] = $context['sandbox']['progress'];
        }
      }
    }

    // If not finished
    // If not finished all tasks, we count percentage of process. 1 = 100%.
    if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
      $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
    }
  }

  /**
   * Process single item.
   *
   * @param string $location
   *   Location Type.
   * @param array $item
   *   Single Location Data.
   */
  public function processItem(string $location, array $item) {

    if (!empty($item)) {

      // Create new queue item.
      $queue = $this->queue_factory->get('queue_data_processor:' . $location);
      $queue->createItem($item);
      // $queue->deleteItem($data);
      $this->logger('queue_examples')
        ->notice($this->t('@location Data Item Pushed to Queue: @data',
          [
            '@data' => implode(',', $item),
            '@location' => Unicode::ucfirst($location),
          ])
        );
    }

  }

  /**
   * Finished callback for batch.
   */
  public function finished($success, $results, $operations) {
    $message = $this->t('Number of Items processed by batch: @count', [
      '@count' => $results['processed'],
    ]);

    $this->messenger()->addStatus($message);
    $this->logger('queue_examples')->info($message);
  }

}

```

### QueueDataProcessorDerivative.php

```
namespace Drupal\queue_examples\Plugin\Derivative;

use Drupal\Component\Plugin\Derivative\DeriverBase;

/**
 * The simple derivative example for Queue.
 */
class QueueDataProcessorDerivative extends DeriverBase {

  /**
   * {@inheritdoc}
   */
  public function getDerivativeDefinitions($base_plugin_definition) {

    $locations = ['countries', 'states', 'cities'];

    foreach ($locations as $location) {

      $this->derivatives[$location] = $base_plugin_definition;
      $this->derivatives[$location]['title'] = $location . 'Queue';

    }

    return $this->derivatives;
  }

}

```

### QueueDataProcessor.php

```
namespace Drupal\queue_examples\Plugin\QueueWorker;

use Drupal\Core\Queue\QueueWorkerBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\StringTranslation\StringTranslationTrait;

/**
 * Processes Locations Data.
 *
 * @QueueWorker(
 *   id = "queue_data_processor",
 *   title = @Translation("Queue Data Processor."),
 *   cron = {"time" = 10},
 *   deriver = "Drupal\queue_examples\Plugin\Derivative\QueueDataProcessorDerivative",
 * )
 */
class QueueDataProcessor extends QueueWorkerBase implements ContainerFactoryPluginInterface {

  use StringTranslationTrait;

  /**
   * The Messenger service.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * Logger service.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected $logger;

  /**
   * Database service.
   *
   * @var \Drupal\Core\Database\Connection
   */

  protected $database;

  /**
   * {@inheritdoc}
   */
  public function __construct(LoggerChannelFactoryInterface $logger, MessengerInterface $messenger, Connection $connection) {
    $this->logger = $logger->get('queue_examples');
    $this->messenger = $messenger;
    $this->database = $connection;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $container->get('logger.factory'),
      $container->get('messenger'),
      $container->get('database')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function processItem($data) {

    $id = $this->getDerivativeId();

    // @todo if id = countries insert data into countries table.
    // if id = states insert data into states table.
    // if id = cities insert data into cities table.
    $this->logger->info($id . 'Queue Processed.');

    if (!empty($data)) {
      // $query = $this->database->insert($id);
      // $query->fields($data);
      // $query->execute();
      $this->logger->info($this->t('Data available to Process.'));

    }
    else {
      $this->logger->warning($this->t('No Data available to Process.'));

    }

  }

}

```

What's wrong in the code I am using?

I would like to insert countries data into countries table, states data into states table, and cities data into cities table. All using single queue processor file using derivatives.

I know of other way where you can conditionally check data and process the data accordingly, but I would like to achieve it using queue derivative.

I can see 3 Queues in the list when I run `drush queue:list`.

```
 ------------------------------------ ------- ---------------------------------
  Queue                                Items   Class
 ------------------------------------ ------- ---------------------------------
  queue_data_processor:countries       0       Drupal\Core\Queue\DatabaseQueue
  queue_data_processor:states          0       Drupal\Core\Queue\DatabaseQueue
  queue_data_processor:cities          0       Drupal\Core\Queue\DatabaseQueue
 ------------------------------------ ------- ---------------------------------

```

In case it helps, I got this idea reading Drupal 8: Derivatives — множественные экземпляры плагина.

**Edit 1:**

The issue I am having is Id is **Null** in `QueueDataProcessor::processItem($data)`

# Answer
With the Help of Niklan I was able to resolve the issue .

The reason for $Id is NULL because of missing parent constructor call. $Id value is available once parent constructor is called.

Full code of Queue Controller as follows :

```
<?php

namespace Drupal\queue_examples\Plugin\QueueWorker;

use Drupal\Core\Queue\QueueWorkerBase;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Logger\LoggerChannelFactoryInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Database\Connection;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Component\Utility\Unicode;

/**
 * Processes Locations Data.
 *
 * @QueueWorker(
 *   id = "queue_data_processor",
 *   title = @Translation("Queue Data Processor."),
 *   cron = {"time" = 10},
 *   deriver = "Drupal\queue_examples\Plugin\Derivative\QueueDataProcessorDerivative",
 * )
 */
class QueueDataProcessor extends QueueWorkerBase implements ContainerFactoryPluginInterface {

  use StringTranslationTrait;

  /**
   * The Messenger service.
   *
   * @var \Drupal\Core\Messenger\MessengerInterface
   */
  protected $messenger;

  /**
   * Logger service.
   *
   * @var \Drupal\Core\Logger\LoggerChannelFactoryInterface
   */
  protected $logger;

  /**
   * Database service.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    $instance = new static($configuration, $plugin_id, $plugin_definition);
    $instance->logger = $container->get('logger.factory')->get('queue_examples');
    $instance->messenger = $container->get('messenger');
    $instance->database = $container->get('database');
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  public function processItem($data) {

    $plugin_id = $this->getPluginId();
    $id = $this->getDerivativeId();

    if (!empty($data)) {
      // $query = $this->database->insert($id);
      // $query->fields($data);
      // $query->execute();
      $this->logger->notice($this->t('@id Data Inserted : @data',
          [
            '@id' => Unicode::ucfirst($id),
            '@data' => implode(',', $data),
          ]
        ));

    }
    else {
      $this->logger->warning($this->t('No Data available to Process.'));

    }

  }

}

```
> 1 votes

---
Tags: 8, batch-operations, queue
---


# Question
Title: How can I use config-set to "unset" the value of a variable?
I am trying to use `config-set` to "unset" a variable. In this case, I have a media image field that has required crop types on it, which is breaking my behat tests, so I want to use drush to temporarily disable the requirement during the behat tests.

I tried something like this:

`drush -y config-set core.entity_form_display.media.image.default content.field_media_image.settings.crop_types_required ''`

But this breaks the config. What's the correct way to "unset" a config value?

# Answer
Use `config-delete`, not `config-set`:

`drush -y config-delete core.entity_form_display.media.image.default content.field_media_image.settings.crop_types_required`

Despite the name, `config-delete` does not delete any of your config `.yml` files; it only "deletes" the config inside the database.
> 1 votes

---
Tags: drush, configuration
---


# Question
Title: How do I set a validation error on a component inside a composite component?
I have a webform with a composite component that allows multiple rows to be added. The structure is something like this, in case that makes it clearer:

```
webform
  sample_details - composite component which allows multiple 'rows', containing:
    sample_ref
    date_sampled (field I want to set the error on)

```

I followed 'method 2 - webform handler' on this guide. I'm able to do the validation itself and set an error on other components, but not on sub-components in the composite one.

This post addresses a similar problem, but the technique hasn't helped me.

I've tried

```
$form_state->setErrorByName( 'date_sampled', $this->t( 'must not have a sample date in the future.' ) );

```

and

```
$form_state->setErrorByName( 'sample_details][date_sampled]', $this->t( 'must not have a sample date in the future.' ) );

```

and a few other things but it seems like I'm missing something. It seems that `setErrorByName` can't work on sub-components because they don't have a standard `#parents` array? Is there a way of achieving this without having to switch to 'the old way'?

# Answer
> 1 votes
The element name "sample\_details\]\[date\_sampled\]" specified in the first parameter of setByErrorName is not correct.

It should be

```
// $key = your multi field array key eg 0,1,2,3
$formState->setErrorByName('sample_details][items][' . $key . '][_item_][date_sampled', $this->t('must not have a sample date in the future.'));

```

You can find out the exact element name by two methods:

1. `$formState->getUserInput()` will give you the exact array pattern to use for setting error by name.
2. Inspect the element from the browser and use the value of `name attribute`.

---
Tags: 8, webforms
---


# Question
Title: How do I format the display and submission format of a datetime field in a custom composite?
on a Drupal 8 webform, I have a datetime entry which works fine and I can format it in settings. When I create a custom composite with a datetime in it, I don't have the same formatting options as before. For example, I cannot pick a display or submit format for the date.

I could create a module to hook onto the submission and alter it that way or, presumably, I could do this in the email submission with tokens. (I have not tried that yet.) That would only affect the submission and not the display, though.

How do I format the display and submission format of a datetime field in a custom composite?

# Answer
> 0 votes
For defining the format of the DateTime field you can use `CUSTOM COMPOSITE SETTINGS`.

Example: To set the format to datepicker like a normal date field, set `datepicker: true` inside the custom text field for the respective composite DateTime element. All other properties can be added here.

You can checkout the JSON representation of the respective property from the source option of the webform. Copy-pasting the properties inside the custom composite setting is all needed.

To set the submission format:

Go to Advance option of the composite element \> Under submission display fieldset select the way you want to display the items.

---
Tags: webforms
---


# Question
Title: How to make menu badges count disappear after the page is viewed?
With reference to my previous question which was a little confusing or I should say it was mixed up with two different problems. I am posting my question again with clarification.

I have created a view, which shows activity logged by Message module. I then created a menu badge using menu badges module which shows the numbers on the menu item. - In start, when there is no activity, it shows 0, After there is new activity, say 2 new activities, the number changes to 2, which is correct, but when the page is viewed the count remains the same and does not decrease or disappear i.e 2, which is wrong. This is the problem. When the page is viewed, the number must disappear until and unless there is new activity.

Currently I am using Message:Message ID in the field to count. I have 3 different message types and I am showing it in one view. Actually, I am trying to create a notifications system. When, the user you are following does some activity, you will be notified.

Coming back to issue. For example, the menu badges module comes with a default badge for the private messages module (it allows users to send/receive messages to/from each other). It is working perfectly as the badge disappears when the users reads all the private messages and it reduces as well. Private messages module does not provide a view so i cannot see how it is working with the menu badges module.

Extra clarifications:

* if the user visited the page containing the view that shows 2 rows corresponding to those 2 new activities, then both of those 2 new activities should no longer be included in the counter for its menu badge.
* I wont use a pager. All items will be listed on the same page.
* We only want menu badges to show count of new activities which the user haven't seen yet i.e the user haven't visited the page containing the activities-logs/notifications. ***Simply, when the user visits the page, the menu badges count must disappear***.
* Visiting the page means user has seen the `notifications/new` activities and now the count should not be visible as there is no new activity. As it happens on stackexchange websites: when you click the notification, the count disappears.

# Answer
> 2 votes
To make the Menu Badges counter **disappear** when visiting the page at `notifications/new` (as in your question), is something you can do by using a special feature of the Rules module, i.e. a technique that is similar to what is described in the answer to "How to execute VBO list of nodes in Rules on After updating an existing user account event?". Read on for more details about the steps to be completed, specific to your question here.

### Step 1:

Create a VBO view of your unread messages, similar to what is described in my answer to "How to allow users to manage their own Message Stack messages?".

### Step 2:

Create a custom Rules Component that will ***execute the VBO list of unread Messages***, and which looks like so:

```
{ "rules_mark_all_unread_messages_read" : {
    "LABEL" : "Mark all unread messages read",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "views_bulk_operations" ],
    "ON" : { "init" : [] },
    "IF" : [
      { "user_has_role" : {
          "account" : [ "site:current-user" ],
          "roles" : { "value" : { "2" : "2" } }
        }
      },
      { "text_matches" : {
          "text" : [ "site:current-page:url" ],
          "match" : "user\/\\d+\/messages\/unread",
          "operation" : "regex"
        }
      }
    ],
    "DO" : [
      { "views_bulk_operations_action_load_list" : {
          "USING" : { "view" : "messages_by_user|page_3" },
          "PROVIDE" : { "entity_list" : { "unread_msgs_list" : "A list of unread messages" } }
        }
      },
      { "LOOP" : {
          "USING" : { "list" : [ "unread-msgs-list" ] },
          "ITEM" : { "current_msg" : "Current message" },
          "DO" : [
            { "component_rules_flag_a_message" : { "message_to_flag" : [ "current-msg" ] } },
            { "drupal_message" : { "message" : "The message with ID [current-msg:mid] (created [current-msg:timestamp]) was marked as read." } }
          ]
        }
      }
    ]
  }
}

```

Some more details about the rule above:

* Rules Event: Drupal is initializing
* Rules Conditions:

+ only for authenticated users.
    + check if the path being visited is `user/%/messages/unread` (adapt this path if you use another path).
* Rules Actions:

+ Create a list of unflagged messages.
    + Loop over each of the unflagged messages found, and flag those messages.

This rule also performs an extra "set message" action, so that you can see what it does if you want to try it in your own site (it shows a message (oeps!) for each message being flagged). Remove that message after QA-testing if you want.

**That's it, works like a charm!**

Note: this solution can also be used in combination with the solution detailed in the related answer. So maybe you want to set a special permission if you want to combine both solutions, so that admins only can mark selected messages as read or unread, if needed.

# Answer
> 0 votes
This is what i have done, very easy and works, menu badges combined with flags & rules, make a NON global flag: node is viewed, make a rule: react on node is being viewed, flag your node with current user (can be many content types), in your badges view and relationship to flag, with current user, filter nodes by not being flagged, done.

---
Tags: 7, views, notifications
---


title: Render private image on twig template

text:
# Question
Title: Render private image on twig template
I have a content type with a private image field. I would like to render the image on the twig template in order to show it to the user when it has enough permission, but the image source is a private directory and I don't know what could be the path to show it.

# Answer
Normally you would configure the formatted output of an image field in the content type and then render it in the node template:

```
{{ content.field_image }}
{{ content|without('field_image') }}

```

If you want to access the path of a private file directly then use the file scheme `private://`:

```
{{ file_url('private://foo.jpg') }}

```
> 6 votes

---
Tags: 8, theming
---


title: Unable to programmatically create user

text:
# Question
Title: Unable to programmatically create user
I am trying to programmatically create a user in Drupal 8 using the following code.

```
$language = \Drupal::languageManager()->getCurrentLanguage()->getId();

$user = \Drupal\user\Entity\User::create();
$user->setPassword($form_state->getValue('pass'));
$user->enforceIsNew();
$user->setEmail('test@test.com');
$user->setUsername('test_test');
$user->set("init", 'test@test.com');
$user->set("langcode", $language);
$user->set("preferred_langcode", $language);
$user->set("preferred_admin_langcode", $language);
$user->activate();
$user->save();

```

When I execute it, I get the following exceptions.

> Drupal\Core\Entity\EntityStorageException: Field type is unknown. in Drupal\Core\Entity\Sql\SqlContentEntityStorage-\>save() (line 783 of /home/printhouseheroes/public\_html/core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorage.php).
> InvalidArgumentException: Field type is unknown. in Drupal\Core\Entity\ContentEntityBase-\>getTranslatedField() (line 586 of /home/printhouseheroes/public\_html/core/lib/Drupal/Core/Entity/ContentEntityBase.php).

How can I avoid getting those exceptions?

# Answer
> 1 votes
The exceptions aren't caused from the code shown in the question. The second exception is caused from the following code in `ContentEntityBase::getTranslatedField()`.

```
// Populate $this->fields to speed-up further look-ups and to keep track of
// fields objects, possibly holding changes to field values.
if (!isset($this->fields[$name][$langcode])) {
  $definition = $this->getFieldDefinition($name);
  if (!$definition) {
    throw new \InvalidArgumentException("Field $name is unknown."); // Line 586.
  }

  // Omissis.

}

```

There is a module that is trying to access the *type* field, which doesn't exist for the User entity.

Your code is correct. Eventually, instead of setting the user fields using a setter method, you could use the array `User::create()` accepts as first parameter, which uses the following array keys (among others):

* *name*
* *mail*
* *pass*
* *status*
* *roles* (an array)
* *langcode*
* *preferred\_langcode*
* *preferred\_admin\_langcode*

There isn't an equivalent value for `enforceIsNew()`, so you need to call that method on the created user object.

---
Tags: users
---


# Question
Title: Why isn't my sub-theme using its CSS file?
I created a sub-theme of the *Drupal8 W3CSS* theme and followed their directions about copying and renaming files, and editing the info.yml file. I installed it, and set it as default theme. It works. (I can see my custom logo.) The styles.css file is not coming from my files, but from the default sub-theme, which I haven't enabled. When I view the source of a page, I see the following tag, which doesn't contain the path for the CSS file used in my sub-theme.

```
<link rel="stylesheet" media="all" href="/themes/d8w3css/drupal8_w3css_subtheme/css/styles.css?qbo25b" />

```

It could be I missed a step.

Do I have to do something with Composer after changing any .yml file of the theme? I did clear all the cache bins.

# Answer
> 0 votes
In Drupal 8 you setup your subtheme libraries in subtheme.libraries.yml. These libraries are then loaded from subtheme.info.yml.

You should check the paths in those files if they are correct.

It's good practice to search for all occurrences of the base\_theme's machine\_name inside your subtheme folder and replace those with the machine\_name of your subtheme.

---
Tags: theming
---


# Question
Title: Error: Private files directory not fully protected
I received the following error in my Drupal 8 status report:

> PRIVATE FILES DIRECTORY Not fully protected See https://www.drupal.org/SA-CORE-2013-003 for information about the recommended .htaccess file which should be added to the private:// directory to help protect against arbitrary code execution.

The obsolete link provided shows no guidance for Drupal 8 or 9, only 7 and prior. I already have what I believe is a strict `.htaccess` file I'd found elsewhere in Drupal's documentation. How can I fix this error in Drupal 8?

# Answer
> 5 votes
Submit the admin form @/admin/config/media/file-system will also create this .htaccess file if your folders are setup correct.

# Answer
> 1 votes
Per glbr, put the following in a `.htaccess` file in your private files directory.

```
# Deny all requests from Apache 2.4+.
<IfModule mod_authz_core.c>
  Require all denied
</IfModule>

# Deny all requests from Apache 2.0-2.2.
<IfModule !mod_authz_core.c>
  Deny from all
</IfModule>

    # Turn off all options we don't need.
    Options -Indexes -ExecCGI -Includes -MultiViews

    # Set the catch-all handler to prevent scripts from being executed.
    SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006
    <Files *>
      # Override the handler again if we're run later in the evaluation list.
      SetHandler Drupal_Security_Do_Not_Remove_See_SA_2013_003
    </Files>

    # If we know how to do it safely, disable the PHP engine entirely.
    <IfModule mod_php5.c>
      php_flag engine off
    </IfModule>
    <IfModule mod_php7.c>
      php_flag engine off
    </IfModule>

```

---
Tags: 8, security, status-messages
---


# Question
Title: How do I print the SQL query of a view in front end?
I have installed latest Drupal 8.1.1 also Devel module installed there is no any option for Display query log on devel setting page while it's present on D7 Devel module. I have created a view with relationship now I want to display SQL Query of that view at the front end.

How do I print the SQL query of a view in front end?

# Answer
> 6 votes
The Devel module includes the webprofiler module; you have to enable that to see the query log.

Note that there's currently a bug in core in 8.1 that prevents it from being used.

# Answer
> 8 votes
While you could install webprofiler module, if you've already got a custom module, it might be quicker to do this:

```
/**
 * Implements hook_views_post_execute().
 */
function MY_MODULE_views_post_execute(ViewExecutable $view) {
  if ($view->id() != 'MY_SPECIAL_VIEW') {
    return;
  }
  dpq($view->query->query());
}

```

# Answer
> 7 votes
You can enable on "Show the SQL query" and "Show other queries run during render during live preview" on "www.example.com/admin/structure/views/settings"

Hope it will help you.

# Answer
> 3 votes
If you're using the database abstraction layer to run your own queries, you can do use the addTag method and pass in 'debug', too.

$query-\>addTag('debug')

# Answer
> 2 votes
Use the below code to print the plain query in frontend in Drupal 8. In order to use the dpq or dpm function, the devel module should be installed in the site.

```
/**
 * Implements hook_views_post_execute().
 */
function MY_MODULE_views_post_execute(ViewExecutable $view) {
  if ($view->id() == 'YOUR_VIEW_MACHINE_NAME') {
    // To print query with placeholder.
    dpm($view->query->query()->__toString());
    // To print query with dynamic argument values
    dpq($view->query->query());
  }

}

```

# Answer
> 1 votes
You can simply do `dpq($query->query());` That will put the query in the message area of your frontend. Edit - You will need devel module to use this feature.

# Answer
> 1 votes
If someone is looking for the **Drupal 7** equivalent of Dalin's answer, the structure is just a little different.

```
/**
 * Implements hook_views_post_execute().
 */
function MY_MODULE_views_post_execute($view) {
  if ($view->name != 'MY_SPECIAL_VIEW') {
    return;
  }
  dpq($view->build_info['query']);
}

```

# Answer
> 0 votes
```
$query = $db->query('MY QUERY');
print_r($query); // In the result you'll see a key "queryString" containing the actual query

```

---
Tags: views, 8, debugging
---


# Question
Title: How would you convert a link to a media item to the file URL in a menu?
I would like to be able to link to media in a Drupal menu and have the link converted to a file url. Is this possible?

# Answer
> 1 votes
I came up with a solution, where you add the link like this: '/media/1234'

And then add this code:

```
function mymodule_link_alter(&$variables) {
  $url = $variables['url'];

  if (!$url->isRouted() && $uri = $variables['url']->getUri()) {
    preg_match('/base\:media\/(\d+)/', $variables['url']->getUri(), $match);
    if (!empty($match) && !empty($match[1])) {
      $media = \Drupal::entityTypeManager()->getStorage('media')->load($match[1]);
      if (!empty($media) && $media->bundle() === 'document') {
        if ($file = $media->field_media_file->entity) {
          $variables['url'] = Url::fromUri(file_create_url($file->getFileUri()), $url->getOptions());
        }
      }
    }
  }
}

```

I hardcoded the source field. You could make it more generic if you like.

---
Tags: 8, files
---


title: Route access check for local task

text:
# Question
Title: Route access check for local task
I've created a view with a page display, filtering on a specific node type. The view's URL is `/admin/poi`.

Now I want to create a local task, linking to this view, for all nodes of type `poi`. The local task is showing, but it is visible when viewing/editing any node type, not just my POIs.

wt\_poi.routing.yml

```
wt_poi.admin_list:
  path: '/admin/poi'
  requirements:
    _permission: 'access administration pages'
    _custom_access: '\Drupal\wt_poi\Controller\WtPoiController::isAllowedPoiAdminList'
  options:
    _admin_route: true

```

wt\_poi.links.task.yml

```
wt_poi.list_overview:
  route_name: wt_poi.admin_list
  base_route: entity.node.canonical
  title: 'List all POIs'
  weight: -9999

```

src/Controller/WtPoiController.php

```
<?php

namespace Drupal\wt_poi\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Access\AccessResult;

/**
 * Controller for the POI node type tasks.
 *
 */
class WtPoiController extends ControllerBase {

  /**
   * Used to limit visibility of local task "List" to POI node type
   */
  public function isAllowedPoiAdminList() {
    $bundle = false;
    $node = \Drupal::routeMatch()->getParameter('node');
    if ($node instanceof \Drupal\node\NodeInterface) {
      $bundle = $node->bundle();
    }
    return AccessResult::forbiddenIf($bundle !== 'poi');
  }
}

```

Why is my `_custom_access` check not hiding the local task on other node types?

UPDATE: There seems to be an access check, but it is coming from "Access" in views module "Page settings" and my own access check is completly ignored. Best case would be my access check in addition to the view's access check, in a pinch I would prefer my own custom check replacing the view's access check.

# Answer
I've found a workaround. When I add the view's URL as path in `routing.yml`, Drupal always used the view's access check. So instead of directly using the view's path, I wrote a simple redirect controller in order to get an alternative path.

wt\_poi.routing.yml

```
wt_poi.admin_list:
  path: '/admin/poi-redirect'
  defaults:
    _controller: '\Drupal\wt_poi\Controller\WtPoiController::redirectToPoiAdminList'
  requirements:
    _permission: 'administer nodes'
    _custom_access: '\Drupal\wt_poi\Controller\WtPoiController::isAllowedPoiAdminList'
  options:
    _admin_route: true

```

wt\_poi.links.task.yml remains unchanged

src/Controller/WtPoiController.php

```
<?php

namespace Drupal\wt_poi\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Access\AccessResult;

/**
 * Controller for the POI node type tasks.
 *
 */
class WtPoiController extends ControllerBase {

  /**
   * The only purpose of this controller is to provide an
   * alternative path to the POI view, so we can attach an
   * _custom_access check to it.
   */
  public function redirectToPoiAdminList() {
    // redirecting to a view: view.VIEW_MACHINE_NAME.DISPLAY_MACHINE_NAME
    return $this->redirect('view.poi.admin_list');
  }

  /**
   * Used to limit visibility of local Task "List" to POI node types
   */
  public function isAllowedPoiAdminList() {
    $bundle = false;
    $route = \Drupal::routeMatch();
    $routeName = $route->getRouteName();
    $node = $route->getParameter('node');
    if ($node instanceof \Drupal\node\NodeInterface) {
      $bundle = $node->bundle();
    }
    // the first part ensures the local task is shown on node pages,
    // the second part makes sure it also works during the redirection itself
    return AccessResult::allowedIf($bundle === 'poi' || $routeName === 'wt_poi.admin_list');
  }
}

```

Two remarks:

A) Remember that the user still has to pass the view's own permission check after the redirection (and this is a good thing, otherwise anybody knowing the alternative URL could bypass the access check).

B) The access check must use an `allowedIf($positiveCondition)`. Do not use an `forbiddenIf($negativeCondition)`, because it only returns `forbidden` or `neutral`, which always hides the local task.

My solution still feels a bit hacky, and I still would be open for a cleaner solution, but at least it does everything I need.
> 1 votes

# Answer
For others who find this page, it took me hours to figure out how to do something similar: have a Views tab on certain node types.

This post helped, but in the end I found what I really needed to do was create a Views Access Plugin.

I created a step-by-step blog post with pictures all about it, here: https://peacocksoftware.com/blog/drupal-89-views-tab-only-certain-node-types
> 0 votes

---
Tags: 8
---


# Question
Title: Splitting field value inside field template not working?
I have a twig template for some text field. Inside it I'm displaying the value like (it's single value field):

```
{% for item in items %}
  {{ item.content}}
{% endfor %}

```

And it's displaying value correctly, which means that inside that loop `item.content` contains correct value.

Now, field value actually contains tags, i.e. value is "tag1 tag2 tag 3". And I want to split that value by space sign. So I tried something like:

```
{% for item in items %}
  {% set tags = item.content|split(' ') %}
  {{ dump(tags) }}
  {{ item.content}}
{% endfor %}

```

And this split function should return list of elements 'tag1', 'tag2', 'tag3', according to documentation: https://twig.symfony.com/doc/2.x/filters/split.html

But instead, this dump call prints out null ?!?!

Why is that happening?

# Answer
> 3 votes
In a field.html.twig template `{{ item.content }}` is a render array. You can't use it in functions which expect a scalar like boolean, integer or string.

If you want to use field values in TWIG code better use the field object `#items`:

```
{% for item in element['#items'] %}
  {% set tags = item.value|split(' ') %}
  {{ dump(tags) }}
{% endfor %}

```

In a single value field you can access the value directly without a loop `element['#items'].value`.

---
Tags: theming
---


# Question
Title: How do I fetch versions of a module compatible with latest core version?
I've been using the endpoint https://updates.drupal.org/release-history/\[module\]/\[version\], where *\[module\]* is the module name and *\[version\]* is its version (as *8.x* or *7.x*). This endpoint, however, doesn't work for *9.x*.

For example https://updates.drupal.org/release-history/search\_api\_solr/8.x works fine but https://updates.drupal.org/release-history/search\_api\_solr/9.x has nothing, although the module has releases compatible with Drupal 9.

Also, the endpoint for *8.x* doesn't return new releases in SEMVER format.

How can I get module releases for Drupal 9? Why aren't SEMVER releases included?

# Answer
You can use https://updates.drupal.org/release-history/search\_api\_solr/current to get the versions either prefixed with 8.x- or without an API compatibility prefix. (The latter is the case for SEMVER versions.)

The output from that URL contains information about this release, for example.

```
<release>
<name>search_api_solr 4.1.1</name>
<version>4.1.1</version>
<tag>4.1.1</tag>
<status>published</status>
<release_link>https://www.drupal.org/project/search_api_solr/releases/4.1.1</release_link>
<download_link>https://ftp.drupal.org/files/projects/search_api_solr-4.1.1.tar.gz</download_link>
<date>1591714636</date>
<files>
<file>
<url>https://ftp.drupal.org/files/projects/search_api_solr-4.1.1.tar.gz</url>
<archive_type>tar.gz</archive_type>
<md5>7f2dbc01229b118c02c66f4ac210d430</md5>
<size>3207604</size>
<filedate>1591714636</filedate>
</file>
<file>
<url>https://ftp.drupal.org/files/projects/search_api_solr-4.1.1.zip</url>
<archive_type>zip</archive_type>
<md5>511e33c0b0ae47a0bd455109f87d07d1</md5>
<size>3792678</size>
<filedate>1591714636</filedate>
</file>
</files>
<terms>
<term>
<name>Release type</name>
<value>Bug fixes</value>
</term>
</terms>
<security covered="1">Covered by Drupal's security advisory policy</security>
<core_compatibility>^8.8 || ^9</core_compatibility>
</release>

```

It also contains data for this release. (This shows that the URL doesn't return information only for SEMVER versions.)

```
<release>
<name>search_api_solr 8.x-3.9</name>
<version>8.x-3.9</version>
<tag>8.x-3.9</tag>
<status>published</status>
<release_link>https://www.drupal.org/project/search_api_solr/releases/8.x-3.9</release_link>
<download_link>https://ftp.drupal.org/files/projects/search_api_solr-8.x-3.9.tar.gz</download_link>
<date>1581700341</date>
<files>
<file>
<url>https://ftp.drupal.org/files/projects/search_api_solr-8.x-3.9.tar.gz</url>
<archive_type>tar.gz</archive_type>
<md5>5050a8e2bd6b4965d414cade7aae3dc8</md5>
<size>1052117</size>
<filedate>1581700341</filedate>
</file>
<file>
<url>https://ftp.drupal.org/files/projects/search_api_solr-8.x-3.9.zip</url>
<archive_type>zip</archive_type>
<md5>140f15134d4e8f2239b96e682186e021</md5>
<size>1278054</size>
<filedate>1581700341</filedate>
</file>
</files>
<terms>
<term>
<name>Release type</name>
<value>Bug fixes</value>
</term>
<term>
<name>Release type</name>
<value>New features</value>
</term>
</terms>
<security covered="1">Covered by Drupal's security advisory policy</security>
<core_compatibility>^8.7.7 || ^9</core_compatibility>
</release>

```

Unfortunately, there isn't a way to get all the versions that are compatible also with Drupal 9 and not just with Drupal 8, using an updates.drupal.org URL. For that, you need to parse the XML output and filter those versions containing *^9* in the `<core_compatibility>` tag.

As side note, the *all*, *8.x*, *7.x* end-points are considered legacy. I guess that means they could be removed in the future.

### References
> 2 votes

---
Tags: community-official-site, 9
---


# Question
Title: Running ajax callbacks on custom composite field
I am using a custom composite field("test") in drupal8 webform in a webform\_form\_alter() hook. Two select fields-"out\_part" and "out\_serial" are added to this composite field("test"). "out\_serial" is dependent on "out\_part" i.e. upon selecting an out\_part value from the dropdown, the dropdown values of out\_serial are generated. I was able to achieve this with ajax callbacks.

```
    $form['elements']['test']['#element'] = array(
    'out_part' => array(
            '#type' => 'select',
            '#id' => 'out_part',
            '#options' => array(
                '80002192'=>'80002192',
                '80002191'=>'80002191'
                ),
            '#ajax' => array(
                'event' => 'change',
                'wrapper' => 'serialNumber_wrapper',
                'callback'=> 'populateOutSerialNumbers',
                'method'=> 'replace'
                )
            ),
    'out_serial' => array(
            '#type' => 'select',
            '#id' => 'out_serial',
            '#validated' => TRUE,
            '#attributes' => [
                                'id' => ['serialNumber_wrapper'],
                              ],
            ));

    function populateOutSerialNumbers($form, $form_state){
        $partNumber = $form_state->getValue('test')[1]['out_part'];
        $partNumber = isset($partNumber) ? $partNumber : 'Onboard';

        // Update the $result with dynamic database query results with respect to selected out_part
        Drupal\Core\Database\Database::setActiveConnection('***');
        $db = Drupal\Core\Database\Database::getConnection();
        $query = $db->query("select distinct T1.serialnumber from assets T1 where T1.dbid <> 0 and (T1.manufacturerpartno = :partNumber)", [':partNumber' => $partNumber]);
        $result = $query->fetchAllKeyed(0,0);

        $form['elements']['test']['#element']['out_serial']['#options'] = $result;

        db_set_active();
        return $form['elements']['test']['#element']['out_serial'];
    }

```

This callback works only on the first set of values of the custom composite field. When I click on "Add", the ajax fails to work on the second set of values. Any suggestions on how to overcome this? Do I need to add the ajax to **$form\['elements'\]\['test'\]\['items'\]** ?

# Answer
You can not modify the $form in the ajax callback. The option for the element `out_serial` should be set inside form build not in ajax callback. Try with following approach:

```
// Inside your form build or alter function.
$form['elements']['test']['#element'] = array(
  'out_part' => array(
    '#type' => 'select',
    '#id' => 'out_part',
    '#options' => array(
      '80002192'=>'80002192',
      '80002191'=>'80002191'
    ),
    '#ajax' => array(
      'event' => 'change',
      'wrapper' => 'serialNumber_wrapper',
      'callback'=> 'populateOutSerialNumbers',
      'method'=> 'replace'
      )
    ),
  'out_serial' => array(
    '#type' => 'select',
    '#id' => 'out_serial',
    '#validated' => TRUE,
    '#attributes' => [
        'id' => ['serialNumber_wrapper'],
      ],
    )
);

// Set value here as when you return the element in ajax callback.
// the form will come here again for rebuild with $form_state having filled values.
if (!empty($form_state->getValue('test'))) {
  $partNumber = $form_state->getValue('test')[1]['out_part'];
  $partNumber = isset($partNumber) ? $partNumber : 'Onboard';

  // Update the $result with dynamic database query results with respect to selected out_part
  Drupal\Core\Database\Database::setActiveConnection('***');
  $db = Drupal\Core\Database\Database::getConnection();
  $query = $db->query("select distinct T1.serialnumber from assets T1 where T1.dbid <> 0 and (T1.manufacturerpartno = :partNumber)", [':partNumber' => $partNumber]);
  $result = $query->fetchAllKeyed(0,0);

  $form['elements']['test']['#element']['out_serial']['#options'] = $result;

  db_set_active();
}
// End of your build or form alter function.

/**
 * Ajax callback of out_part element.
 */
function populateOutSerialNumbers($form, $form_state){
  return $form['elements']['test']['#element']['out_serial'];
}

```
> 0 votes

---
Tags: 8, webforms
---


# Question
Title: Can we make 2nd field required only if 1st field is filled in a custom composite field?
I am using custom composite field in one of my webform form . It has 4 fields and i want to make 2nd field as required only if 1st field is filled .How can i do this?

I had added field2 as required in webform and I had tried to do remove the required attribute from field2 if field1 is not filld by using some jQuery code but that is not working.

Below is the jQuery code i had used

```
var field1=$('#field1').val();

if (field1 == "") {
 $('#field1').removeAttr('required aria-required aria-invalid');
 $('#field2').removeClass('required error');
}

```

# Answer
> 0 votes
You can do it with two ways

1. With Webform Custom Handlers.
2. With custom js.

I prefer you to go with the 1st approach I mentioned above. How to create and work with webform custom handlers is documented well on drupal.org's webform document. Attaching here for quick reference.

```
namespace Drupal\mys_module\Plugin\WebformHandler;

use Drupal\Core\Form\FormStateInterface;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\Component\Utility\Html;
use Drupal\webform\WebformSubmissionInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;

/**
 * Webform validate handler.
 *
 * @WebformHandler(
 *   id = "my_module_custom_validator",
 *   label = @Translation("Alter form to validate it"),
 *   category = @Translation("Settings"),
 *   description = @Translation("Form alter to validate it."),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_SINGLE,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 *   submission = \Drupal\webform\Plugin\WebformHandlerInterface::SUBMISSION_OPTIONAL,
 * )
 */
class CustomValidatorWebformHandler extends WebformHandlerBase {

  use StringTranslationTrait;

  //We will overwrite the method validateForm, inherit from WebformHandlerBase.
  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
    $this->validatePhone($form_state);
  }

  //We will define a new method to validate for example the phone.
  /**
   * Validate phone.
   */
  private function validatePhone(FormStateInterface $formState) {
    $value = !empty($formState->getValue('phone')) ? Html::escape($formState->getValue('phone')) : NULL;

    // Skip empty unique fields or arrays (aka #multiple).
    if (empty($value) || is_array($value)) {
      return;
    }
    if ($value > 9) {
      $formState->setErrorByName('phone', $this->t('Phone not valid.'));
    }
    else {
      $formState->setValue('phone', $value);
    }
  }
}

```

Enable it for your webform: The route to administer the handlers of a Webform is `/admin/structure/webform/manage/[your_webform_name]/handlers`

The second way is to add javascript in assets section of the webform: Route is: `/admin/structure/webform/manage/[webform]/settings/assets`

In the case of jQuery, I suggest instead of removing the `required` try adding it. As the property is configured in the webform element setting.

---
Tags: 8, webforms
---


# Question
Title: How can I hide fields by user role when viewing a node?
I have managed to hide certain fields for certain roles programmatically in Drupal 8 using `function module_name_form_node_form_alter(array &$form, FormStateInterface &$form_state, $form_id)`.

The matter is that what I managed to hide such fields in the "Edit" tab, but I would also like to do the same in the "View" tab. What I intend to do is to hide certain fields depending on their machine name and the role of the user logged.

Do any of you know which hook should I use for that?

# Answer
> 2 votes
OK, this code seems to be the solution:

```
/**
 * Implements hook_entity_field_access().
 */
function MYMODULE_entity_field_access($operation, \Drupal\Core\Field\FieldDefinitionInterface $field_definition, \Drupal\Core\Session\AccountInterface $account, \Drupal\Core\Field\FieldItemListInterface $items = NULL) {
  if ($field_definition->getName() == 'NAME_OF_THE_FIELD' && $operation == 'view') {
    return \Drupal\Core\Access\AccessResult::forbidden();
  }
  else {
    return \Drupal\Core\Access\AccessResult::neutral();
  }
}

```

---
Tags: 8, nodes, users
---


# Question
Title: Custom field validation condition not working
I have created a custom form validation.

I am using `webform` module to build the form.

in `_achva_tz_validate` function there are two fields that have the same validation.

The second field, `zug_id`, is shown only if the user selects `family_state` value to `1`. if `family_state` is not `1` the `zug_id` field is hidden.

The issue is that the `zug_id` validation is not fired.

I am looking for a way to fire it only if `$form_state->getValue('family_state') === 1`

this is the module\_name.module code:

```
// DEFINE TZ RETURN VALUES
define(TZ_ELEGAL_INPUT, -1);
define(TZ_NOT_VALID, -2);
define(TZ_VALID, 1);

function ValidateID($str)
{

    //Convert to string, in case numeric input
    $IDnum = strval($str);

    //validate correct input
    if(! ctype_digit($IDnum)) // is it all digits
        return TZ_ELEGAL_INPUT;
    if((strlen($IDnum)>9) || (strlen($IDnum)<5))
        return TZ_ELEGAL_INPUT;

    //If the input length less then 9 and bigger then 5 add leading 0
    while(strlen($IDnum<9))
    {
    $IDnum = '0'. $IDnum;
}

    $mone = 0;
    //Validate the ID number
    for($i=0; $i<9; $i++)
    {
        $char = mb_substr($IDnum, $i, 1);
        $incNum = intval($char);
        $incNum*=($i%2)+1;
        if($incNum > 9)
            $incNum-=9;
        $mone+= $incNum;
    }

    if($mone%10==0)
        return TZ_VALID;
    else
        return TZ_NOT_VALID;

}

function achva_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id)
{
    switch($form_id){
    case 'webform_submission_qyt_qlyth_mwrwt_mmnwt_wqdmyh_kyt_add_form':
        $form['#validate'][] = '_achva_tz_validate';
        break;
    default:
        $form['#validate'][] = '_achva_tz_test_validate';
        break;
    }
}

function _achva_tz_test_validate(&$form, $form_state) {

    if(ValidateID($form_state->getValue('idno')) !== 1) {
        $form_state->setErrorByName('title', t('Please enter a valid ids number'));
    }
}

function _achva_tz_validate(&$form, $form_state) {

if(ValidateID($form_state->getValue('idno')) !== 1) {
    $form_state->setErrorByName('idtitle', t('Please enter a valid id number'));
}

if(ValidateID($form_state->getValue('zug_id')) !== 1 && $form_state->getValue('family_state') === 1) {
    $form_state->setErrorByName('zugidtitle', t('Please enter a valid zug id number'));
     }
  }

```

# Answer
> 0 votes
You anyway have a problem here:

```
//If the input length less then 9 and bigger then 5 add leading 0
while(strlen($IDnum<9))
{
$IDnum = '0'. $IDnum;

```

}

it should be:

```
while(strlen($IDnum)<9)
{
$IDnum = '0'. $IDnum;

```

}

---
Tags: 8, forms, webforms
---


title: Checkout flow broken

text:
# Question
Title: Checkout flow broken
I'm trying to make a webshop with commerce 2.0 in Drupal 8.

But when I have added a product to the cart, and I've filled in the Payment Information pane, and I press "Continue to review", the same page is being reloaded and there's a duplicate of the product I tried to purchase.

So I'm stuck in the check out flow. If I disable the Payment Information pane, then I can continue in the checkout flow, but then I'm missing the payment information.

Does anyone have an idea for a work around or a fix? or maybe knows what's causing this?

# Answer
Turns out it was because of a module called commerce\_variation\_cart\_form. After uninstalling it, everything worked as expected.
> 1 votes

# Answer
My solution was to go into the Product Variation Type -\> Manage Display

On the "Summary" tab, the Add to Cart field was displaying. I disabled it and now I can place orders.
> 0 votes

---
Tags: 8, commerce
---


# Question
Title: How to render a text with linebreak saved from a textarea form?
Unfortunately I haven't found anything on the web with this specific problem.

I have a field (text, formatted, long) and a form with a textarea element that should save the entered text to this field.

Now I want to render it in my twig template. I access the value like this in my controller:

```
'text' => $node->field_text->value

```

And I render it in twig normally:

```
<p>{{ text }}</p>

```

But whenever I entered a new line by pressing enter in the textarea, it doesn't render the new line. The same thing in the CKEditor when I edit the node and look at the content, there's no new line.

I'm sure that there's a linebreak though, because when I `dpm()` this value, it prints that.

I tried putting the value in a `'#markup' => $text` render array, but it was the same. How can I render this new line?

# Answer
> I tried putting the value in a `'#markup' => $text` render array, but it was the same. How can I render this new line?

Yes, you need to put the text in a render element, but for a formatted text field the correct element is `processed_text`:

```
'text' => [
  '#type' => 'processed_text',
  '#text' => $node->field_text->value,
  '#format' => $node->field_text->format,
],

```
> 3 votes

---
Tags: 8, theming
---


# Question
Title: Send custom data to endpoint based on checkbox value via webforms POST handler
Drupal 8.9, webforms 5.x

I'm trying to send some text data to a endpoint on form submission via a POST handler. It's based on the value of a (single) checkbox on a webform. The endpoint only accepts specific text values, so I need to somehow convert the 0/1 to those specific text values - if checked =\> "Signed up", else =\> "Not signed up".

I want the equivalent of

```
"key": [webform:elements:checkbox_machine_name:checked] ? "Signed up" : "Not signed up"

```

if you could have a ternary in the yaml format...

Is there a way I can do this via webforms?

I'm happy to install more modules, but if possible I'd like to avoid writing any PHP...

# Answer
> 1 votes
You could use a Computed Twig element to execute the ternary operator and set the value in the remote post data.

@see https://www.youtube.com/watch?v=rRlTTkwdP\_o

---
Tags: 8, webforms
---


# Question
Title: How to inherit 'Date' element in webforms?
I tried to simply extend the Date element in webforms like this

```
/**
 * Provides a 'birthday' element.
 *
 * @WebformElement(
 *   id = "birthday",
 *   label = @Translation("Birthday"),
 *   description = @Translation("Provides a custom form element for birthday date selection."),
 *   category = @Translation("Date/time elements"),
 * )
 */
class BirthdayElement extends Date {}

```

and I see and can select it in the build options. However when I click on the Test tab, I only see the Label and no date input field. What am I missing?

# Answer
> 0 votes
Webform elements require a Drupal Form API 'Element' plugin and 'WebformElement' plugin.

@see webform\_example\_element.module

---
Tags: webforms
---


# Question
Title: Toolbar broken, permission errors after permission changes
After performing the most recent core update, which required me to temporarily disable layout builder, my admin toolbar somehow became grey and unformatted as shown below. I've tried changing the admin theme, rebuilding the cache, disabling CSS, etc. but to no avail.

After updating, I ran the security check, which gave some apparently very bad advice about changing permissions of hundreds of files to 744. I followed the advice, which totally broke the site. After reading the various guidance on permissions, I restored permissions to the best recommended ones I could, find but there are still permission errors occurring in the logs, which may or may not be related to this issue.

```
13498   11/Jun 17:49   file   Error      The specified file 'temporary://fileiFPN8R' could not be copied because the destination directory is not properly configured. This may be caused by a problem with file or directory permiss
13497   11/Jun 17:49   file   Error      The file permissions could not be set on public://css.
13496   11/Jun 17:49   php    Warning    User warning: mkdir(): Permission Denied in Drupal\Component\PhpStorage\FileStorage->createDirectory() (line 145 of /home/public/core/lib/Drupal/Component/PhpStorage/FileStorage.php) #0 /h

```

What other troubleshooting steps can I perform short of attempting to restore a backup pre-update?

# Answer
> 1 votes
Issue was from the instructions at the top of the page of this top-ranked search result for Drupal permissions.

I did `chmod -R 664 files` for the files directory, which apparently wasn't sufficient to change all file permissions. Issue persisted until changing permissions it via `find files -type f -exec chmod 664 {} \;` as described here.

---
Tags: 8
---


# Question
Title: Create an order as administrator user and let users continue with the checkout
I am using Drupal 7 and the Drupal Commerce module. I need the ability to create an order as administrator user and let users continue with the checkout. What I have tried:

Do you have any idea?

# Answer
Could you create a new "shopper" user for this customer, then assign the order to them? Make sure the role has proper permissions, workflow, etc. But then they will be the owner of the order and should be able to complete payment (and all the other checkout features like confirmation email).
> 0 votes

# Answer
The only way this can work by default is when you create an order for an existing user and ensure they login prior to attempting to access the form. However, I doubt you should be directing them to the payment page - that page has special logic attached to it that may not make it the ideal point of direction. Much better to send people to the checkout page that actually has the payment checkout pane on it.

If you want to link customers to the checkout form and ensure they're logged in, use a URL like:

https://www.example.com/user/login?destination=checkout/##

If the customer is already logged in, they will be redirected to the checkout form without any issues. If they aren't, they will be prompted to log in. The order ## must match an order that you have assigned to their user account in order for them to then view checkout for that order.

For a customer who does not yet exist in your system, you'll have to create an account for them first and ensure they can access it. There may be a contributed module out there that would let you include a token or something in the URL to grant anonymous access to the order, but I've never heard of it. It's theoretically possible through hooks Commerce offers, I've just never heard of anyone developing it.
> 0 votes

---
Tags: commerce, rules
---


# Question
Title: How to theme webform's Custom Composite element?
Is there any chance I can move specifics sub-element to Custom Composite? Either, I couldn't find any way how to use flexbox inside in a custom composite.

For example, I wish to have;

```
[First name] [Last name]
[Yes, I am coming or no, coming] [allergies list]

```

Rather than all in a row:

```
[First name] [Last name] [Yes, I am coming or no, coming] [allergies list]

```

Can I also use conditional logic in the custom composite element such as if people click "Yes, I am coming" means allergies list will be visible?

# Answer
You can add classes like you do for any other element. The only difference is that in the case of custom composite elements, there are no fields for setting them directly. Instead, you can go to your respective nested element of Custom composite and set your classes like

```
'#attributes':
  class:
    - trip-departure-date

```

inside the custom property and theme accordingly. You can also use bootstrap class to change the layout.
> 2 votes

---
Tags: 8, webforms
---


# Question
Title: Custom webform validation handler not getting called using Event subscriber
I am trying to implement a custom validation for webform. I need to validate if user entered email is valid or not. For that I have altered the webform using event subscriber and assigned a validation handler. But validation handler is not getting called. The configured webform is ajax enabled. Below is my code.

```

namespace Drupal\mymodule\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Drupal\hook_event_dispatcher\HookEventDispatcherInterface;

/**
 * Altering drupal forms with hook_event_dispatcher.
 */
class ContactWebFormFormAlterEventSubScriber implements EventSubscriberInterface {

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    return [
      HookEventDispatcherInterface::FORM_ALTER => 'hookFormAlter',
    ];
  }

  /**
   * Altering form array from here.
   */
  public function hookFormAlter($event) {
    if ( strpos( $event->getFormId(), 'webform_submission_contact_us' ) !== false ) {
      $form = $event->getForm();
      $form['#validate'][] = '::mymodule_webform_submission_contact_us_validate';
      $event->setForm($form);
    }
  }

  /**
   * Altering form array from here.
   */
  public function mymodule_webform_submission_contact_us_validate(array &$form, FormStateInterface $form_state) {
    $email = $form_state->getValue('email');
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
      $form_state->setErrorByName('email', $this->t('Email address is invalid'));
    }
  }
}

```

# Answer
You should use a custom webform plugin handler for that.

More information here: https://www.drupal.org/docs/8/modules/webform/webform-cookbook/how-to-add-custom-validation-to-a-webform-element
> 0 votes

---
Tags: 8, forms, webforms
---


# Question
Title: How do I get the logged-in user wrapper?
In Drupal 7, we are using this code.

```
global $user;
$user_wrapper = entity_metadata_wrapper('user', $user);

```

How do I get the logged-in user wrapper in Drupal 8?

# Answer
a User in drupal 8 becomes an entity type: and each **entity type** has **storage class** that enable us to CRUD a specific entity type entities, so in Drupal 8 in order to get a current user field we need to follow this steps :

```

# step 1 : get current user ( an object represents the current user)
$current_user = \Drupal::currentUser();

# step 2 : get the user entity type storage :
$user_storage  = \Drupal::entityTypeManager()->getStorage('user');

#step 3 : Getting specific user entity.
$user = $user_storage->load($current_user->id());

# step 4 : getting a user entity field
$user->name->value();

# (optional step): to Display all available fields
kint( $user->toArray)

```

### Explanation :

* **step 1:** Get the current active user.
* **step 2:** the user entity type storage class is: `Drupal\user\UserStorage` which contains a set of methods that enable us to CRUD the user entities ex :

+ **load(2)** : load the user entity that have an id = 2.
    + **loadMultiple(\[1,5,8\])** : loadthe users that have ids = 1 or 5 or 8.
* **step 3 :** using the user storage load method to get a specific user entity object, in our case we pass to it current active user id.
* **step 4 :** `$user->{field_name}->{field_property}` you can use `kint( $user->toArray)` to display the lists of fields and each field properties (value , uri ...).
> 0 votes

# Answer
Drupal 8 already uses PHP classes for entities. You don't use `entity_metadata_wrapper()` anymore.

The code you need in Drupal 8 is the following.

```
use Drupal\user\Entity\User;

$account = User::load(\Drupal::currentUser()->id());

```

Alternatively, you could use the following code.

```
$account = \Drupal::entityTypeManager()->getStorage('user')->load(\Drupal::currentUser()->id());

```

When possible, the code should use Dependency Injection.

Note that `\Drupal::currentUser()` returns an instance of the `AccountProxy` class, not an instance of the `User`. The object returned from `\Drupal::currentUser()` doesn't have all the methods the `User` class has, and it doesn't store the values for the fields a User entity has.

### References

* Entity API (in particular, the *Loading, querying, and rendering entities* section)
> 1 votes

---
Tags: 8, users
---


# Question
Title: EntityQuery condition "is not equal to..."
## Problem :

I need filtering entities based on the value of a multiple-choice field.
I want my query returns all entities **except those who have a given value** ('`doe`' for this example).

## Actual :

*multiple-choice values*

```
foo|Choice 1
bar|Choice 2
doe|Choice 3

```

*MyController.php*

```
$nodeStorage = \Drupal:::entityManager()->getStorage('node');
$nids = $nodeStorage->getQuery()
       ->condition('type', 'order')
       ->execute();
$entities = $nodeStorage->loadMultiple($nids);

```

## Need :

So I need something like below :

```
$nodeStorage = \Drupal:::entityManager()->getStorage('node');
$nids = $nodeStorage->getQuery()
       ->condition('type', 'order')
       ->condition('field_multiple_choice', '!=', 'doe')
       ->execute();
$entities = $nodeStorage->loadMultiple($nids);

```

How can I do ? Thank you in advance.

# Answer
I found it !

Just reverse the last two parameters of the condition function and use the `<>` operator.

```
$nodeStorage = \Drupal::entityManager()->getStorage('node');
$nids = $nodeStorage->getQuery()
       ->condition('type', 'order')
       ->condition('field_multiple_choice', 'doe', '<>')
       ->execute();
$entities = $nodeStorage->loadMultiple($nids);

```

> As the doc says, public function QueryInterface::condition take following arguments :
>
> ```
> condition( $field , $value = NULL , $operator = NULL , $langcode = NULL )
>
> ```
> 16 votes

# Answer
It is impossible to check for the existence of entities with field \<\> value if that field may be null.

Instead, you must use an orCondition to do notExists OR \<\>:

```
$query= Drupal::service('entity.query')->get('myentity');
$group = $query->orConditionGroup()
->notExists('my_field')
->condition('my_field', '53', '<>');
$ids = $query->condition($group)->execute();

```
> 4 votes

---
Tags: database, 9
---


# Question
Title: How to export the config files of a content type to a module?
I have a custom module. I created a content type and added some fields to that content type. I also enabled the layout builder on the manage display of the content type

Then I run `drush -y cex` to export the config files.

Then I copy all the config files related to my content type to the module's `config/install` director

Now if I make some changes to content type, their config files should be added/updated/exported in/to the module's `config/install` directory and should not be added to the site's default sync directory.

Is this possible?

# Answer
> 2 votes
You can do exactly this with the Features module.

> Features provides a UI and API for taking different site building components from modules with exportables and bundling them together in a single feature module. A feature module is like any other Drupal module except that it contains additional information in its info file so that configuration can be checked, updated, or reverted programmatically.

While ignoring the related config from configuration management with Config Ignore at the same time. Which also takes wildcards so you don't have to enter every single config object by hand.

# Answer
> 2 votes
You can use a Drupal Console command:

```
drupal config:export:content:type page \
  --module="demo" \
  --optional-config \
  --remove-uuid \
  --remove-config-hash

```

Source: https://drupalconsole.com/docs/en/commands/config-export-content-type

# Answer
> 2 votes
You maybe misunderstand the drupal configuration workflow. A modules config files will only be installed when installing the module. At that moment the configuration will be imported in the database, and so, when you export the sites configuration your modules config will also be part of that. Subsequent changes to configuration of your own module can be done in update\_hooks, but it's easier to make changes on the site self, export that, and have it versioned in that site's repo. If your module only holds config, you could also uninstall it immediately after you installed it, because it doesn't serve a purpose anymore.

So doing this, exporting config to a module, makes sense when you need that same configuration on another site that doesn't already have that configuration. Its a quick way to setup parts of the site the way you like. If a customer wants events where users can register to, and you created that before, you could create a module for that, that when enabled on the site sets up the basics for it. Further customizations to the clients wish on that particular configuration will be versioned in its own repo, when exporting the sites configuration.

# Answer
> 1 votes
> After installing the Configuration Split module, the configuration can be exported in one or more "splits", enabling you to target different configurations for different environments or situations.

1. Install the Configuration split module :

`composer require drupal/config_filter drupal/config_split && drush en -y config_filter config_split`
2. Using the Backoffice create 2 splits one will export your module configurations to `config/install` and the other will export other configurations into standard sync folder, a split enables you to :

* Specify the exportation directory ex (`config/install`).
    * Specify what module configuration to export (your module).
3. just run **drush csex -y** and the code will be exported according to the split setup.

you may find these videos useful: https://www.youtube.com/results?search\_query=Configuration+split+module+

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


# Question
Title: How can I allow editors to manage many taxonomies while choosing which terms to boost and which to make visible?
The system I am working on has about 15 taxonomies. It may have 30 or more eventually. We didn't want to add a field for every taxonomy since the editors would have hated that. Initially we went with one field called "Search term(s)" aka field\_search\_terms that lets editors reference multiple taxonomies.

Now the editors also want to be able to

1. Mark some terms as primary and others as secondary (Let them control which terms to boost in search)
2. Mark some terms as visible tags on the page while most will be hidden.

I can think of two options:

* Make separate fields on the nodes for primary, secondary and visible\_terms. Unfortunately the editors will have to select visible terms/tags twice.
* Make a custom "search\_term\_reference" entity with fields: {field\_search\_term, is\_primary, is\_visible} and then provide something like inline entity form to edit them.

Can anyone offer any practical guidance based on experience with the issue of allowing editorial control of search boost for individual terms? Feedback on how much custom code was needed for example?

# Answer
My preference is to use 3 fields. I'm not sure I think it's ideal, but I think it's actually an easier UX and a better data structure than 1 field (or subentity) with taxonomy ref plus additional checkboxes for primary and display with each tag.

On the surface, it may seem like 1 field would be better, but I think that's actually an illusion. The two main users I'd consider here are developer and editor, and I think one complicated field is bad for both of them. For developers, it's going to be more difficult to determine the search terms or display terms when you try to get them in code with one complicated field vs 3 separate fields. It's also going to be more difficult for editors, they won't be able to scan and see all search terms or all display terms easily.

**Field 1: Tags** This is the master field, it has all the tags that would be in either of the other two fields. If you're generally checking if the content has a tag, you'd check here.

**Field 2: Display Tags** This field is a subset of Field 1 tags and its only purpose is determining which tags display.

**Field 3: Search Boost Tags** This field is also a subset of Field 1 tags and its only purpose is boosting search results.

**Custom Field Widget** Create a new field widget to be used with the display tags and search boost tags fields. This widget displays tags with checkboxes and is limited to only the tags in the first, master tags field. Also have the widget update its options via ajax whenever the first tag field changes.

This approach creates an easy interface for editors, keeps all the data easily accessible for developers, and limits special custom coding to just the field widget. (Bonus: you now have a cool field widget in your collection that you can use elsewhere in similar situations.)
> 1 votes

---
Tags: search
---


# Question
Title: Show the cart icon only if it exists and it isn't empty
I'm looking for an easy way to show on my template a cart icon only if the **cart has 1 or more elements** (Drupal 8, commerce 2.x); I've tried with a view, but I had problems to identify the cart associated to the current (normally anonymous) user.

Does that easy way exist?

Can anyone point me in the right direction? I've searched on Commerce 2.x docs, but I didn't find anything about the feature I'd like to implement. (I don't want to show the cart, only show an icon when the cart exists and has items.)

I've also used suggestions found on How do I count the number of products in cart programmatically? and I was able to create a twig variable using theme preprocess function, but the variable is never updated. Is it mandatory to develop a module?

# Answer
Don't know any module that does this but it is simple to do in your theme

Add this to your `THEMENAME.theme`

```
function THEMENAME_preprocess_block(&$variables) {
  if ($variables['plugin_id'] == 'commerce_cart') {
    if ($variables['content']['#count'] == 0) {
      $variables['attributes']['class'][] = 'visually-hidden';
    }
  }
}

```
> 0 votes

---
Tags: 8, commerce
---


# Question
Title: Menu hook callbacks not working for anonymous users
My custom error handler module is somewhat based on the customerror module, but instead of returning markup, my menu callback function redirects based on the original path. It registers error paths as follows:

```
function my_customerror_menu() {
  $items = array();

  $items['my_customerror/%'] = array(
    'title callback' => FALSE,
    'access callback' => TRUE,
    'page callback' => 'my_customerror_page',
    'page arguments' => array(1),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

```

`'access callback' => TRUE` should make it accessible to all users. I can use the path `my_customerror/404` for example in the site settings and it is recognized as a valid path. This works fine in a local instance and on the Pantheon development site, but once I pushed it to the Pantheon test environment, `my_customerror/404` is not invoked on 404 - Drupal uses the default error response. Unless I am logged in, then it works in Test as well.

But the path `my_customerror/404` works regardless when I type it in manually and does what it should. Somehow Drupal erroneously thinks that this path is not accessible to anonymous users.

What could be causing this?

Here is a simplified version of the callback function that shows what it does:

```
function my_customerror_page($code) {
  $dest = variable_get('my_customerror_' . $code . '_default', '');
  switch ($code) {
    [conditional stuff]
    default:
      header('Status: 301 Moved Permanently', false, 301);
      header("Location: " . $dest);
      break;
  }
  return "";
}

```

Don't ask why I use header() and not drupal\_goto() ....

Just bringing something into the problem description that I already mentioned in a comment. When the Devel module is turned on and anonymous users are given permission to see developer output, it starts working! But this is not a solution, I obviously can't do this in the Live environment.

# Answer
> 1 votes
You're doing a switch(), but with only a default for the switch and no options, it means the switch is unnecessary. Drupal also provides the `drupal_goto()` function, which handles both redirects, as well as cancelling killing the script so the redirect can proceed. Your code can be simplified to:

```
function my_customerror_page($code) {
  $dest = variable_get('my_customerror_' . $code . '_default', '');
  drupal_goto($dest);
}

```

Or if you're really set on using `header()` to set headers for whatever reason, you just need to add `drupal_exit()` after your call to `header()`.

# Answer
> -1 votes
Two subtle changes to the callback function appear to have resolved this. It is working now:

1. returning something other than an empty string
2. using drupal\_add\_http\_header() to set the response code instead of the low level PHP function.

As in:

```
function my_customerror_page($code) {
  $dest = variable_get('my_customerror_' . $code . '_default', '');
  drupal_add_http_header('Status', '301 Moved Permanently');
  header("Location: " . $dest);
  return "redirecting ....";
}

```

---
Tags: 7, hooks, navigation
---


title: Product structure

text:
# Question
Title: Product structure
While building a demo webshop for wine, I am not sure about how the product structure should be. So, I have to map the next structure and I am not sure what is the right approach.

For example, we have wine as product, which could be Chardonnay/Riesling or Cabernet. It could also differ in sizes (1L, 1.5L, 2L) and every product would have their own images.

What is the right approach for the structure? Which would be a product type, which would be a product variation and which would be a product attribute?

# Answer
> 0 votes
Your products variations are the bottles you are going to put in a box a deliver to a customer. They have an unique sku and a price. Starting with that, you should choose how they are going to be shown in the store view. In my case I chose two attributes. One for the year (vintage) and one for the size (1L, 1.5L, ...). Every product variation has its own score (Parker o J.Peñin), tasting, pairing, but the products has the shared properties like producer, country, region, etc.

# Answer
> 0 votes
**Commerce** gives you a lot of flexibility actually and might get confusing

I see 2 basic setups:

1. **wine** *product type* and **wine type** and **size** *attributes* and attach them to the wine *product variation type*. This way you would probably add images to the *variation type* and you would create wine *variations* specifying unique image, SKU, title, type for each variation. Typically with this setup all wine variations are displayed as 1 product and when changing an attribute dropdown the wine variation details (price, image etc) would appear without page refresh. I would choose this setup if I wanted to display all variations as one product.
2. **Wine** *product* with just 1 *variation*, image could be a part of the *product* or *variation*. You then would create individual **wine** *products* specifying price, SKU, image and other details. This way **wines** would display as **individual items** in a catalog view. And would choose this setup for this exact reason. No *attributes* are needed in this setup.

Of course you can make other combinations from the solutions above with **type** or **size** not setup as attribute or with image being part of product or product variation.

There is probably other ways to setup products using contrib modules from drupal.org.

---
Tags: 8, commerce
---


# Question
Title: How do I recalculate the price based on a given address?
I have a basic commerce shop setup and I need to recalculate the price based on the delivery region within the country.

The first approach I tried was to add a list field for the customer profile type and defined various regions. The idea was to recalculate the price based on the selected region and the current total price with the price resolver, the problem was I couldn't access the custom added field value, after the information had been entered in the order information form.

I should note that all purchases would be make by guest accounts.

Is it possible to access this information that way?

I'm currently looking at the shipping module but it seems it doesn't really support this approach because it's more oriented towards characteristics such as weight and dimensions.

Any advice on how to tackle this issue?

I'm using Drupal 8.

# Answer
> 0 votes
Price resolver might be the thing you need. Here's the example: https://www.drupal.org/project/commerce/issues/2931445#comment-12391622

# Answer
> 0 votes
Here is a very similar discussion on the subject. Original author ended up creating and contributing a custom module commerce\_country\_store which is probably worth a try. The discussion above has a lot of options discussed and might be worth a thorough read but not easy to summarize in this post.

---
Tags: commerce
---


# Question
Title: What's the command to migrate images too?
I'm currently using Drush to migrate a Drupal 7 site to a fresh copy of Drupal 8. Everything is migrated except the image fields.

I get thousands of these warnings with different ID numbers.

> \[warning\] Missing file with ID 26. ImageItem.php:329
> \[warning\] Missing file with ID 26. ImageItem.php:329
> \[warning\] Missing file with ID 26. ImageItem.php:329

I'm also using WAMP to locally migrate the site and maybe I'm typing the destination public file path incorrectly. Here's some of the commands I tried.

* `drush migrate-upgrade --legacy-db-key=migrate --legacy-root=/wamp64/www/d7 --configure-only`
* `drush migrate-upgrade --legacy-db-key=migrate --legacy-root=c:/wamp64/www/d7 --configure-only`
* `drush migrate-upgrade --legacy-db-key=migrate --legacy-root=/www/d7 --configure-only`
* `drush migrate-upgrade --legacy-db-key=migrate --legacy-root=/d7 --configure-only`

What's the command to migrate images too?

Thanks!

# Answer
Thanks guys for helping out! I figured it out and migrated all my images and files. Here's what I did for anyone who has the same problem:

I'm was using WAMP and WSL Ubuntu, I was setting the legacy--path incorrectly so my source\_base\_path was incorrect. I had to open up migrate\_plus.migration.upgrade\_d7\_file.yml and used the correct path. Then I ran drush config-import to import the updated file and then ran the migrate.

Here's my file:

```
uuid: 2a4842a5-0869-4984-aaae-68d6c5814f5d
langcode: en
status: true
dependencies: {  }
id: upgrade_d7_file
class: Drupal\migrate\Plugin\Migration
field_plugin_method: null
cck_plugin_method: null
migration_tags:
  - 'Drupal 7'
  - Content
migration_group: migrate_drupal_7
label: 'Public files'
source:
  plugin: d7_file
  scheme: public
  constants:
    source_base_path: /mnt/c/wamp64/www/d7
process:
  fid:
    -
      plugin: get
      source: fid
  filename:
    -
      plugin: get
      source: filename
  source_full_path:
    -
      plugin: concat
      delimiter: /
      source:
        - constants/source_base_path
        - filepath
    -
      plugin: urlencode
  uri:
    -
      plugin: file_copy
      source:
        - '@source_full_path'
        - uri
  filemime:
    -
      plugin: get
      source: filemime
  status:
    -
      plugin: get
      source: status
  created:
    -
      plugin: get
      source: timestamp
  changed:
    -
      plugin: get
      source: timestamp
  uid:
    -
      plugin: get
      source: uid
destination:
  plugin: 'entity:file'
  source_base_path: /mnt/c/wamp64/www/d7/sites/default/files/
migration_dependencies:
  required: {  }
  optional: {  }

```
> 0 votes

---
Tags: migrations
---


title: How do I migrate a multilingual site?

text:
# Question
Title: How do I migrate a multilingual site?
I'm currently trying to migrate my Drupal 7 site, which has the Dutch language enabled, to Drupal 8. I have enabled the following modules as instructed in the docs: Configuration Translation, Content Translation, Interface Translation, Language. After running the migration, no nodes have been created on the Drupal 8 site. Moreover, the log contains lots of error messages similar to the ones underneath.

> Migration d7\_node\_complete:webform did not meet the requirements. Missing migrations language. requirements: language.
>
> Operation on Node complete (Webform) failed

Am I doing something wrong? How can I solve this?

# Answer
It turned out that some of the migration processes were stuck after the first attempt. Here is how I solved the problem and completed the migration of my multilingual site:

* Download and enable the Migrate Tools module and Drush 8
* Run `drush help` to verify that new migration commands such as `migrate-status` and `migrate-import` are enabled
* Run `drush migrate-status` and check the migration processes; all statusses should be *Idle*, but in my case some were stuck on *Importing*
* Use `migrate-stop` to stop any running processes; according to the documentation, this ''cleanly stops a running operation''
* Use `migrate-reset-status` to set the status of stopped processes back to *Idle*; according to the documentation, this ''sets a migration status to Idle if it's gotten stuck''
* Continue the upgrade via the web browser or Drush
> 0 votes

---
Tags: 8, migrations
---