title: How to reformat HTML output of format?

text:
# Question
Title: How to reformat HTML output of format?
I have looked for days and cannot find an example of what I need to do. I wish to reformat the HTML output ckeditor uses for blockquote.

CKEditor output for quote:

```
<blockquote><p>Content</p></blockquote>

```

I wish it to output to something like:

```
<div class="name"><blockquote>Content</blockquote></div>

```

If I am able to do this, it has a lot of potential uses for every format provided in many sites for me. Does anyone know how to do this?

\*Edit: My preference is to do this in PHP within a module if possible rather than JavaScript.

# Answer
> 0 votes
Here is a PHP-only, module-based example that defines a custom filter. The filter creates a DOMDocument object from the HTML output so you can iterate over the elements and alter them. This approach of course will only alter the tags when they are output to the browser, *not inside CKEditor* (you will absolutely need a plugin for this, as Kevin suggested).

Once you have created the filter you will need to enable it for your text format in *Configuration \> Text Formats*.

If you've never created a Drupal module before, all of the basics are here: Creating custom modules (Drupal 7).

Example `mymodule.module` file:

```

/**
 * Implements hook_filter_info().
 */
function mymodule_filter_info() {
  $filters['mymodule'] = array(
    'title' => t('Blockquote filter'),
    'description' => t('Alter <em>blockquote</em> tags.'),
    'process callback' => '_mymodule_process_callback',
  );
  return $filters;
}

/**
 * Callback function.
 */
function _mymodule_process_callback($text, $filter, $format, $langcode, $cache, $cache_id) {
  return _mymodule_filter_html($text);
}

/**
 * Helper function. Handles the actual processing.
 *
 * @param string $string
 *   HTML content to filter from.
 * @return string
 *   HTML with tags altered, if any; else the original HTML.
 */
function _mymodule_filter_html($string) {

  // Suppress errors on HTML5 elements.
  libxml_use_internal_errors(true);

  // filter_dom_load() is a Drupal API function that loads the whole text
  // string into a DOMDocument object.
  $dom = filter_dom_load($string);

  // This flag will tell us if the HTML was altered.
  $altered = FALSE;

  // Process blockquote elements.
  foreach ($dom->getElementsByTagName('blockquote') as $tag) {

    // Do your processing here. Look up examples for wrapping elements
    // using `DOMDocument`.

    $altered = TRUE;
  }

  // If any tags were altered, dump the new DOM to HTML.
  if ($altered) {
    // filter_dom_serialize() is another Drupal API function that serializes
    // the DOMDocument back to XHTML.
    return filter_dom_serialize($dom);
  }
  return $string;
}

```

# Answer
> 0 votes
You could do this easily with jQuery, check the .wrap() method:

```
$('blockquote').wrap('<div class="name"></div>');

```

The wrap() method will wrap elements into another element.

If you want to do it as custom CKEditor plugin I would look at an existing plugin that does something similar and modify it to get the markup you want. I found a Drupal module with a custom plugin that add a wrapper element to blockquote: https://www.drupal.org/project/ckeditor\_blockquote\_attribution

---
Tags: 7, theming, wysiwyg
---


title: Admin Access for Webform Entries

text:
# Question
Title: Admin Access for Webform Entries
The following problem has occurred: A client fills in a reservation form, but the time requested is already fully booked. The clerk and the client negotiate a different time, and the clerk wants to change the requested time (f.e. 18:00) to the negotiated time (f.e. 20:00) -- but as the same form has a date restriction (one cannot reserve on the same day) the clerk can't save the form at the day of the appearance.

Is there any way to give a role the permission to change every webform, without any restrictions? I.e. any changes made by role "Trusted User" will not be checked in any way.

# Answer
Webform for Drupal 8 allows you to give a role (or specific user) access to view and update submissions of a SPECIFIC webform to accomplish what you need

Goto **Settings \> Access** of the webform in question and assign **VIEW ANY SUBMISSIONS** and **UPDATE ANY SUBMISSIONS** to your **Trusted user** role

Than you have to give this user the URL to view and edit/update all the submissions. For example for the contact form they should visit `/admin/structure/webform/manage/CONTACT/results/submissions` and they would be able to see all submissions and edit them.
> 1 votes

---
Tags: webforms
---


# Question
Title: How to create a "Make this Sticky" link or tab
I need faster way to promote a node I'm looking at.

I usually go for:

Is there a faster way than that? The idea is to have a "Make this sticky" tab or link.

# Answer
I just released Toggle Sticky Toggler. Which adds a "Make Sticky / Unmake Sticky" tab next to the default "Edit" tab.
> 0 votes

---
Tags: 8, nodes
---


# Question
Title: Multiple forms on the same page are causing conflicts?
I have the following code.

```
function mymodule_get_node_create_or_edit_form($nodeType = '', $inputNode = null, $prepopulationFields = array())
{
  if (empty($inputNode))
  {
    $values = array(
      'type' => $nodeType,
    );
    $values = array_merge($values, $prepopulationFields);
    $node = \Drupal::entityTypeManager()
      ->getStorage('node')
      ->create($values);
    $form = \Drupal::service('entity.form_builder')->getForm($node);
  }
  else
  {
    $form = \Drupal::entityTypeManager()
      ->getFormObject('node', 'default')
      ->setEntity($inputNode);
    $form = \Drupal::formBuilder()->getForm($form);
  }

  return \Drupal::service('renderer')->render($form);
}

```

I use this function to create edit forms for a node. So I can, for example, create a form that can be used to create a form:

```
print mymodule_get_node_create_or_edit_form('page', null, array());

```

Or I can get the edit form:

```
$node = node_load(1);
print mymodule_get_node_create_or_edit_form($node->getType(), $node , array());

```

The problem is if I execute both on the same page. Eg:

```
print mymodule_get_node_create_or_edit_form('page', null, array());
$node = node_load(1);
print mymodule_get_node_create_or_edit_form($node->getType(), $node , array());

```

If I now make changes to node 1, instead of saving it, it creates a new node with the changes I made, Instead of actually editing the existing node.

# Answer
> 3 votes
To apply the workaround suggested in The same form twice on one page with different arguments may process the wrong form when submitted, you need an instance of a class implementing `FormStateInterface`. It cannot be applied to the code you are using, since you don't have any instance of a class implementing `FormStateInterface`.

Altering the form ID for each form, which is essentially the Drupal 8 to achieve what `hook_forms()` achieved in Drupal 7 (see hook\_forms() has been removed), would require to sub-class a class marked as *@internal* (the `NodeForm` class), and alter the `Node` entity to change its edit form.

I would instead implement `hook_ENTITY_TYPE_prepare_form()`.

```
function mymodule_node_prepare_form(EntityInterface $entity, $operation, FormStateInterface $form_state) {
  if ($operation == 'edit') {
    $form_state->setRequestMethod('POST');
    $form_state->setCached(TRUE);
  }
}

```

The other function is still required. This is how I would implement it.

```
function mymodule_get_node_edit_form($node, array $entity_values = []) {
  if (is_string($node)) {
    $node = \Drupal::entityTypeManager()->getStorage('node')
      ->create(array_merge(['type' => $node], $entity_values));
  }
  $form = \Drupal::service('entity.form_builder')->getForm($node, 'edit');
  return \Drupal::service('renderer')->render($form);
}

```

Essentially, I am applying the workaround given in The same form twice on one page with different arguments may process the wrong form when submitted inside a hook.

# Answer
> 2 votes
I recently had the same issue and found a workaround in the corresponding Drupal core issue: The same form twice on one page with different arguments may process the wrong form when submitted.

The third comment suggests to enable `FormState` caching, and that worked great for me.

```
$form_state->setRequestMethod('POST');
$form_state->setCached(TRUE);

```

# Answer
> 1 votes
According to coments in the original question, the issue is resolved by adding the forms to the render array rather than using `print` directly.

# Answer
> 0 votes
I ran into this problem in Drupal 6 and at the time the solution was to use `hook_forms`. That function still existed in Drupal 7 (see hook\_forms docs for Drupal 7) but it has been removed from Drupal 8. There is a change record for Drupal 8 about how hook\_forms has been removed and how to migrate code.

Perhaps from those documentation pages it will be clear what you need to do?

---
Tags: 8, forms
---


title: Options form with FieldPluginBase?

text:
# Question
Title: Options form with FieldPluginBase?
I tried some variations on the code below, but I have not been able to pass my custom form options to `render()`.

```
class CustomField extends FieldPluginBase {

  public function query() {
    // This is a custom field.
    // Leave empty to avoid a query on this field.
  }

  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['my_options'] = [
      '1' => 1,
      '2' => 2,
      '3' => 3,
    ];
    return $options;
  }

  public function buildOptionsForm(&$form, FormStateInterface $form_state) {

    //Form select element.
    $form['my_options'] = [
      '#type' => 'select',
      '#required' => TRUE,
      '#title' => $this->t('My Options'),
      '#options' => $this->options['my_options'],
      '#description' => $this->t('Description.'),
      '#default_value' => 1,
    ];
    parent::buildOptionsForm($form, $form_state);
  }

  public function render(ResultRow $values) {
    return kpr($this->options['my_options']);
  }

}

```

As is the `['my_options']` key is empty. If I create the `$options['my_options']` in `buildOptionsForm()` it does populate the select list in the views field form. Both, however, break the output of the `render(ResultRow $values)` function. No errors, just no output.

How do you create and pass options from `defineOptions()` to `buildOptionsForm()`, and inevitably access them in `render(ResultRow $values)`?

Trying to reference: FieldPluginBase::defineOptions and Field::buildOptionsForm without success. As well as referencing: https://www.webomelette.com/creating-custom-views-field-drupal-8

# Answer
The `defineOptions()` method returns the view field options, not the options to use in one of the form elements returned from the `buildOptionsForm()` method.

If you look at an existing `defineOptions()` implementation, for example `Date::defineOptions()` or `Custom::defineOptions()`, you will notice the returned array follows a specific format.

```
protected function defineOptions() {
  $options = parent::defineOptions();
  $options['date_format'] = [
    'default' => 'small',
  ];
  $options['custom_date_format'] = [
    'default' => '',
  ];
  $options['timezone'] = [
    'default' => '',
  ];
  return $options;
}

```

```
protected function defineOptions() {
  $options = parent::defineOptions();

  // Override the alter text option to always alter the text.
  $options['alter']['contains']['alter_text'] = [
    'default' => TRUE,
  ];
  $options['hide_alter_empty'] = [
    'default' => FALSE,
  ];
  return $options;
}

```

The `buildOptionsForm()` method then uses the `$this->options` array to set the default values of the form elements it shows. (See `Date::buildOptionsForm()`.)

```
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
  $date_formats = [];
  foreach ($this->dateFormatStorage->loadMultiple() as $machine_name => $value) {
    $date_formats[$machine_name] = $this->t('@name format: @date', [
      '@name' => $value
        ->label(),
      '@date' => $this->dateFormatter->format(REQUEST_TIME, $machine_name),
    ]);
  }
  $form['date_format'] = [
    '#type' => 'select',
    '#title' => $this
      ->t('Date format'),
    '#options' => $date_formats + [
      'custom' => $this->t('Custom'),
      'raw time ago' => $this->t('Time ago'),
      'time ago' => $this->t('Time ago (with "ago" appended)'),
      'raw time hence' => $this->t('Time hence'),
      'time hence' => $this->t('Time hence (with "hence" appended)'),
      'raw time span' => $this->t('Time span (future dates have "-" prepended)'),
      'inverse time span' => $this->t('Time span (past dates have "-" prepended)'),
      'time span' => $this->t('Time span (with "ago/hence" appended)'),
    ],
    '#default_value' => isset($this->options['date_format']) ? $this->options['date_format'] : 'small',
  ];
  $form['custom_date_format'] = [
    '#type' => 'textfield',
    '#title' => $this->t('Custom date format'),
    '#description' => $this->t('If "Custom", see <a href="http://us.php.net/manual/en/function.date.php" target="_blank">the PHP docs</a> for date formats. Otherwise, enter the number of different time units to display, which defaults to 2.'),
    '#default_value' => isset($this->options['custom_date_format']) ? $this->options['custom_date_format'] : '',
  ];

  // Setup #states for all possible date_formats on the custom_date_format form element.
  foreach ([
    'custom',
    'raw time ago',
    'time ago',
    'raw time hence',
    'time hence',
    'raw time span',
    'time span',
    'raw time span',
    'inverse time span',
    'time span',
  ] as $custom_date_possible) {
    $form['custom_date_format']['#states']['visible'][] = [
      ':input[name="options[date_format]"]' => [
        'value' => $custom_date_possible,
      ],
    ];
  }
  $form['timezone'] = [
    '#type' => 'select',
    '#title' => $this->t('Timezone'),
    '#description' => $this->t('Timezone to be used for date output.'),
    '#options' => [
      '' => $this->t('- Default site/user timezone -'),
    ] + system_time_zones(FALSE, TRUE),
    '#default_value' => $this->options['timezone'],
  ];
  foreach (array_merge([
    'custom',
  ], array_keys($date_formats)) as $timezone_date_formats) {
    $form['timezone']['#states']['visible'][] = [
      ':input[name="options[date_format]"]' => [
        'value' => $timezone_date_formats,
      ],
    ];
  }
  parent::buildOptionsForm($form, $form_state);
}

```

In your case, the array returned from `defineOptions()` doesn't have the expected values (*default* or *contains*) and this is causing the issue you noticed.
> 1 votes

# Answer
`$this->options` and `#options` of the select element are two different things.

See the separator field of NumericField::buildOptionsForm:

```
$form['separator'] = [
  '#type' => 'select',
  '#title' => $this->t('Thousands marker'),
  '#options' => [
    '' => $this->t('- None -'),
    ',' => $this->t('Comma'),
    ' ' => $this->t('Space'),
    '.' => $this->t('Decimal'),
    '\'' => $this->t('Apostrophe'),
  ],
  '#default_value' => $this->options['separator'],
  '#description' => $this->t('What single character to use as the thousands separator.'),
  '#size' => 2,
];

```
> 1 votes

---
Tags: views, 8, plugins
---


# Question
Title: How to migrate content using a web service with multiple calls?
I need to migrate content from a web service to which I have to call several URLs. A call to receive a list of nodes and then a call for each node to receive information from the fields.

Something like this:

Calling *domain.test/webservice/*

```
<results>
  <count>10</count>
  <list>
    <id>100</id>
    <id>101</id>
    <id>102</id>
    ...
  </list>
</results>

```

Calling *domain.test/webservice/101*

```
<results>
  <id>101</id>
  <name>Name</name>
  <field1>Field example</field1>
    ...
</results>

```

So, in my migration yml file I have something like:

```
source:
  plugin: url
  data_fetcher_plugin: http
  headers:
    Accept: application/xml
  data_parser_plugin: simple_xml
  urls: https://domain.test/webservice/

```

How can I specified the migrate process to retrieve each content info from a URL like `https://domain.test/webservice/[ID]`?

# Answer
> 1 votes
To solve this I had to create a source plugin that for each row calls a new data parse plugin with the URL for this row.

Here is the plugin:

```
/**
*
* @MigrateSource(
*   id = "url_per_row"
* )
*/
class UrlPerRow extends Url {

protected $dataNewParserPlugin;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
  }

  /**
   * {@inheritdoc}
   */
  public function prepareRow(Row $row) {
    $prepare_row = parent::prepareRow($row);

    if (!$row->getIdMap() || $row->needsUpdate() || $this->aboveHighwater($row) || $this->rowChanged($row)) {
      $item_info_settings = $row->getSourceProperty('item_info');
      if (!empty($item_info_settings)) {
        $this->getItemData($row, $item_info_settings);
      }
    }

    return $prepare_row;
  }

  protected function getItemData(Row &$row, $settings) {
    $new_url = str_replace($settings['token'], $row->getSourceProperty($settings['token_replace']), $settings['url']);

    $this->getNewDataParserPlugin($new_url, $settings['item_selector'],     $row->getSource());
    $this->dataNewParserPlugin->rewind();
    $xml_data = $this->dataNewParserPlugin->current();
    if (!empty($xml_data)) {
      $fields = $row->getSourceProperty('fields');
      foreach ($fields as $field) {
        if (!empty($field['item_info']) && !empty($xml_data[$field['name']])) {
          $row->setSourceProperty($field['name'], $xml_data[$field['name']]);
        }
      }
    }
  }

  protected function getNewDataParserPlugin($url, $item_selector, $settings) {
    $settings['urls'] = [$url];
    $settings['item_selector'] = $item_selector;

    $this->dataNewParserPlugin = \Drupal::service('plugin.manager.migrate_plus.data_parser')
      ->createInstance($settings['data_parser_plugin'], $settings);

    return $this->dataNewParserPlugin;
  }

}

```

Then I put some info in the migration .yml definition:

```
source:
  plugin: url_per_row
  data_fetcher_plugin: http
  headers:
    Accept: application/xml
  data_parser_plugin: simple_xml
  urls: https://myws.com
  item_selector: /ResultWeb/data
  item_info:
    url: https://myws.com/[id]
    token: '[id]'
    token_replace: id
    item_selector: /ResultWeb/data

```

Notice that the `id` from `token_replace` is a field with name *id*. You can use other field.

Also, for every field where is needt to rereive information from the specified URL I put a `item_info: true` element.

```
-
  name: myfield
  label: 'My Field'
  selector: fields/field/my
  item_info: true

```

# Answer
> 2 votes
There is an issue with the UrlPerRow plugin above.

The source data isn't populated until after the check for whether the source data has changed. Because of that fact, it's always looking at previous data, which means the hash will never change, so "rowChanged()" never returns true. It will import new data but not update if the data changes.

A fixed version is below:

```
<?php

namespace Drupal\fad_migration\Plugin\migrate\source;

use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Plugin\migrate\source\SourcePluginBase;
use Drupal\migrate_plus\Plugin\migrate\source\Url;
use Drupal\migrate\Row;

/**
 *
 * @MigrateSource(
 *   id = "url_per_row"
 * )
 */
class UrlPerRow extends Url {

  protected $dataNewParserPlugin;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
  }

  /**
   * {@inheritdoc}
   */
  public function prepareRow(Row $row) {
    $prepare_row = parent::prepareRow($row);

    $item_info_settings = $row->getSourceProperty('item_info');
    if (!empty($item_info_settings)) {
      $this->getItemData($row, $item_info_settings);
    }

    if (!$row->getIdMap() || $row->needsUpdate() || $this->aboveHighwater($row) || $this->rowChanged($row)) {
      return $prepare_row;
    }
    else {
      return false;
    }

  }

  protected function getItemData(Row &$row, $settings) {

    $new_url = str_replace($settings['token'], $row->getSourceProperty($settings['token_replace']), $settings['url']);
    $this->getNewDataParserPlugin($new_url, $settings['item_selector'], $row->getSource());
    $this->dataNewParserPlugin->rewind();
    $xml_data = $this->dataNewParserPlugin->current();
    if (!empty($xml_data)) {
      $fields = $row->getSourceProperty('fields');
      foreach ($fields as $field) {
        if (!empty($field['item_info']) && !empty($xml_data[$field['name']])) {
          $row->setSourceProperty($field['name'], $xml_data[$field['name']]);
        }
      }
    }
  }

  protected function getNewDataParserPlugin($url, $item_selector, $settings) {
    $settings['urls']          = [$url];
    $settings['item_selector'] = $item_selector;

    $this->dataNewParserPlugin = \Drupal::service('plugin.manager.migrate_plus.data_parser')
                                        ->createInstance($settings['data_parser_plugin'], $settings);

    return $this->dataNewParserPlugin;
  }

}

```

---
Tags: 8, migrations
---


# Question
Title: "Language neutral" is not available for content
On a standard multilingual Drupal installation (Drupal 8.6.10), when editing existing content or creating new content the option *language neutral* isn't available; only the enabled languages and some other options are shown.

>

How do I select *Language neutral*?

# Answer
In Drupal 8 LANGUAGE\_NONE (neutral) has changed to LANGUAGE\_NOT\_SPECIFIED, LANGUAGE\_NOT\_APPLICABLE and LANGUAGE\_MULTIPLE.

I usually use LANGUAGE\_NOT\_SPECIFIED where I used to use LANGUAGE\_NONE in Drupal 7.

Berdir mentions that all those new options makes no difference to how content is displayed, but they let you treat differently to content on your site if you'd wanted to in views, custom code, ...
> 1 votes

---
Tags: 8, i18n-l10n
---


# Question
Title: Relate Content to a Group feature when creating a node outside a group
In my drupal site, I'm using the Group module.

My problem:

* I created a regular Drupal node type, let's call it **userpost**
* I created a group type called "usergroup"
* The content type "userpost" is also installed as a group node of group type "usergroup"

Is there a way to put a reference field or something similar into my "regular" node form for my content type called userpost? So that it's possible to (optional) relate a node during creation, to one (or more) group(s) at the same time?

In the admin interface of a group it's possible to relate existing content to a group. This kind of reference field I would like to place into my node creation form :)

Thanks for any hint in advance.

Best regards Phil

P.S. I opened for this problem an issue at Drupal.org too.

# Answer
> 0 votes
Well, if I understand your problem correctly, you could just add an `entity_reference` field to your node type 'userpost' via admin toolbar. Go to Structure-\>Content types-\>userpost-\>Manage fields-\>Add field-\>Choose Reference (other)-\>Select Group and set cardinality to whatever you want.

This would allow you to add group references when you create a new node of content type userpost

**Update** What I described adds a reference from a node to one or multiple group(s) via a new field, it does NOT add this node as a group-content to your group(s). It depends what you are trying to achieve? If you want to add your node as a group-content and you want to do this via the node creation form, you need one more extra step. You can implement a `hook_ENTITY_TYPE_insert()`. From there get the group(s) that you entered to your node field (from $node), `$groups = $node->get('field_groups')` and add the $node as group\_content to each group, similar as done in the answer you linked.

---
Tags: 8, nodes, group
---


# Question
Title: How do I give access permission for specific node to anonymous User
I have removed "Access Content " Permission from Anonymous user. Now want to display specific node to the anonymous user.

As this is for only 1 or 2 nodes, It's not a good idea to use a contributed module like https://www.drupal.org/project/access\_by\_entity. I am looking for a solution as a custom code only

I have tried mymodule\_node\_access also but it's not working.

# Answer
> 1 votes
An access hook can't change the result once you have forbidden access by removing the permission "Access Content", see Is there a way to add node grants to anonymous users?.

If you don't want to grant this permission, because it controls much more than node access, another approach might be to setup a route which bypasses permissions and checks the node ID instead:

*mymodule.routing.yml:*

```
mymodule.my_nodes:
  path: '/path_to_my_nodes/{node}'
  defaults:
    _entity_view: 'node.full'
  requirements:
    _access: 'TRUE'
    node: (123|124)

```

# Answer
> 1 votes
Give back the "Node access" permission (View published content) to Anonymous user and control the accesss with your custom module

```
use Drupal\Core\Access\AccessResult;
use Drupal\node\NodeInterface;

function MODULENAME_node_access(NodeInterface $node, $op, $account) {
  $allowed = [1,2];
  if ($op == "view" && in_array($node->id(),$allowed)) {
    return AccessResult::allowed();
  }
  return AccessResult::forbidden();
}

```

---
Tags: 8, nodes
---


# Question
Title: How to make use of the render placeholder system for cacheablejsonresponse?
I have custom controllers which provide `CacheableJsonResponse` responses. Those responses are quite heavy to build (couple of seconds), so I want to build them better. I build those responses by getting the entity object(s), normalizing its content—referenced entities included—and putting the data directly into the response object.

My JSON responses varies by user, checks the role access, and includes some user related content (e.g. flags). I have tried to put a cache context on **user** (and **url**) on the `CacheableJsonResponse`, but this is not a viable way to handle cache, from my perspective; it would create a cache entry for each user and url request and would be ineffective (the cache will HIT only when the same request is asked twice or more by the same user).

Standard Drupal renderer seems to include a placeholder system which makes the majority of the page cached with proper cache context+tags, and the little parts with *high-cardinality/invalidation rate* rendered last out of the cache system (from my understanding) and then would be useful for my needs.

How can I easily reproduce the same system for my controllers? Is there any standard mechanism/pattern out there?

Reference: https://www.drupal.org/docs/8/api/render-api/auto-placeholdering

# Answer
The only trade-off I have found is to implement custom tags (per user) and put the response data array in cache so I have control over the conditions of cacheability at the controller level. I build the cacheability metadata (context + tags) with the help of a service which registers the metadata of the content which is currently normalized. And when the normalization ends, I merge the metadata onto the response and put the response in a cache backend.

And when the controller is called again, I try to retrieve the cached response and returns it if not invalidated.

Internal and dynamic page cache still works for the other controllers (i.e. standard rendered pages) without removing the high invalidation tags from the **services.yml** file.

Feel free to add better answers than this one.

Tested on **Drupal 8.6.7**.

# Side note

Because I was using flag, I have had to implement cache tags pairs: userid+flaggingid. This way, we will not invalidate the caches of all users whenever a single user flags or unflags a content. This does not answer this question, but I thought it could be useful to include in your reflections for your own cache system.
> 0 votes

---
Tags: caching, performance, 8
---


# Question
Title: How to output multiple files url entities on twig?
I have a file entity field that I can upload multiple files and I'm trying to render or display it inside my node twig template. The code below is what I'm trying to make it display. Tried clearing my cache but it still shows empty.

I can display the **url/uri** of a single file upload but I can't seem to figure out how I can display multiple upload files **url/uri** in the loop.

## Single file here:

```
<a href="{{ file_url(node.field_upload_file.entity.uri.value) }}">Download File</a>

```

## Multiple files Here:

```
{% for key,value in node.field_upload_file.value %}
  <a href="{{ file_url(node.field_upload_file.entity.uri.value) }}">Download File</a>
{% endfor %}

```

Is this a way to display multiple upload files url/uri in the loop? Please suggest to me.

# Answer
> 1 votes
You can try to loop over the field items:

```
{% for item in node.field_upload_file %}
  <a href="{{ file_url(item.entity.uri.value) }}">Download File</a>
{% endfor %}

```

---
Tags: theming, files, uri
---


# Question
Title: Translating a taxonomy term does not populate content into fields
When translating a node into another language it does the following:

* automatically populates all fields with content from the source node on the edit form
* ensures the two nodes are linked as translations
* defaults to the second language (if only two enabled)

When you press 'translate' on a taxonomy term it loads a blank form (as if you are creating a new term).

How do I duplicate the behaviour of the node 'translate' link for taxonomy term 'translate' - to create the same one-click functionality?

# Answer
I have found one compromise solution that needs Replicate & Replicate UI modules:

1. Go to relevant taxonomy term and click 'replicate'
2. Edit replicated taxonomy term as necessary and switch language
3. Create a new 'translation set' to link the two taxonomy terms as translations of each other

This solution isn't suitable for my end-users because of the third step. The 'translate' feature for nodes automatically links the two pieces of content as translations.
> 0 votes

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


# Question
Title: How to remove partricules and apostrophes in url
I'm using drupal 8 and Pathauto.

I have title of the type (in French) `Personnes d'Allemagne`, I would like to delete `d'` to have like url `personnes-allemagne`.

Pathauto removes the apostrophes well, but preserves the particle before, which gives `people-dallemagne`.

I tried to add in the words to delete `d'` or just `d`, but it does not work. Pathauto continues to delete only the apostrophe and not the `d`.

I thought of replacing the apostrophe with a dash, but I would prefer to delete particle and dash.

Someone has a solution?

# Answer
I have been able to achieve it with the Pathauto module 8.x-1.3, using the following settings (/admin/config/search/path/settings).

* For *Strings to Remove* I used *a, an, as, at, before, but, by, for, from, is, in, into, like, of, off, on, onto, per, since, than, the, this, that, to, up, via, with, d'*
* Under *Punctuation*, for *Single quotation marks (apostrophe) (')*, I selected *No action (do not replace)*

I used */content/\[node:nid\]/\[node:title\]* as pattern for the nodes, and created a node with *Personnes d'Allemagne* as title. The path alias for that node has been set to /content/1/personnes-allemagne.

>

The disadvantage is that the apostrophe will not taken off from the path aliases, except when it is present in a string given for the *Strings to Remove* setting.
> 3 votes

# Answer
The punctuation processing is done before the words processing/replacements and Kiamlaluno's answer would be my solution too.

Just wanted to point out that if you want to **reenable the apostrophe stripping** but still keep the `d'` stripping you can do so in a custom module

```
function MODULENAME_pathauto_alias_alter(&$alias, array &$context) {
  $alias = str_replace("'","",$alias);
}

```
> 2 votes

---
Tags: 8, path-aliases
---


title: Is there any "block_user" module?

text:
# Question
Title: Is there any "block_user" module?
After moving my sites to the new server, and some updates in the mean time. I have found one of the sites displaying the

```
"The following module is missing from the file system: block_user bootstrap.inc:276"

```

warring.

Have search the DB and it seems the only "block\_user" string is located inside the **key\_value** table, it's raw definition looks like that:

```
INSERT INTO `key_value` (`collection`, `name`) VALUES ('system.schema','block_user')

```

It has one more binary column as well.

To test the issues have changed the field value to "block\_user\_1234", it changed the warring message so it's the point for sure.

Should I remove the row ??

# Answer
There is no `block_user` module so far as I can see or find.

You can delete the row from the key value table, yes. It should get rid of the error. You can do it with drush if you want.

1. **Back up your database**
2. `drush sql-query "DELETE FROM key_value WHERE collection='system.schema' AND name='block_user';"`

This assumes a *Drupal 8* site.
> 0 votes

---
Tags: configuration
---


title: Multilevel submenu with bootstrap 3

text:
# Question
Title: Multilevel submenu with bootstrap 3
I am trying to make a multilevel menu using a Bootstrap theme on Drupal 8. I have created the menu and activated the "Show children" flag for all submenu containers but only first level submenus are showing.

I have tried http://knackforge.com/blog/pathirakaliappan/create-multi-level-bootstrap-menu-in-Drupal-8, but it doesn't seem to work: The submenus aren't being generated at all in the HTML.

I am using Drupal 8.1.2 and the 8.x-3.x-dev version of Drupal Bootstrap

# Answer
You should conigure the max number of menu level in block structure
> 6 votes

# Answer
After setting menu levels from block configuration, if you want to open the submenu on hover use below CSS,

```
ul.nav li.dropdown:hover > ul.dropdown-menu {
  display: block;
}

```
> 2 votes

# Answer
```
 ul.nav ul.dropdown-menu li.menu-item--expanded:hover ul.dropdown-menu{
  display: block;
  position: absolute;
  left: 175px !important;
  top: -33px !important;
  background: #92996F;
  border: 1px solid white;
  width: 270px;

```

}
> 1 votes

# Answer
By default, the Bootstrap theme for Drupal 8 shows the first level items only, so you have to "tell" the theme that you need more levels. This is the procedure that usually works for me:

1. logged in as administrator, click Structure \> Block Layout
2. locate the Block corresponding to your menu (e.g. "Main navigation" in the Navigation region) and click \[Configure\]
3. from the configuration page, set the "Number of levels to display" to the max number of levels you plan of displaying to users, including the initial level

After saving your changes you should see the inner levels of your menu.
> 0 votes

---
Tags: 8, theming, navigation
---


# Question
Title: Block machine name is in use that is not available
I have a Site Branding block I style in my theme. To do this I give it a specific machine name, in this case: `sitelogo`

On a site using that theme I am trying to create this block but when I try to edit the machine name of the block to `sitelogo` I am getting the following error:

```
The machine-readable name is already in use. It must be unique.

```

An actual block with that machine name does not appear to exist, or at least I cant find it on the site.

Is there a way to force the deletion of that machine name so I can re-use it? I am pretty sure I didn't create it and I need block to have that specific machine name...

# Answer
Block machine names must be unique in the system, not only in the theme.

When you know the machine name of a placed block you can delete it in UI:

```
/admin/structure/block/manage/sitelogo/delete

```

This will of course remove the site logo from one of the other themes.
> 1 votes

---
Tags: theming, blocks
---


title: Export JSON sitemap of views

text:
# Question
Title: Export JSON sitemap of views
I have a Drupal 8 site that is using a bunch of custom views with REST endpoints. These views contain a bunch of content nodes on them which make up a single page.

I have been able to generate an XML sitemap of the views by using Simple XML Sitemap module but I am wanting to know if (and how) it's possible to generate a JSON sitemap of all the views and the paths that are associated with REST but dynamically?

# Answer
> 2 votes
Create a simple custom REST resource in a custom module and within the resource you can return a list of views and other relevant information

Here is a `get()` function that returns views that are enabled and their displays

```
/**
 * Responds to entity GET requests.
 * @return \Drupal\rest\ResourceResponse
 */
public function get() {

    $entity_ids = \Drupal::service('entity.query')
        ->get('view')
        ->condition('status', TRUE)
        ->execute();

    $views = [];
    foreach (\Drupal::entityManager()
        ->getStorage('view')
        ->loadMultiple($entity_ids) as $view) {

        $displays = [];
        // Check each display to see if it meets the criteria and is enabled.
        foreach ($view->get('display') as $id => $display) {

            // If the key doesn't exist, enabled is assumed.
            $enabled = !empty($display['display_options']['enabled']) || !array_key_exists('enabled', $display['display_options']);
            if ($enabled ) {
                $displays[] = [
                    'id' => $display['id'],
                ];
            }
        }
        $views[] = [
            'view_id' => $view->id(),
            'displays' => $displays,
        ];
    }

    $response = new ResourceResponse($views);
    return $response;
}

```

You can modify the `views` array using the for loops to display any information that you find relevant to your task.

Here is a working demo module that I did for the sake of this exercise

---
Tags: views, 8
---


# Question
Title: Show a block on the front page, but only on the first page
I have a block that I want to show on the front page, but not on every paged page (i.e., don't show it on /front-page?page=1).

How can I achieve this?

# Answer
Install and enable request\_data\_conditions module

Then on the configuration of your block add following settings

* **Pages** as `<front>`
* **URL query parameters** set
    + `page` as `must not be set`
    + `page` as `must equal` 0
    + uncheck **require all**
> 2 votes

# Answer
Have you configured the block as shown in screen shot?

If this block is generated using code, also have a look at code also.
> 0 votes

# Answer
In hook\_preprocess\_page() add the following code.

```
if(!isset($_GET['page']))
$block_entity = Drupal\block_content\Entity\BlockContent::load(BLOCK_ID);// BLOCK_ID
$block_view = \Drupal::entityTypeManager()->getViewBuilder('block_content')->view($block_entity, 'DISPLAY_VIEW_NAME');
if ($block_view) {
    $variables['page']['my_block'] = $block_view;
}
}

```

In your Twig template, print the block with the following code.

```
{% if page.my_block %}
  {{ page.my_block }}
{% endif %}
```

Refference: Render a custom block programmatically
> 0 votes

---
Tags: 8, blocks
---


# Question
Title: Avoid repetitive API calling in form rebuild while submitting
I am calling external API in form build function. While submitting form gets rebuild and call external API again.

How can I avoid repetitive API calls in the form's build function? I used `form_state->set()` but it's doesn't seem to be working.

# Answer
> 1 votes
You can test whether the form is currently rebuilding using the `FormStateInterface::isRebuilding` method:

```
if (!$form_state->isRebuilding()) {
  // Contact the API
}

```

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


# Question
Title: How can I display a list of users who have the same taxonomy term
**The setup:**

A Taxonomy Vocabulary called "Area of work".

The vocabulary has the following associated terms: A, B, C, D, E, F, G, etc.

During registration users have to choose a department from the taxonomy list to associate themselves with.

**The challenge:**

I would like to create a single page view or multiple page views if necessary that displays the users that work in each department.

Another requirement is to display each list of users page using the following the path pattern: people/staff/A/, people/staff/B/...

**Current status:**

So far, I have managed to create a generic list with all users that have selected one of the departments in the following path: people/staff, but I can't figure out how to display single lists for each department.

Any help will be much appreciated!

# Answer
> 2 votes
First of all, thank you very much to @leymannx, @GiorgosK and @prkos, because without the three contributions I wouldn't have achieved the desired result.

These are the steps I have followed to display a list of users who have the same taxonomy term in a page with a specific path pattern: people/staff/A/, people/staff/B/...

1. As @leymannx initially suggested, in my view a wildcard in the path was missing. So, instead of people/staff/, I have changed it to `people/staff/%`
2. As @GiorgosK illustrated with his screenshot, I have included a Relationship field\_staff\_area: Taxonomy term, and then a Contextual filter on Taxonomy term: Name using this relationship.
3. Finally, as @prkos precisely described, to show the actual term name in the URL I also needed to configure the Contextual as follows:

a. When the filter value is NOT in the URL: Select the option **Display all results for the specified field**

b. When the filter value IS in the URL or a default is provided: Select the option **Specify validation criteria**. Then, select **Taxonomy term name** in the dropdown, and, finally, check the vocabulary we intend to use (Areas in my case).

# Answer
> 0 votes
Modify the view that you already have that displays all users to include a **Relationship** *field\_department: Taxonomy term* and **Contextual filter** on *Taxonomy term: Name* using this relationship. Here is some details

After that you should be able to visit `/people/staff/A` or `/people/staff/B` etc and see the users that have the corresponding term selected.

# Answer
> 0 votes
To organize your current list of users according to their Department you can group the results by the Department field.

To do that:

1. add the Department Field to the Fields list, `Exclude from display` if you don't need it repeated in the result rows.

Change Style settings to use the wrapper that makes sense in your case (maybe H2). Style settings set here will be applied to most Format settings, so it will server as sort of a "grouping heading".
2. then Under Format settings set the **Grouping field Nr.1** to the Department field.

This will reorganize the results into groups of people that work under the same Department.

---

The second question has already been answered by GiorgosK.

You can make Drupal automatically create pages sensitive to the Department in the URL with the help of a Contextual filter. Adding a Taxonomy field Contextual will work but the URL will show the TID number, not the term name.

To show the actual term name in the URL:

1. you first need to add the Relationship towards the taxonomy term, then you will be able to add the **Name** Contextual filter.
2. Then configure the Contextual:
`When the filter value is NOT in the URL`
**Display all results for the specified field**
`When the filter value IS in the URL or a default is provided`
**Specify validation criteria**
**Taxonomy term name**
**\[your vocabulary\]**
\[Other options that make sense in your case\]
3. Edit the Path to `/people/staff/%` to tell it which path should be replaced with the Contextual
4. Optionally you can also **Override title** and enter the token you can find under `Replacement patterns`, something like `{{ arguments.name }}` so when you add the name into the URL the results will be filtered and the title will change accordingly.

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


# Question
Title: "Declaration of <function> must be compatible with <interface>" in Drupal 8.6.10
Up until Saturday I had a functioning Drupal 8.6.x instance. The I did

```
composer update

```

and Drupal 8.6.10 was installed. Since then I get the following in my error logs:

> Declaration of Drupal\Core\Template\TwigTransTokenParser::parse(Twig\_Token $token) must be compatible with Twig\TokenParser\TokenParserInterface::parse(Twig\Token $token)

and Drush fails with

> Robo\Robo::configureContainer() must be an instance of Robo\Config\Config, instance of Drush\Config\DrushConfig given

I use PHP 7.2 on Ubuntu 18.04.

I did a clean reinstall of Drupal 8.6.10 and the same things occur. I've tried to replace 8.6.10 with 8.6.9 and even 8.6.0 but I still get these errors. If it were Java, I would suspect that the interface and the class had been compiled with different versions of the compiler. But I don't know PHP well enough to know where to start. These errors seem to me to be in core: all my code is under modules/xxx.

Any hints?

Steve

# Answer
> 4 votes
It is a global issue on this new Twig version 1.38.0.

I can be **temporarily fixed** by downgrading its version using `composer require twig/twig:1.37.1`

You can follow this issue to know when the Twig version can be updated again.

---
Tags: 8, installation, composer
---


# Question
Title: How to limit a custom views filter to a certain display type?
I'm creating a views filter, and I would like to limit it by display type. How do I do that?

I'm creating a custom filter for the entity\_browser view display (entity\_browser/src/Plugin/views/display/EntityBrowser.php).

Since it's only relevant for this display, I would like it only appear in the list of filters when on that display. How do I do that?

# Answer
This works, you can use a form alter hook to check the display plugin, and then remove options from the AddHandler form.

```
/**
 * Implements hook_form_FORM_ID_alter().
 */
function entity_browser_form_views_ui_add_handler_form_alter(&$form, FormStateInterface $form_state) {

  // Hide 'entity_browser_bundle' filter plugin for displays other than
  // entity_browser.
  $display_id = $form_state->get('display_id');
  $display_plugin = $form_state
    ->get('view')
    ->get('storage')
    ->get('display')[$display_id]['display_plugin'];

  if ($display_plugin != 'entity_browser') {
    foreach ($form['options']['name']['#options'] as $key => $value) {
      if (strpos($key, 'entity_browser_bundle') !== FALSE) {
        unset($form['options']['name']['#options'][$key]);
      }
    }
  }
}

```
> 1 votes

---
Tags: views, 8
---


# Question
Title: Migrate: Create term(s) if they do not yet exist
Question similar to this question here, but this time, I am not doing a separate migration later.

I want to create taxonomy terms if they do not exist while processing a record. Does `entity_lookup` do this in the same way `migration_lookup` does for stubbing? In this case, I won't be doing another migration to fill in a stub, but surely there must be a way to create a term and keep going.

I don't see anything in `entity_lookup`s plugin indicating it will create if not found.

# Answer
> 0 votes
Wow, ok, getting better at parsing the docs/code for migrate plus. I found it as soon as I posted. The `entity_generate` plugin will do this behavior.

```
  field_paper_jel_codes:
    plugin: entity_generate
    source: jel_codes

```

Now I have a system full of taxonomy.

---
Tags: 8, migrations
---


# Question
Title: How to fix drush issue "Could not bootstrap at phase 5"?
I installed drush via Composer. I am using drush 9.5.2 with Drupal 8.6.4.

I mention that everything is fine on local. However, in a docker instance in GitLab CI, when I execute `vendor/bin/drush updatedb -y -vvv`, I get:

```
 [preflight] Config paths: /builds/v2/my-project/vendor/drush/drush/drush.yml,/builds/v2/my-project/drush/drush.yml
 [preflight] Alias paths: /builds/v2/my-project/web/drush/sites,/builds/v2/my-project/drush/sites
 [preflight] Commandfile search paths: /builds/v2/my-project/vendor/drush/drush/src,/builds/v2/my-project/drush
 [bootstrap] Starting bootstrap to full [0.09 sec, 8.27 MB]
 [bootstrap] Drush bootstrap phase 5 [0.09 sec, 8.27 MB]
 [bootstrap] Try to validate bootstrap phase 5 [0.09 sec, 8.27 MB]
 [bootstrap] Try to validate bootstrap phase 5 [0.09 sec, 8.27 MB]
 [bootstrap] Try to bootstrap at phase 5 [0.09 sec, 8.4 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalRoot() [0.09 sec, 8.4 MB]
 [bootstrap] Change working directory to /builds/v2/my-project/web [0.09 sec, 8.4 MB]
 [bootstrap] Initialized Drupal 8.6.4 root directory at /builds/v2/my-project/web [0.1 sec, 8.4 MB]
 [bootstrap] Try to validate bootstrap phase 5 [0.1 sec, 8.4 MB]
 [bootstrap] Try to bootstrap at phase 5 [0.1 sec, 8.92 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalSite() [0.1 sec, 8.92 MB]
 [bootstrap] Initialized Drupal site default at sites/default [0.1 sec, 8.92 MB]
 [bootstrap] Try to validate bootstrap phase 5 [0.1 sec, 8.92 MB]
 [bootstrap] Try to bootstrap at phase 5 [0.1 sec, 8.92 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalConfiguration() [0.1 sec, 8.92 MB]
 [debug] Add service modifier [0.11 sec, 9.14 MB]
 [bootstrap] Try to validate bootstrap phase 5 [0.11 sec, 9.14 MB]
 [info] sql-query: SELECT 1; [0.11 sec, 9.28 MB]
 [info] Executing: mysql --defaults-file=/tmp/drush_FfJCYU --database=my_project --host=xxx.rds.amazonaws.com --port=3306 --silent -A < /tmp/drush_BsP1AL > /dev/null [0.11 sec, 9.28 MB]
 [info] sql-query: SELECT 1 FROM key_value LIMIT 1; [0.23 sec, 9.28 MB]
 [info] Executing: mysql --defaults-file=/tmp/drush_TOHYme --database=my_project --host=xxx.rds.amazonaws.com --port=3306 --silent -A < /tmp/drush_4SNKF4 > /dev/null [0.23 sec, 9.28 MB]
 [notice] Missing database table: key_value [0.35 sec, 9.28 MB]
 [bootstrap] Could not bootstrap at phase 5 [0.35 sec, 9.28 MB]

In BootstrapHook.php line 32:

  [Exception]
  Bootstrap failed. Run your command with -vvv for more information.

Exception trace:
 () at /builds/v2/my-project/vendor/drush/drush/src/Boot/BootstrapHook.php:32
 Drush\Boot\BootstrapHook->initialize() at /builds/v2/my-project/vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InitializeHookDispatcher.php:34
 Consolidation\AnnotatedCommand\Hooks\Dispatchers\InitializeHookDispatcher->callInitializeHook() at /builds/v2/my-project/vendor/consolidation/annotated-command/src/Hooks/Dispatchers/InitializeHookDispatcher.php:27
 Consolidation\AnnotatedCommand\Hooks\Dispatchers\InitializeHookDispatcher->initialize() at /builds/v2/my-project/vendor/consolidation/annotated-command/src/CommandProcessor.php:117
 Consolidation\AnnotatedCommand\CommandProcessor->initializeHook() at /builds/v2/my-project/vendor/consolidation/annotated-command/src/AnnotatedCommand.php:391
 Consolidation\AnnotatedCommand\AnnotatedCommand->initialize() at /builds/v2/my-project/vendor/symfony/console/Command/Command.php:221
 Symfony\Component\Console\Command\Command->run() at /builds/v2/my-project/vendor/symfony/console/Application.php:971
 Symfony\Component\Console\Application->doRunCommand() at /builds/v2/my-project/vendor/symfony/console/Application.php:248
 Symfony\Component\Console\Application->doRun() at /builds/v2/my-project/vendor/symfony/console/Application.php:148
 Symfony\Component\Console\Application->run() at /builds/v2/my-project/vendor/drush/drush/src/Runtime/Runtime.php:112
 Drush\Runtime\Runtime->doRun() at /builds/v2/my-project/vendor/drush/drush/src/Runtime/Runtime.php:41
 Drush\Runtime\Runtime->run() at /builds/v2/my-project/vendor/drush/drush/drush.php:66
 require() at /builds/v2/my-project/vendor/drush/drush/drush:4

updatedb [--cache-clear [CACHE-CLEAR]] [--entity-updates] [--post-updates [POST-UPDATES]] [--no-cache-clear] [--no-post-updates] [-h|--help] [-q|--quiet] [-v|vv|vvv|--verbose] [-V|--version] [--ansi] [--no-ansi] [-n|--no-interaction] [-d|--debug] [-y|--yes] [--no] [--remote-host REMOTE-HOST] [--remote-user REMOTE-USER] [-r|--root ROOT] [-l|--uri URI] [--simulate] [--pipe] [-D|--define DEFINE] [--xh-link XH-LINK] [--notify [NOTIFY]] [--druplicon] [--] <command>

```

I mention that **the command mysql -V is working.**

And when I execute `vendor/bin/drush sql:connect -vvv`, I get:

```
 [preflight] Config paths: /builds/v2/my-project/vendor/drush/drush/drush.yml,/builds/v2/my-project/drush/drush.yml
 [preflight] Alias paths: /builds/v2/my-project/web/drush/sites,/builds/v2/my-project/drush/sites
 [preflight] Commandfile search paths: /builds/v2/my-project/vendor/drush/drush/src,/builds/v2/my-project/drush
 [bootstrap] Starting bootstrap to max [0.1 sec, 8.27 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalRoot() [0.1 sec, 8.4 MB]
 [bootstrap] Change working directory to /builds/v2/my-project/web [0.1 sec, 8.4 MB]
 [bootstrap] Initialized Drupal 8.6.4 root directory at /builds/v2/my-project/web [0.1 sec, 8.4 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalSite() [0.11 sec, 8.92 MB]
 [bootstrap] Initialized Drupal site default at sites/default [0.11 sec, 8.92 MB]
 [bootstrap] Drush bootstrap phase: bootstrapDrupalConfiguration() [0.11 sec, 8.92 MB]
 [debug] Add service modifier [0.11 sec, 9.11 MB]
mysql --user=my_project --password=xxx --database=my_project --host=xxx.rds.amazonaws.com --port=3306 -A

```

So, no problem with `drush sql:connect`.

**Does the notice *"Missing database table: key\_value"* could cause the issue?**
How could we troubleshoot the issue?

Just in case, here is the build part of my *gitlab-ci.yml*:

```
build:
  stage: build

  before_script:
    - apt-get update

    #install additional gd extension, that is required by Drupal
    - apt-get install libpng-dev -y
    - docker-php-ext-install gd

    #install mysql-cli
    - apt-get install -y mysql-client

    #install composer
    - apt-get install zip unzip
    - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    - php composer-setup.php
    - php -r "unlink('composer-setup.php');"

    #install composer package to run parallel tasks
    - composer -n global require -n "hirak/prestissimo"

  script:
    - mysql -V
    - php composer.phar install
    - vendor/bin/drush
    - vendor/bin/drush sql:connect -vvv
    - vendor/bin/drush updatedb -y -vvv
    - vendor/bin/drush config-import -y
    - vendor/bin/drush cache-rebuild -y

```

# Answer
To fix the issue I had to export my local database and import it in the production server database (same for the sync configuration files).
> 0 votes

---
Tags: 8, drush
---


title: How do I clear a specific cache entry?

text:
# Question
Title: How do I clear a specific cache entry?
I saved a cache entry using `cache_set()`. How can I clear this entry using Drush?

# Answer
> 3 votes
You can create a custom drush command to call the cache\_clear\_all function or just use:

```
drush ev "cache_clear_all('my_module', 'cache', TRUE);"

```

You can read more about cache\_clear\_all in A Beginner's Guide to Caching Data in Drupal 7

---
Tags: 7, drush, caching
---


# Question
Title: How to show the following n events with respect to the current date or the past events to always ensure n elements in the view?
I have an agenda on my homepage, and I want to always ensure 5 events.

If there are 5 or more following events (including the current one), show the nearest 5 from the start date.

If there is less, show X past events in such a way that the following and the past are 5 in total.

Examples:

Today is March 12.

a) List of events (more than 5 futures): \- March 10th \- March 11th \- March 12 \- March 13 \- March 14 \- March, 15th \- March 16 \- March 17 \- March 18th

Show in the view March 12, 13, 14, 15 and 16.

b) List of events (mix, p past events, q future events): \- March 9 \- March 10th \- March 11th \- March 13 \- March 14 \- March, 15th

Show in the view: March 10, 11, 13, 14 and 15.

c) List of events (no future events, show recent events). \- March 1st \- March 2 \- March 3rd \- March 8 \- March 9 \- March 10th \- March 11th

Show in the view: March 3, 8, 9, 10 and 11.

# Answer
> 0 votes
You will need to develop a custom module with a custom views sort plugin as views don't have something for this.

Read the Custom Views Sort Plugin for Upcoming Events blog post that will help you.

---
Tags: views, database, datetime
---


# Question
Title: What's wrong with a new installation of Drupal 8.6.10?
A fresh install of Drupal results in a WSOD including a very helpful error message which says "The website encountered an unexpected error. Please try again later."

I normally install Drupal with the drupal-project template from github and at first, I thought this was a problem with my local DDEV environment. I then tried with MAMP Pro to find exactly the same.

Finally I tried on simplytest.me to realise that it isn't me.

A look at my local error logs reports the following;

```
"NOTICE: PHP message: Uncaught PHP Exception Twig\Error\SyntaxError:
An exception has been thrown during the compilation of a template
("Attribute "name" does not exist for Node
Twig\Node\CheckToStringNode) in
core/themes/bartik/templates/block--system-menu-block.html.twig"." at
/var/www/html/public_html/vendor/twig/twig/src/Environment.php line
797"

```

I found that is was possible to access the site via the admin path, and changing the theme to Stark allowed me to view the site.

I then attempted to view recent system messages at admin/reports/dblog - only to once again to get the "Please try again later" message.

# Answer
> 0 votes
Twig version 1.38.1 is broken (or not D8 compatible)

Revert to 1.37.1

---
Tags: 8
---


# Question
Title: How can I break into my own Drupal site?
I was doing a Media module tutorial. Half way through it I decided to install the tutorial companion files and foolishly replaced my files. In the companions readme it says the admin login is username - admin and password - admin.

But it is not! Now i’m completely locked out. Can someone tell me how I might break in to my tutorial site? I have access to the DB via PHPMyAdmin.

I was thinking a MySQL update command to the password field for the admin. Can someone tell me what I could use to reset the admin password?

I changed the admin email address then requested a new password but it has not fired off an email. I believe the password encryption method is sha1().

# Answer
> 5 votes
If you're using Linux:

1. Install drush if you haven't already
2. Go to /install\_directory/sites/mysite
3. Type sudo drush uli
4. Copy the link to your browser

Drush is extremely useful for many things. The above will log you in as user 1, after which you can reset your password in the usual way.

# Answer
> 2 votes
Look at this post: Resetting the administrator password with sql-query (Drupal 7)

> When, in Drupal 7, the password for user 1 (the administrator) is lost and the email notification or drush methods don't work, it is possible to set the password via a database query.

I have done it in the past using a PHP script (it provides the link to that post in above post).

> The password reset method described below uses a PHP script that must be uploaded to the web server to reset the administrator password. The ability to upload a PHP file to the server where the site is hosted is required for successful execution of this method.

And it is always prudent to make a backup of the database before making any unconventional changes to it.

# Answer
> 0 votes
A little late to the game, but the simplest solution for me would be:

1. Go to the `user` database table
2. Change the email of the "admin" user (Remember to save the original email.)
3. Go to `yoursite.com/user/password` and reset your password.
4. Change the email back to the original one.

---
Tags: security
---


# Question
Title: Recursion when reading field in hook_entity_load
Is there a preferred approach modifying values?

I need to modify a value when a node loads, but must use other values from the node. The code below causes recursion errors.

```
function zzzmodule_entity_load(array $entities, $entity_type_id) {

  foreach ($entities as $entity) {

    if ($entity_type_id === "node" && $entity->hasField('other_field')) {

      $t = $entity->title->value;
      $o = $entity->other_field->value;

      if (empty($o)) {

        $o2 = json_encode($t);

        $entity->set('other_field', $o2);
        $entity->save();
      }

    }

  }

}

```

# Answer
Your code works just remove the `$entity->save();` and it works i have tested it:

```
function zzzmodule_entity_load(array $entities, $entity_type_id) {
  foreach ($entities as $entity) {
    if ($entity_type_id === "node" && $entity->hasField('other_field')) {
      $t = $entity->title->value;
      $o = $entity->other_field->value;
      if (empty($o)) {
        $o2 = json_encode($t);
        $entity->set('other_field', $o2);
      }
    }
  }
}

```
> 0 votes

---
Tags: 8, hooks
---


title: Custom form template

text:
# Question
Title: Custom form template
So I am recently started working on front-end development, and have started messing around with making my own custom templates for modules. I have been able to get page related templates to work, but am having a problem getting form related templates to work.

This is for Drupal 7.

I have a form, like this (Its not quite this basic, but very similar and no special fields)

```
function mymodule_menu() {
  $items['admin/atavism/config'] = array(
    'title' => 'Configuration',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('atavism_config'),
    'access arguments' => TRUE,
  );
}

function atavism_config() {
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Save Configuration',
  );

  $form = theme('atavism_config_form', array('form',$form));
  return $form;
}

function atavism_theme() {
  return array(
    'atavism_config_form' => array(
      'template' => 'page--atavism-config-form',
      'path' => drupal_get_path('module','atavism') . '/theme',
    ),
  );
}

```

And then I created the `page--atavism-config-form.tpl.php`. Inside of the form, I am using;

```
print render($form);

```

I am doing the same thing for pages that are just content (normal pages with just text and markup for example, and no forms), and it's working as intended, but I am also doing the same thing for a couple of different forms I have, and I am running into two problems. Either #1, the form renders in the template, but ONLY the provided `$form` variables are available (so the form can't be submitted), or I get a white screen with a PHP error of 'Unsupported operand'.

It appears I may be doing something wrong with forms, but I can't figure out what. Could somebody please help me?

# Answer
> 0 votes
Adding the response I gave on Drupal.org:

The issue is that you are rendering the form with the theme() function, in the form definition. Instead, you need to identify the form as using a #theme, and let it be rendered downstream:

So remove this:

```
$form = theme('atavism_license_list_view', array('form' => $form));

```

And add this:

```
$form['#theme'] = 'atavism_license_list_view';

```

Link: https://www.drupal.org/forum/support/module-development-and-code-questions/2019-03-07/custom-template-file-for-modules#comment-13019068

---
Tags: 7, theming
---


# Question
Title: Module to create a custom field in all the content types
I am building a module to insert a custom field in all bundles of the node. I have encountered many difficulties, any help they can give me, I would appreciate it very much.

The custom field I am creating is used to save a tocken automatically or manually. - ***field\_custom\_tocken*** -

If a new bundle is created, the field\_custom\_tocken field must be added automatically to the new bundle. To generate the token it is necessary the id of the entity (nid), or that the tockent is inserted by the user.

I have used Drupal Console, create the field type, the widget and the formatter. This does not generate the field, the drawback is that you have to manually add the field to the bundle. drupal generate: plugin: field

In this documentation the field is created and added to a specific bundle, I use part of this documentation. *field.storage.node.field\_brand\_information.yml*

I have this:

this creates the field. *modules/custom/custom\_tocken/config/install/field.storage.node.field\_custom\_tocken.yml*

```
# field.storage.node.field_custom_tocken.yml
langcode: en
status: true
dependencies:
  enforced:
    module:
    - custom_tocken
  module:
    - node
    - text
id: node.field_custom_tocken
field_name: field_custom_tocken
entity_type: node
type: string
settings: {  }
module: core
locked: true
cardinality: 1
translatable: true
indexes: {  }
persist_with_no_fields: false
custom_storage: false

```

This should create the custom field in the existing bundles, when the module is installed, but it does not work :(

```
/**
 * Implements hook_install().
 */
function ide_d8_url_shortener_install() {
  $entity_type         = 'node';
  $bundle              = '';
  $field['field_name'] = 'field_custom_tocken';
  $field['label']      = 'Tocken';
  $field['entity_type']= 'node';
  $field['type']       = 'string';
  $field['settings']   = array();

  $bundles = \Drupal::service('entity_type.bundle.info')->getBundleInfo($entity_type);
  $arr_bundles = [];

  foreach($bundles as $key => $value) {
    $bundle = $key;
    $fields       = \Drupal::entityManager()->getFieldDefinitions($entity_type, $bundle);

    if ( !isset($fields['field_short_url']) ) {
      entity_get_form_display($entity_type, $bundle, 'default')
        ->setComponent($field['field_name'], $field )
        ->save();

      entity_get_display($entity_type, $bundle, 'default')
        ->setComponent($field['field_name'], $field)
        ->save();
    }
  }
}

```

Any help you can give me I would appreciate it.

# Answer
> 2 votes
Instead of installing the field in your install hook (which will be triggered when installing the module only), you should implement hook\_entity\_base\_field\_info() to add the field to all nodes and all bundles.

An example below:

```
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;

/**
 * Implements hook_entity_base_field_info().
 *
 * Attaches a custom field 'field_custom_tocken' to all nodes.
 */
function mymodule_entity_base_field_info(EntityTypeInterface $entity_type) {
  // Whether the entity type is 'node'.
  if ($entity_type->id() == 'node') {
    return [
      'field_custom_tocken' => BaseFieldDefinition::create('string')
        ->setName('field_custom_tocken')
        ->setLabel(t('Tocken'))
        ->setDescription(t('My tocken, which might be named token instead.'))
        ->setSettings([
          'max_length' => 150,
          'text_processing' => 0,
        ])
        ->setDefaultValue('')
        ->setDisplayOptions('view', [
          'label' => 'above',
          'type' => 'string',
          'settings' => [
            'link_to_entity' => FALSE,
          ],
          'weight' => 0,
        ])
        ->setDisplayOptions('form', [
          'type' => 'string_textfield',
          'weight' => 0,
        ])
        ->setDisplayConfigurable('form', TRUE)
        ->setDisplayConfigurable('view', TRUE),
    ];
  }
}

```

---
Tags: 8
---


# Question
Title: Location Contextual Filter: Distance/Proximity works for all nodes but one
Drupal 7 site with Location and Location CCK modules.

Client has custom content type with Location field provided by Location CCK module.

Each Location node has a Views block display of Nearby Locations with sort criteria “Location: Distance / Proximity (asc)” and this works for all nodes except a new one recently created.

In Views UI, if I preview with contextual filters, I see the closest four locations sorted by proximity.

But viewing the actual node, I see four other locations that are quite some distance farther away.

What could be causing this, and how should I troubleshoot it? (I have cleared the cache!)

# Answer
> 0 votes
I did not figure out why this is happening, but I was able to enter the latitude and longitude manually. This solves the problem for the short term, since the client does not add Location nodes often. I'm leaving the question open in case anyone has a clue!

---
Tags: 7, views, location
---


# Question
Title: Drupal 7 chosen module use ajax to fill the select
I have two select elements and depending on what I select in the first select element second should fill from ajax call. First one is the simple select second one use chosen. The problem is if I fill `.chosen-results` `ul` with `li` results in `jQuery` and press on select elemnt it clears all `ul`.

```
    'purchase_type' => [
        '#type' => 'select',
        '#options' => _purchases_fill_type_options(),
        '#attributes' => [
          'class' => ['purchases-funds-report-item-type'],
        ],
        '#empty_option' => t('Select type'),
        '#empty_value' => '',
        '#required' => TRUE,
        '#title_display' => 'invisible',
        '#default_value' => '',
        '#cell_attributes' => [
          'class' => ['purchasetype'],
        ],
      ],
      'account_name' => [
        '#type' => 'select',
        '#options' => [],
        '#empty_option' => t('Select account'),
        '#required' => TRUE,
//        '#chosen' => TRUE,
        '#title_display' => 'invisible',
        '#default_value' => '',
        '#attributes' => [
          'class' => [
            'purchases-funds-report-account-name',
            'common-select-report',
          ],
        ],
        '#cell_attributes' => [
          'class' => ['accountname'],
        ],
      ],

```

Chosen is commented because I initiate it from jQuery adding class on it and sending to `attachBehaviors` because these rows are added dinamicly:

```
$('#purchases-report-funds-edit-form', context).on("gridTableRowAdd", 'tr', function() {
      $(this).find('.accountname select').addClass('chosen-enable');
      Drupal.attachBehaviors(this, Drupal.settings);
    });

```

And the result of ajax :

```
var li_options = ['<li value="">' + Drupal.t('Select account') + '</li>'];
$.each(data, function (i, value) {
            li_options.push('<li class="active-result" data-option-array-index="' + i + '">' + value + '</li>');
          });
$this.parents('tr').find('.chosen-results').html(li_options.join(''));

```

When I press first select and populate chosen select:

Then I press chosen select and it clears:

This approach is working fine when chosen select options are defined from php code and not dynamically added. My question is there any event that I should fire on that the list was changed so it doesn't clear it, or another way it can be solved?

# Answer
> 0 votes
I'm not completely sure about this, but have you tried triggering "chosen:updated" after updating the options? See Updating Chosen Dynamically

```
$("#form_field").trigger("chosen:updated");

```

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


# Question
Title: Set a date field equal to "current time" + "5 minutes" using tokens
I am using the Field Timer module to display countdown timer on my article node.

Say my article node has the date/time field named (field\_article\_datetime)

This module will take the value of the date/time field (field\_article\_datetime) and convert it into a countdown timer in the display of the article.

When the article node is created, I want to set the value of the date/time field (field\_article\_datetime) equal to **current time + 5 minutes.**

To extract the current time, I am using the token \[node:created\] from the token module, but I cannot find a solution on how to **add +5 minutes** to the token \[node:created\].

**EXAMPLE:**

Say at **12/03/2019 08:50:15 PM**, a user has created a new article node... So I need a solution to **add +5 minutes** to the created time so the date/time field named (field\_article\_datetime) will be equal to **12/03/2019 08:55:15 PM**...

This way, the user will see a countdown timer for 5 minutes on the article node display page.

**Note:** I am using the Business Rules module (similar to Rules module) to set the value of the date/time field (field\_article\_datetime) with the help of the token module.

---

**Update #1:** Say the node is already created on the site and I want after the submission of a webform to fetch & update the node with **update time + 5 minutes**.

I think the best Idea is to use a custom module which will do the below:

1. Fetch the article by nid.
2. Set the value of `field_article_datetime` equal to: `updated time + 5 * 60`.
3. Save the Node

Since the above actions will be triggered when a user will submit a webform, so why not create a customwebformhandler.php file.

I have created a custom webform handler file but I need help to finish it since I am not a programmer:

```
<?php

namespace Drupal\my_module_name\Plugin\WebformHandler;

use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Serialization\Yaml;
use Drupal\Core\Form\FormStateInterface;

use Drupal\node\Entity\Node;

use Drupal\webform\WebformInterface;
use Drupal\webform\Plugin\WebformHandlerBase;
use Drupal\webform\webformSubmissionInterface;
use Drupal\webform\Entity\WebformSubmission;

/**
 * Update a node entity from a webform submission.
 *
 * @WebformHandler(
 *   id = "Update a node",
 *   label = @Translation("Update a node"),
 *   category = @Translation("Entity Update"),
 *   description = @Translation("Updates a node from Webform Submissions."),
 *   cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_UNLIMITED,
 *   results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
 *   submission = \Drupal\webform\Plugin\WebformHandlerInterface::SUBMISSION_REQUIRED,
 * )
 */

class UpdateNodeWebformHandler extends WebformHandlerBase {

  /**
   * {@inheritdoc}
   */

  // Fetch & Update node object from webform-submission.

  // Function to be fired while submitting the Webform.
  public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {
    // Get an array of the values from the submission.
    $values = $webform_submission->getData();

    // The webform has an element text field with machine name (update_nid) which
    // contains the node ID of the node to be updated.
    // This is the part where to fetch the node by the value of (update_nid) element.
        Some code here

    // This is the node Updating part.
    $created = $entity->updated->value;
    date_default_timezone_set('GMT');
    $createdadd5 = date('Y-m-d\TH:i:s', $created + 5 * 60);
    $entity->field_article_datetime->value = $createdadd5;

    // This is the node Saving part.
    $node->save();
  }
}

```

# Answer
> 1 votes
I can't think of a solution with just tokens. Here is a quick and dirty solution without tokens

Setup your **Article datetime** field so that has a default relative time of *+5 minutes*

You can hide this field with css so the user will not change it or you can do it in a `hook_form_alter` function in your `MODULENAME.module` file

```
// adjust node_article_form for your content type
if($form_id == 'node_article_form'  || $form_id == "node_article_edit_form"){
  $form["field_article_datetime"]['widget'][0]['value']['#attributes']['readonly'] = 'readonly';
}

```

Of course if a user takes much time to fill the form the set datetime might not reflect exactly the NODE CREATION TIME +5 minutes (as a datetime is set on form creation time)

If the above is not good enough you can probably use `hook_entity_presave` to adjust the time to be EXACTLY the creation time +5 minutes.

```
function MODULENAME_entity_presave(Drupal\Core\Entity\EntityInterface $entity) {
  // adjust article to reflect your content type
  if ($entity->bundle() == "article" && $entity->isNew()) {
    $created = $entity->created->value;
    date_default_timezone_set('GMT');
    $createdadd5 = date('Y-m-d\TH:i:s', $created + 5 * 60);
    $entity->field_article_datetime->value = $createdadd5;
  }
}

```

**NOTE:** if you want to update the timer even on node update you can just delete the `&& $entity->isNew()` part.

---
Tags: 8, datetime, tokens
---


title: Disable field date and checkbox

text:
# Question
Title: Disable field date and checkbox
I'm trying to disable input fields of type date and checkbox in hook\_form\_alter with above code:

```
$key = 'field_name';

$form[$key]['widget'][0]['value']['#attributes']['disabled'] = true;
$form[$key]['widget']['#attributes']['disabled'] = true;
$form[$key]['widget'][0]['#attributes']['disabled'] = true;
$form[$key]['widget'][0]['target_id']['#attributes']['disabled'] = true;
$form[$key]['widget'][0]['#attributes']['disabled'] = true;
$form[$key]['#disabled'] = 'disabled';
$form[$key]['widget']['#attributes']['readonly'] = 'readonly';

```

Disabled all fields (type text or entity reference) but not work for checkbox and date fields. Any ideas for solve this?

# Answer
This is how to disable the field:

```
$form[$key]['widget'][0]['value']['#attributes']['disabled'] = 'disabled';

```
> 0 votes

---
Tags: 8, entities, hooks
---


# Question
Title: How to print author's email address in in node template
I have a content of type summary only visible by the author and administrators. I need to print in my node--summary.tpl.php the author's email address that was set at the account creation.

Any idea how this can be achieved?

# Answer
> 1 votes
Use

```
<?php
  print $user->mail;
?>

```

If `$user` is not available use

```
<?php
  $user = user_load($node->uid);
  print $user->mail;
?>

```

---
Tags: 7, theming, nodes
---


# Question
Title: How to to redirect a form to a certain node for anonymous users?
In a custom module, I have a form that is triggered by an option in a menu.
I'd want this form to be redirected automatically (without action of the user) to a certain node (/node/2) when the user is not authenticated.
In the `public function buildForm(array $form, FormStateInterface $form_state) {`, I know how to not display the fields of the form for the anonymous user:

```
$oCurrentUser = \Drupal::currentUser();
if ($oCurrentUser->isAnonymous()) {
} else {

some fields...

$form['submit'] = [
  '#type' => 'submit',
  '#value' => $this->t('Submit'),
];
return $form;
}

```

I guess that redirection might be done with `$form_state->setRedirect('entity.node.canonical', ['node' => 2]);` but I don't know how to make it work...
Any idea?

# Answer
Using kiamlaluno's advice, the route for the menu is now associated to /association/showMembership.

```
association.membership_showMembership:
  path: '/association/showMembership'
  defaults:
    _controller: '\Drupal\association\Controller\MembershipController::showMembership'
    _title: 'Membership'
  requirements:
    _access: 'TRUE'

```

The controller class uses the following code.

```
class MembershipController extends ControllerBase {
  public function showMembership() {
    if ($this->currentUser()->isAnonymous()) {
      return $this->redirect('entity.node.canonical', ['node' => 2]);
    }
    return $this->formBuilder()->getForm('Drupal\association\Form\Membership');
  }
}

```

The `Membership` form doesn't redirect users in `buildForm()`.
> 1 votes

# Answer
The class implementing `FormInterface` is allowed to return an instance of a class extending the `Response` class, despite `FormInterface::buildForm()` not documenting it. See what a comment in the `FormBuilder::retrieveForm()` code says.

> Exceptions should not be used for code flow control. However, the Form API currently allows any form builder functions to return a response.
> @see https://www.drupal.org/node/2363189

This means that code similar to the following one would actually work.

```
public function buildForm(array $form, FormStateInterface $form_state) {
  // Verify the currently logged in user is an anonymous user and redirect.
  if ($this->currentUser()->isAnonymous()) {
    return $this->redirect('entity.node.canonical', ['node' => 2]);
  }
}

```

Although, since Do not allow form builder functions to return Response objects (the bug report linked in the comment) is open for Drupal 8.8.x, that code could not work anymore, in future.

See also the following comment in the `FormBuilder::buildForm()` code.

> Exceptions should not be used for code flow control. However, the Form API does not integrate with the HTTP Kernel based architecture of Drupal 8. In order to resolve this issue properly it is necessary to completely separate form submission from rendering.
> @see https://www.drupal.org/node/2367555

The linked issue is Deprecate EnforcedResponseException support (a task, not a bug report).

A module that works also after the change described in that issue is implemented would:

* Associate a controller to the route, not a form builder
* In the controller method associated with the route, redirect the anonymous users to the node page, or render the form for authenticated users

```
class RedirectOrFormController extends ControllerBase {
  public function showForm() {
    if ($this->currentUser()->isAnonymous()) {
      return $this->redirect('entity.node.canonical', ['node' => 2]);
    }

    return $this->formBuilder()->getForm('Drupal\\locale\\Form\\TranslateEditForm');
  }
}

```

Replace `'Drupal\\locale\\Form\\TranslateEditForm'` with the fully qualified name of the form builder.
> 2 votes

# Answer
In buildForm() you can return a redirect response the same way as in a controller:

```
  public function buildForm(array $form, FormStateInterface $form_state) {
    if ($this->currentUser()->isAnonymous()) {
      return $this->redirect('entity.node.canonical', ['node' => 2]);
    }

    // build $form for authenticated users

    return $form;
  }

```

Use `$form_state->setRedirect()` if you want to redirect in a form submit handler.

---

Using `buildForm()` as controller by specifying `_form` instead of `_controller` is documented and widely used (not in FormInterface, but on DO: https://www.drupal.org/docs/8/api/routing-system). It's unlikely core will ask devs to replace it by their own controller.
> 1 votes

# Answer
yes, you are right. you can redirect to the node using the code that you have mentioned. There is another way to set the redirection check the below code.

use the name space :

```

use Symfony\Component\HttpFoundation\RedirectResponse;
$response = new RedirectResponse(node url);
$response->send();
exit(0);

```

I don't know what you are trying to achieve hope this code may help you.
> 0 votes

---
Tags: 8, forms
---


# Question
Title: Product / subscription / membership for places on a physical veg box scheme?
My client can provide max 30 veg boxes at any one time, delivered physically. A purchase buys a weekly delivery for 6 weeks (ie 6 veg boxes). When the 6 week period is over, deliveries stop. So there are max 30 places on the veg box scheme. After each customer's 6 week membership has lapsed, the stock level needs to be incremented by 1, indicating that there is now a free place on the scheme.

So I need a way of setting a lapse period on a product (6 weeks), along with a total-stock-at-any-one-time (30 places) setting, which needs to be aware of orders currently in date.

Recurring billing is not required, as customers will have to re-order if they want another 6 weeks membership on the scheme.

I am developing a new site in Commerce 2. Is this use case covered and where? I have hunted in commerce\_stock and commerce\_subscription and docs and videos, but I can't find anything.

Also client needs to print out, every week, names and delivery locations of each person in credit that week. I'm hoping that would be covered by views.

# Answer
You won't be able to do this through views and configuration, such a project requires heavy amounts of custom code.

Eldum Rett is a Commerce 2.x site built for the same use case. You could contact 1xInternet for consulting, since they built it.

Under the hood it's Commerce Recurring, Commerce Recurring Shipping plus custom code.
> 0 votes

---
Tags: commerce
---


# Question
Title: Can webform conditionals require filling one of two fields?
The snippet below is one of the ways I attempted to require that the user fill out at least one of phone no. and/or email using webform conditionals. This one came closest to working. The logic is both fields default to required but that requirement clears when the other field is filled out. It fails because webform interprets it as a circular reference.

Any suggestions? I don't have the technical wherewithal to attempt the answer to question 87889 so looking for a way to do this using webform conditionals. Question 63912 looked promising until I realized it dealt with Drupal fields and not Webform fields.

# Answer
> 0 votes
The Webform Validation module has what you are looking for (*Require at least one of two fields*).

> The following validation rules are currently included:
>
> * Numeric values (optionally specify min and/or max value)
> * Minimum length
> * Maximum length
> * Minimum number of words
> * Maximum number of words
> * Equal values on multiple fields
> * Unique values on multiple fields
> * Specific value
> * Require at least one of two fields
> * Require at least one of several fields
> * Minimum number of selections required
> * Maximum number of selections allowed
> * Exact number of selections required
> * Plain text (disallow tags)
> * Regular expression
> * Must be empty (anti-spam: Hide with CSS)
> * Words blacklist
> * Must match a username

---
Tags: webforms
---


# Question
Title: Twig conditions for node/page/view in page-title.html
I am trying to set different classes in the page-title.html.twig based on what drupal is actually showing. The first condition works in a node template, but not in the page-title.html. This is a pseudo-code of what I am trying to achieve:

```
{%
  set classes = [
    'title--h1',
    node.type.entity.label == 'Blogpost' ? 'ico ico--time',
    page.machine_name == 'about_me' ? 'ico ico--world',
    view.machine_name == 'blogpost_list' ? 'ico ico--target'
  ]
%}

```

# Answer
Try adding this to your `MYTHEME.theme`. This will provide the machine name value to your `page.html.twig` template files.

**MYTHEME.theme**:

```
/**
 * Implements hook_preprocess_HOOK().
 */
function MYTHEME_preprocess_page($variables) {
  $variables['machine_name'] = $variables['page']['#type'];
}

```

Then in **page.html.twig**:

```
{%
  set classes = [
    'title--h1',
    machine_name == 'about_me' ? 'ico ico--world',
  ]
%}

```

`{{ machine_name }}`

For **node.html.twig** templates, use bundle to get the machine name:

```
{%
  set classes = [
    node.bundle == 'content__type' ? 'one-class' : 'another-class'
  ]
%}

```

You cannot access the bundle type in `MYTHEME_preprocess_page_title()` directly.
> 0 votes

---
Tags: theming
---


title: How to download file from URL manually?

text:
# Question
Title: How to download file from URL manually?
I need to upload on Drupal 8 a file from an URL programmatically without using a form and a field type 'managed\_file'. I'm not sure how to do this, I found different web pages on it but it's often the old version of Drupal and only some part of code.

What exactly I want to do :

* I Have an URL (for example a PDF document, a \*.doc, ...)
* I need to save it on Drupal and create the associated record in the database

# Answer
You could keep it really simple by using something like `file_get_contents()` to retrieve your file and save it somewhere on the servers filesystem, presumably `DRUPAL_ROOT/sites/default/files`. After that, you can put in the database whatever you want.

The thing is, Drupal won't know what to do with that in most cases. Files in Drupal must be associated with a file field. That's the way things work.
> 1 votes

---
Tags: 8, files
---


# Question
Title: for anonymous user, webform not submitted because of private file
I have one webform which contain the private file field.

As admin user: i can upload the file and submit the form.

As anonymous user: i can upload the file but while saving the form, i am getting 'file field is required'

Uploaded file '/system/files/webform/abc.jpg' present at '/sites/default/files/private/webform'.

As Anonymous user: i can access file using '/sites/default/files/private/webform/abc.jpg' but get access denied using '/system/files/webform/abc.jpg' url.

Additional Info:

File Setting:

Private Path : 'sites/default/files/private'

Public Path : 'sites/default/files'

Drupal 7.64

Webform : 7.x-4.18

# Answer
First and foremost, you've got an error in how you set up your private files path. It should be located outside of your web root, not as a subfolder of your public files. The way it is now, your private files are actually public. That is the reason why you can acces the file at '/sites/default/files/private/webform/abc.jpg', you shouldn't be able to do that.

Now as to why you get an error uploading it is probably an issue with how your permissions are configured for private files. The anonymous user can upload to the private files, but does not have sufficient permissions to access the uploaded file.
> 0 votes

---
Tags: files, webforms
---


title: What version of PHP/MySQL?

text:
# Question
Title: What version of PHP/MySQL?
I just retrieve maintenance (archive FTP/SQL) of a website running **Drupal 6.22…**

But… I have an Debian 8 server with Apache 2.4, PHP 5.6 and MySQL 5.5... :)

**==\> So my question is : what is the upper version of these software (Apache, PHP, MySQL) can run Drupal 6.22 ?** I think PHP 5.3, but after ? (I know that 6.22 is an old version but I will update after first run).

Really thanks for your help.

# Answer
> 2 votes
Per the d.o. requirements page, D6's requirements are:

* **Web server:** Apache, Nginx, or Microsoft IIS
* **Database:** MySQL 4.1 or higher, PostgreSQL 7.1,
* **PHP:** PHP 5.x only (5.2.5 or higher recommended). Warning: support for PHP 4.x has been dropped. Drupal core should work with PHP 5.3.x, but PHP 5.3.x and higher may produce errors or unexpected behavior especially for contributed modules and themes.

# Answer
> 0 votes
Latest version of Drupal 6 LTS can be run at PHP 7.3 + MySQL 8.0 environment. https://github.com/d6lts/drupal

I had more than twice performance speed up for complex website after migrating from PHP 5.3 + MySQL 5.7.

---
Tags: 6
---


# Question
Title: How do I trigger a modal from a template that points to a controller returning an AJAX response
I am trying to trigger a modal from a twig. The path of the modal is a controller that returns an AJAX response as below:

**Routing code**

```
usgbc_myaccount.get_badges_evidence_controller:
path: '/account/get-badges-evidence/{badge_type}'
defaults:
_controller:
'\Drupal\usgbc_myaccount\Controller\GetBadgesEvidenceController::getEvidence'
_title: ''
 requirements:
_permission: 'access content'
_format: 'html'

```

---

**Controller code**

```
namespace Drupal\usgbc_myaccount\Controller;

class GetBadgesEvidenceController extends ControllerBase
{
/**
* @return AjaxResponse
*/
public function getEvidence($badge_type)
{

    $options = [
      'width' => '50%',
    ];

    $response = new AjaxResponse();
    $response->addCommand(new OpenModalDialogCommand(t('Modal title'),
 $badge_type , $options));

    return $response;
}
}

```

---

Call to router from twig template

```
<a class="use-ajax popup-dialog-class" data-type="modal" href="{{
path('usgbc_myaccount.get_badges_evidence_controller', {'badge_type':
result.badge_type}) }}" data-dialog-type="modal">{{ 'Read more'|t }}</a>

```

---

When I click on the link I get the response in JSON in text area on another page. What is missing? It the approach correct? Any help will be appreciated.

Thanks

# Answer
You're trying to trigger your modal in multiple ways. Right now your twig is saying to open the href in a modal, but your controller is not return html, it's returning a json/ajax response to open its content in a modal.

To fix this you should do one of the following:

1. Update your twig to just point to the link, don't do anything there to trigger a modal. Your current ajax response from the controller is handling opening the content in a modal.
2. Update your controller to return html and leave your twig as-is. In this scenario your twig is handling making the content open in a modal.

I'm not sure about the \_format parameter in your route definition, but I think you can just omit it.
> 3 votes

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


# Question
Title: VotingApi / Fivestar rating Player per Game
Can not figure how this works, and hope is doable.

I'd like to add a feature using the fivestar module but I could not figure it out myself. The work may simply require configuring the module correctly or make code changes.

1. I create a new node with "game" content type for each game.
2. I add the team squad (list of players) for that game. Each player is a separate node, with "player" content type.
3. I would like each player to be voted per game and display the score of the player for that game only. This is where I'm stuck, I could not display player votes per game.

Thanks

# Answer
You can set up an intermediary content type containing two reference fields and a fivestar field. One reference field references the game, the other references the player. Then use views as a block with a contextual filter to display the fivestar and the player info on the game node.
> 0 votes

---
Tags: rating
---


title: Render Date Range on node template

text:
# Question
Title: Render Date Range on node template
I'm trying to render both start and end date on a node template in Drupal 8 from the Date range field from the content type. I've tried multiple ways to no avail.

-- Only shows start date --

```
{{ kint(node.field_date_range.value ) }}

{% if node.field_date_range %}
{{ node.field_date_range.value|date(format='l M j') }}
{% endif %}

```

---

# Answer
Here is the full solution that allowed me to separate the content into a traditional calendar mock-up on a node--events--html.twig:

```
<div class="cal-wrapper">

{% if node.field_date_range.value %}
  <div class="cal-day">
  {{ node.field_date_range.value|date(format='l')  ~ ' thru ' ~ node.field_date_end_range_value|date(format='l') }}
{% else %}
  {{ node.field_date.value|date(format='l') }}
  </div>
{% endif %}

{% if node.field_date_range.value %}
  <div class="cal-month">
  {{ node.field_date_range.value|date(format='M')  ~ ' thru ' ~ node.field_date_end_range_value|date(format='M') }}
 {% else %}
  {{ node.field_date.value|date(format='M') }}
 </div>
 {% endif %}

 {% if node.field_date_range.value %}
   <div class="cal-main-date">
   {{ node.field_date_range.value|date(format='j')  ~ ' thru ' ~ node.field_date_end_range_value|date(format='j') }}
 {% else %}
   {{ node.field_date.value|date(format='j') }}
   </div>
 {% endif %}

 </div>

```
> 1 votes

# Answer
For the end value of a *'data\_range'* field you can use: *'.end\_value'*, instead of *'.value'*, example:

```
{% if node.field_date_range %}
  {{ node.field_date_range.end_value|date(format='l M j') }}
{% endif %}

```

Sorry my bad english.
> 1 votes

---
Tags: theming, entities, datetime
---


title: twitter block module

text:
# Question
Title: twitter block module
I am trying to embed a timeline of tweets to my website's sidebar. I am using Drupal 8. The module "Twitter Block" requires a widget ID but Twitter has stopped providing widget ids and only generates html code but I don't know at which file should I embed this code to. Is there any other way? Any suggestions? Thank you.

# Answer
Sorry for this late reply... but here is the module you are looking for:

Twitter API Block

As explained in its README file, you need to download it and the required library with composer, as follow:

```
composer require drupal/twitter_api_block drupal/j7mbo/twitter-api-php

```

Then go create a new app in Twitter and finally, place the block in your Drupal site.

Simple :) Enjoy!
> 0 votes

---
Tags: 8
---


# Question
Title: Translating variables with context in Twig templates
In Drupal 8, with English and German enabled, I am trying to translate a variable using a specific context.

When visiting a page **in German**:

```
{% trans with {'context': 'Long month name'} %}
    March
{% endtrans %}

```

> This outputs **März** which is fine.

---

```
{% set month = 'March' %}

{% trans with {'context': 'Long month name'} %}
   {{ month }}
{% endtrans %}

```

> This outputs **March** which is **not** fine.

---

Why? And how am I supposed to translate variables in a Twig template?

Here is the documentation I have read.

---

**Edit**: https://www.drupal.org/node/2357633

This mentions:

> *The `t` filter will run the variable through the Drupal `t()` function, which will return a translated string. **This filter should be used for any interface strings manually placed in the template that will appear for users**.*

And also:

> *The following patterns are unsafe and should not be used because they pass a variable directly to translation. This not only inflates the list of strings for translation but is also a potential vulnerability, particularly if the output can be entered by a user.*

```
{{ var1|t }}
{{ var1|placeholder }}
{% trans %}{{ var1 }}{% endtrans %}

```

# Answer
A variable is like a placeholder. It does *not* get translated. Context or not is not relevant. Your example basically translates to t('@month', \['@month' =\> 'March'\], \['context' =\> 'Long month name'\]). It simply doesn't work like that.

if you need to translate march and then put it as a variable in a bigger text, you first need to translate March on its own using the context and then put it in the other text.

I'm not sure if you can do that within twig, but I suppose that's only a simplified example and you actually get month injected? Then you need to translate the month name at the source, where it is provided to the template. If that is not the case, then you need to explain your actual use case, because I suppose this is not it..
> 2 votes

# Answer
In Drupal 8, you can translate a string in a Twig file with a specified context in two ways :

```
{{ "Text to translate"|t({}, {'context' : 'Context name'}) }}

```

and

```
{% trans with {'context': 'Context name'} %}
    Text to translate
{% endtrans %}

```
> 9 votes

---
Tags: theming, 8, i18n-l10n
---