# Question
Title: Can I create non-default EntityReferenceSelection?
I have the following `EntityReferenceSelection` plugin:

```
/**
 * Provides an entity reference selection for my_entity.
 *
 * @EntityReferenceSelection(
 *   id = "extra:my_entity",
 *   label = "...",
 *   entity_types = {
 *     "my_entity"
 *   },
 *   group = "extra",
 *   weight = 1
 * )
 */
class MyEntityExtraSelection extends DefaultSelection {

  protected function getAllowedIds() {
    return [...];
  }

  protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
    $query = parent::buildEntityQuery($match, $match_operator);
    $query->condition('id', $this->getAllowedIds(), 'IN');
    return $query;
  }

  public function validateReferenceableNewEntities(array $entities) {
    $entities = parent::validateReferenceableNewEntities($entities);
    $allowed = $this->getAllowedIds();
    return array_filter($entities, function ($entity) {
      return in_array($entity->id(), $allowed);
    });
  }

}

```

I'd like to call it `extra:my_entity` because I don't want this filtering to occur by default, every time I use it, only when I refer to it using the `'handler' => 'extra'` setting explicitely.

But the core plugin manager gives these errors:

```
Warning: uasort() expects parameter 1 to be array, null given in Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManager->getPluginId() (line 65 of core/lib/Drupal/Core/Entity/EntityReferenceSelection/SelectionPluginManager.php).
Warning: end() expects parameter 1 to be array, null given in Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManager->getPluginId() (line 66 of core/lib/Drupal/Core/Entity/EntityReferenceSelection/SelectionPluginManager.php).
Warning: key() expects parameter 1 to be array, null given in Drupal\Core\Entity\EntityReferenceSelection\SelectionPluginManager->getPluginId() (line 67 of core/lib/Drupal/Core/Entity/EntityReferenceSelection/SelectionPluginManager.php).

```

# Answer
## Update

I needed it again, this time already in Drupal 10. The old tricks are no longer necessary, it works without the deriver and the extra key now.

## Earlier

Finally, after some investigation, two required items never documented:

* unlike the core `EntityReferenceSelection` plugins that, for some reason, get away without it, you have to provide

```
deriver = "Drupal\Core\Entity\Plugin\Derivative\DefaultSelectionDeriver"

```

in the plugin annotation.

* It might be completely unnecessary in your case but you have to make sure your custom entity type has an `entity_key` named `label`. If it doesn't, core will use `PhpSelector` instead of your selector, forcedly.
> 3 votes

# Answer
As commented, you should not need to provide a deriver for a single entity reference selection plugin. A random plugin ID like `extra_my_entity` should work. The only condition is that you define the (in this case irrelevant) `group` property with the same value:

```
/**
 * Provides an entity reference selection for my_entity.
 *
 * @EntityReferenceSelection(
 *   id = "extra_my_entity",
 *   label = "...",
 *   entity_types = {
 *     "my_entity"
 *   },
 *   group = "extra_my_entity",
 *   weight = 1
 * )
 */
class MyEntityExtraSelection extends DefaultSelection {

```

See Entity reference selection plugins break when not following a weird ID pattern.

When you extend DefaultSelection then also extend the schema:

*config/schema/mymodule.schema.yml*

```
entity_reference_selection.extra_my_entity
  type: entity_reference_selection.default
  label: '...'

```

---

**Starting a new group**

A group in contrast consists of multiple plugin classes. A base class that derives the installed entity types using for example the base plugin ID `extra`. On installation Drupal will scan the entity types and create for each entity a plugin ID: `extra:[entity_type]`. You can override the base class by using this plugin ID syntax and the group `extra`. These group members then don't need to define a `deriver`, like the core plugins you've seen overriding `default:*`.

It's not a good idea to combine base and group member in one class, because then deriving the plugin ID as base ends up in `a:b:b` and other unpredicted things can happen.
> 4 votes

---
Tags: entities, 9
---


# Question
Title: Add a calculated column programmatically using views data export
I am using the views data export module with Drupal 8. I have a view that shows a list of users and the desired columns to be exported to the csv are:

* Name
* Trained
* Status

Unfortunately, both of the Trained and Status columns are calculated through a semi-complex method from my module. Using the calculated field module isn't really an option.

Ideally my csv should look something like the below. The "Trained" and "Status" columns would be calculated by running the user\_id through their respected methods:

```
Name | Trained | Status
user_name_1 | is_trained(user_id_1) | get_status(user_id_1)
user_name_2 | is_trained(user_id_2) | get_status(user_id_2)
...

```

I have tried what I feel is every combination of views pre\_render, post\_render, post\_execute, etc...; however, I just can't seem to find a way to add a calculated value to the row. It is possible I am approaching this wrong but any suggestions on how to accomplish this would be appreciated.

# Answer
> 1 votes
I am going to go ahead and answer my own post to help anyone else out.

A simple way to do this for me was to write a views plugin as suggested in the comments.

Here is a great link to walk you through this: https://www.webomelette.com/creating-custom-views-field-drupal-8

I do not feel I can write any explanation better than what is done in this article so I would jump over there for more information.

---
Tags: 8, views
---


# Question
Title: Post content via JSON API: CURL works, PHP not?
I've got those modules enabled:

* HAL
* HTTP Basic Authentication
* JSON:API
* REST UI
* RESTful Web Services
* Serialization

When I run this command, the content is created.

```
curl \
--user demo:9aqW72MUbFQR4EYh \
--header 'Accept: application/vnd.api+json' \
--header 'Content-type: application/vnd.api+json' \
--request POST http://www.demo.drupal/jsonapi/node/article \
--data-binary @payload.json

```

Now I try to read via PHP, which works fine too.

```
require 'vendor/autoload.php';

use GuzzleHttp\Client;

// Update to a user on your Drupal site that has permissions to create content
$user = 'demo';
$pass = '9aqW72MUbFQR4EYh';
$url = 'http://www.demo.drupal';

$content_client = new GuzzleHttp\Client([
    'base_uri' => $url,
    'timeout'  => 20.0,
]);

$res = $content_client->request('GET', '/jsonapi/node/mail/71adf560-044c-49e0-9461-af593bad0746');

$body = $res->getBody();
$stringBody = (string) $body;
var_dump(json_decode($stringBody, true));

```

I can't post content. The code I am using returns a 401, 402, or 500 error.

```
$headers = [
  'Content-type' => 'application/vnd.api+json',
  'Accept' => 'application/vnd.api+json'
];
$payload['data'] = [
  'type' => 'node--article',
  'attributes' => [
    "title" => "My custom title"
  ]
];

$guzzleResponse = $content_client->post('/jsonapi/node/article', [
  'json' => json_encode($payload),
  'headers' => $headers
]);

if ($guzzleResponse->getStatusCode() == 200) {
  $response = json_decode($guzzleResponse->getBody());
}

```

What am I doing wrong?

# Answer
The 401 error is because you're not sending the basic auth creds like you are with your curl request. You need to add an Authorization header to your Guzzle request:

`'Authorization' => 'Basic ' . base64_encode($user . ':' . $pass),`

The 500 error is likely due to a malformed payload that JSONAPI can't parse. The value of `json` should be an associative array, not a JSON encoded string. See the Guzzle docs on uploading JSON data.
> 5 votes

---
Tags: nodes, 9
---


# Question
Title: Change individual file from public to private and vice-versa
Running Drupal 7. I have two file fields set up: One is public, the other private. I need to be able to take a file which has been saved as a public file, and switch it to the private file field. And, vice-versa. Can someone provide some some advice on this? Thanks!

# Answer
> 3 votes
I've written an update script to switch a file field from private to public:

```
function MYMODULE_update_7100(&$sandbox) {
  $field_name = 'MY_FIELD_NAME';

  $fids_data = db_select('field_data_' . $field_name, 'dat')
    ->fields('dat', array($field_name . '_fid'))
    ->execute()
    ->fetchCol();

  $fids_revision = db_select('field_revision_' . $field_name, 'rev')
    ->fields('rev', array($field_name . '_fid'))
    ->execute()
    ->fetchCol();

  $fids = array_unique(array_merge($fids_data, $fids_revision));

  // Move files using Drupal's File API
  $files = file_load_multiple($fids);
  foreach ($files as $file) {
    if ($file && file_exists($file->uri)) {
      $destination = str_replace('private:', 'public:', $file->uri);
      $directory = drupal_dirname($destination);
      if (file_prepare_directory($directory, FILE_CREATE_DIRECTORY|FILE_MODIFY_PERMISSIONS)) {
        file_move($file, $destination, FILE_EXISTS_RENAME);
      }
    }
  }

  // Update field configuration
  $field = field_info_field($field_name);
  $field['settings']['uri_scheme'] = 'public';
  field_update_field($field);
}

```

What this function simply does:

1. Gets the `fid` of all files from `field_data` and `field_revision` tables.
2. Moves files using File API
3. Updates field configuration

# Answer
> 0 votes
I'm assuming that your "fields" are fields on a content type, but I think this advice is helpful regardless.

1. Use the File API (also, here) to store your files;
2. Store the row id from the managed\_files table ($file-\>fid) in your fields.

When you need to switch a file from one to the other, just set the values of those fields (for example, load the content using entity\_load and set the field's value with something like `$my_content->public_file_id = NULL` and `$my_content->private_file_id = 3`.

...AND when referring to the file, use the public:// or private:// notation. You'll see that there's methods for actually moving the file, too, if you need to do so. I've only scratched the surface, but the File API has been very useful.

# Answer
> 0 votes
I finally got this to work. Essentially, Micheal's response (first response to original question) was a good guideline for beginning. I'll add some notes here in case someone else is looking for this solution.

First, you need to be able to modify the file attachment widget in order to put in a checkbox or button or whatever you want to use to indicate that an existing file needs to be switched from one file\_attachment field to another. I used this very excellent tutorial as my guide to modify the widget: Drupal7 tip: Alter a field widget by
Dominique De Cooman (google this).

Next, you need to process the results of this form -- that is, create code which will actually do the physical switching. I tried using hook\_node\_update(), but found out it would not save my changes. I ended up putting my processing code into hook\_node\_presave();

My processing consisted of:

1. Moving the file's file\_attachments field elements in the $node from public table to private (or vice-versa) as suggested by Michael.
2. Copying (or moving) the physical file using the file api. I discovered that you can use file\_move() to move from from private to public, but you must use file\_copy() to move file from public to private. This is because when you remove the public file\_attachment's field info in the $node, that ends up deleting the physical file (or, at least removing it from the file\_managed table).

Also don't forget to use the public:// and/or private:// uris as appropriate when copying/moving files.

Of course, there are a lot of little details in between, but the gist of it is that it can be done, and Michael's outline is a great roadmap for at least one way to do it.

# Answer
> 0 votes
I am using the following query to change all files from public:// to private://. This also will update URLs contained in content body and summary.

```
START TRANSACTION;

# WARNING: Do not just blindly run this without making sure that this only modifies what you want.

SET @public = '"/sites/default/files/';
SET @private = '"/system/files/';

# change field URI scheme from public:// to private://

UPDATE field_config
SET `data` = REPLACE(field_config.`data`, 's:10:"uri_scheme";s:6:"public";', 's:10:"uri_scheme";s:7:"private";')
WHERE `data` LIKE '%s:10:"uri_scheme";s:6:"public";%'
;

# update URLs of files

UPDATE file_managed
SET file_managed.uri = REPLACE(file_managed.uri, 'public://', 'private://')
WHERE fid=fid
;

# update URLs in content body and summaries

UPDATE field_revision_body
SET field_revision_body.body_value = REPLACE(field_revision_body.body_value, @public, @private)
WHERE field_revision_body.body_value LIKE CONCAT('%', @public, '%')
    AND field_revision_body.revision_id IN (SELECT revision_id FROM field_data_body)
;
UPDATE field_revision_body
SET field_revision_body.body_summary = REPLACE(field_revision_body.body_summary, @public, @private)
WHERE field_revision_body.body_summary LIKE CONCAT('%', @public, '%')
    AND field_revision_body.revision_id IN (SELECT revision_id FROM field_data_body)
;

UPDATE field_data_body
SET field_data_body.body_value = REPLACE(field_data_body.body_value, @public, @private)
WHERE field_data_body.body_value LIKE CONCAT('%', @public, '%')
;
UPDATE field_data_body
SET field_data_body.body_summary = REPLACE(field_data_body.body_summary, @public, @private)
WHERE field_data_body.body_summary LIKE CONCAT('%', @public, '%')
;

/*
COMMIT;

ROLLBACK;
*/

```

After this, move the files themselves from your public files directory to the private directory.

---
Tags: 7, files
---


# Question
Title: Using cache tags for a particular node list
Caching in Drupal 8 is great, but documentation is thin (at this time) on using cache tags for render arrays in Drupal 8.

I have some code that basically generates a list of node teasers, say for content types "books" and "magazines". I'm caching the list to speed things up. I would like to refresh the list every time a "book" or "magazine" is added/deleted/edited. So I have a render array that looks like this:

```
$build = array(
  '#type' => 'markup',
  '#markup' => $sMarkup,
  '#cache' => [
    'keys' => ['home-all','home'],
    'tags'=> ['node_list'], // invalidate cache when any node content is added/changed etc.
    'max-age' => '36600', // invalidate cache after 10h
  ],
);

```

By using the cache tag \['node\_list'\], the cache invalidates properly when content is added or edited, but will also invalidate when a content type not being listed here is changed, say "casette".

What cache tags can I use to limit the invalidation to when only "book" or "magazine" is added/changed/deleted? I've tried using: \['book\_list','magazine\_list'\] but that doesn't work.

# Answer
> 6 votes
Starting Drupal 8.9.0, there is a new `ENTITY_TYPE_list:BUNDLE` cache tag added (see the change record).

So in your case you would simply need to tag our list with `node_list:book`.

https://www.drupal.org/node/3107058

# Answer
> 4 votes
In this case I know two options.

One - Include all node tags (node:{#id}), if doesn't matter if a new node of a particular type was added.

Two - Create and control your own cache tag, and invalidade it when you want.

I'm developing a site that was needed create a term list cache per vocab\_id. In this case every time that a term from a particular vocab\_id change/add/delete the cache tag is invalided using `Cache::invalidateTags($tag_id)` then my block will be rebuild.

**Edit 1**

Example:

```
use Drupal\Core\Cache\Cache;

function filters_invalidate_vocabulary_cache_tag($vocab_id) {
  Cache::invalidateTags(array('filters_vocabulary:' . $vocab_id));
}

```

In your case maybe is just change `$vocab_id` for `$node_type`.

# Answer
> 1 votes
See the contrib module handy\_cache\_tags. I haven't used it (yet), but it purports to do exactly what you are looking for. From the module's description:

> The module provides the following cache tags for you to use:

```
handy_cache_tags:[entity_type]
handy_cache_tags:[entity_type]:[entity_bundle]

```

---
Tags: 8, caching
---


# Question
Title: How to make a case sensitive entity query?
My custom entity type comes with a string field for which I would prefer case sensitive queries. When I use

```
$query = \Drupal::entityQuery('my_entity_type')
 ->condition('my_token_field', 'SomeSortofTokenString')
 ->execute();

```

the result will include all entities no matter if the string in `my_token_field` is written the same way or for example with lowercases only. `my_token_field` is set a base field of type string - maybe this is the problem?

# Answer
As the issue in a comment under my question describes this is the way to go:

```
 $given_token = 'AbTg4576Ft6h6';
 $result = \Drupal::database()->select('my_database_table', 't')
    ->where(
      'binary my_token_field = :given_token',
      ['given_token' => $given_token]
    )
    ->fields('t', ['id'])
    ->execute()
    ->fetchAll();

```
> 1 votes

# Answer
Like you already said, I think you should set case\_sensitive to true in the field settings, like here. This can also be set in the config.

When digging in the code, I found that the condition function at some point leads to translateCondition which checks if a field is case sensitive and automatically applies the binary option to the sql query.
> 1 votes

---
Tags: 8, entities, database
---


# Question
Title: Is there a way to display webform submission based on element values?
I create a webform in Drupal 8 with certain elements (first name, last name, email, phone, visible (Yes / No)).

I want to display the results of the webform based on the element (visible = Yes), so that other roles cannot see the results where visible = No.

How can I do that? How can I filter webform submissions based on element values?

# Answer
> 0 votes
You can achieve this with Webform Views Integration. This module allows you to build a view of webform submissions. You then can use Views' filtering on elements values.

Unclear is where you want to display them. But with Webform Views Integration you can of course build a view page with an URL or view block as you need.

> Use Webform Views Integration module to expose Webform submissions to Views (Webform is a module for making forms and surveys in Drupal).

---
Tags: 8, webforms
---


# Question
Title: Sales Tax Exemption for an Authorized User?
I have my Drupal Commerce store set up to apply my state sales tax on appropriate purchases. I also have an authorized user who has a state-approved sales tax exemption. I'm trying to configure my tax type such that no sales tax will be applied on their orders, but I'm not having much luck.

I've installed the Commerce Product Tax Conditions module, which appears to support a customer role condition. The module documentation doesn't identify that condition as "apply sales tax for this role" or "exempt this role from sales tax", though, and I haven't been able to apply an exemption.

How can I make this work?

# Answer
> 0 votes
After looking at the code I figured out that this module isn't about conditions to provide exemptions. It's about conditions to apply the tax.

So yes, to make it work you have to check all of the roles for which you want the tax applied and leave out the roles for which tax should not be applied. It might also be necessary to apply a patch and add a setting.

---
Tags: 8, commerce
---


# Question
Title: How can I change the user login tabs labels?
I am pretty new to Drupal and wonder if there's any possibility to change the text of the user login / create an account and reset tab? I'd like to rename them to something like "sign in", "sign up" and "reset account".

I found no way through the backend UI. Neither in Tabs Block Content nor Menu structure.

Do I need to write a theme hook or a module to achieve that, or is there any functionality in the backend I've overlooked?

# Answer
As shown in the answer to the duplicate question you can use `template_preprocess_menu_local_task` from a custom theme or `hook_preprocess_HOOK` from a custom module to override the tabs.

If you want to do it right, you also set the page title and the HTML title to display the same strings. Maybe keep things DRY and get the `$target_routes` array from a small helper function.

First the tabs:

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

  $target_routes = [
    'user.login' => t('sign in'),
    'user.register' => t('sign up'),
    'user.pass' => t('reset account'),
  ];
  $current_route = \Drupal::routeMatch()->getRouteName();

  if (isset($target_routes[$current_route])) {
    /** @var \Drupal\Core\Url $url */
    $url = $variables['link']['#url'];
    $route_name = $url->getRouteName();
    $variables['link']['#title'] = $target_routes[$route_name];
  }
}

```

Then the page title:

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

  $target_routes = [
    'user.login' => t('sign in'),
    'user.register' => t('sign up'),
    'user.pass' => t('reset account'),
  ];
  $current_route = \Drupal::routeMatch()->getRouteName();

  if (isset($target_routes[$current_route])) {
    $variables['title'] = $target_routes[$current_route];
  }
}

```

And finally the HTML title:

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

  $target_routes = [
    'user.login' => t('sign in'),
    'user.register' => t('sign up'),
    'user.pass' => t('reset account'),
  ];
  $current_route = \Drupal::routeMatch()->getRouteName();

  if (isset($target_routes[$current_route])) {
    $variables['head_title']['title'] = $target_routes[$current_route];
  }
}

```
> 3 votes

# Answer
You could also make use of the Hook regarding the menu alter depending on your needs. A sample of it could be something like :

```
function MYMODULE_menu_alter(&$items) {
    $items['user/%user/track/navigation']['title'] = "Track Your Posts";
    $items['user/%user/view']['title'] = "View Profile";
    $items['user/%user_category/edit']['title'] = "Edit Profile";
}

```
> -1 votes

---
Tags: 8, theming
---


# Question
Title: How do I display only products that do not exceed the end date?
I created in my product type, a "Date interval" field.

I created a view that contains this field. With a start date and an end date.

I want my view to show only products that are within the end date.

I have searched in "FILTER CRITERIA" and I could not find anything to limit the results of my sight.

How do I display only products that do not exceed the end date?

# Answer
Try using the views query alter (assuming you are using views since you have been wondering in the filter section). A sample of it would work something like this :

```
function HOOK_views_query_alter(\Drupal\views\ViewExecutable $view, \Drupal\views\Plugin\views\query\QueryPluginBase $query) {

    if ($view->id() == 'YOUR VIEW MACHINE NAME') {
        $query->setWhereGroup('AND', 0);
        $query->addWhere(0, "Field NAME FROM Database for date", "ARRAY OF DATES FOR FILTER", 'In');
    }

```

Just Replace this with the keys for your requirements and it should work.
> 0 votes

---
Tags: 8, views, entities, datetime
---


# Question
Title: Target EntityBrowser in custom validation constraint
Having a custom validation constraint on an entity reference field using entity browser as form widget, I am trying to get the field light up in the form on validation violation. This is not working for me.

Using the following code in an entity validation constraint:

```
      $this->context
        ->buildViolation($constraint->message, [])
        ->atPath('field_entity_reference')
        ->addViolation();

```

This works fine for fields that do not use the entity browser widget (the field gets marked red indicating an validation error). But for the entity browser widget the field is not marked in the form, though the validation itself is working correct. It seems to me this is related to the entity browser widget. There is this information about targeting specific properties in complex field widgets, which seems to address this matter. But I cannot seem to find a way to target the right property to make the field light up in the form. Entity Browser widget only have hidden form input elements and targeting does not seem to work on container or div fields as far as I can see, so maybe this is the reason this is not working?

Is there a possibility to have the entity browser widget light up in the form on validation violation?

# Answer
I think this is a limitation of Entity Browser module. Drupal is ultimately using setErrorByName() to add the error to the form and Entity Browser does not provide a name attribute that Drupal can attach it to. So if a name attribute is added somewhere in the entity browser widget Drupal could attach the error. That is, Drupal does only visibly attach the error to (visible) input, select and textareas in the form. Other elements may be targeted and get the class "error" added, but this will not show visibly as an error in the form.

I have created a small module to provide the error flagging for the entity browser widget: https://www.drupal.org/project/entity\_browser\_validation
> 0 votes

---
Tags: 8, forms, entities
---


# Question
Title: How can I hide revision information on node forms?
Trying to figure out how to hide revision information from node form. When users create a node, they see revision info at the bottom which confuses them. I can't seem to disable revision info from the content type edit settings since there are nodes already. So the only solution is to hide it.

The way that I am going is by trying to add this:

```
$form['revision_information']['#access'] = false;

```

My question is how can I add that to my theme-name.theme file?

The content type is QUESTIONS

# Answer
> 10 votes
Please try below code in your theme-name.theme file.

```
/**
 * Implements hook_form_alter().
 */
function THEMENAME_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  $form['revision_information']['#access'] = FALSE;
}

```

# Answer
> 2 votes
There also is the Hide Revision Field module which makes the revision info another field you can disable in the form mode of an entity. It also gives you some more options, like permission based display etc.

> Hide Revision Field provides a configurable field formatter for the revision log field for revisionable entities. This allows you to create revisions but reduces noise for your content editors/site owners. All revisionable entity types are supported including module added.

# Answer
> 1 votes
When you create a new content type you have the option to not create new revisions. Whilst you can set that for future content any existing nodes will still have revisions on. If there are not too many to change you could manually uncheck this or write a script in the database to uncheck them.

# Answer
> 0 votes
Try hiding it using css:

```
.field--name-revision-log-message {
  display: none;
}

```

I used this for media.

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


# Question
Title: How do I hide the submission button basing on some conditions?
I have a webform with a mandatory Yes/No button. I want to hide the submission button if *No* is selected.

How can I set up the logical condition for achieving this?

# Answer
> 5 votes
I just figured out that there is the 'Submit' element at the end of the webform elements under webform build tab and I can apply the conditions on that 'Submit' element.

# Answer
> -2 votes
If I were you I'd make it easier for myself and leave it as is.

Because if the answer is no and you don't want him to submit at all so bother to make him do it from the first place!

But: if you need this to happen it is possible to have a little JavaScript doing that for you, see this Example

---
Tags: 8, webforms
---


# Question
Title: Disable vertical tabs by content type or user role
Some users may only have the ability to edit one of the fieldsets that shows up in vertical tabs on the node edit form. In such a case it looks rather silly to be using vertical tabs since there is only one vertical tab to choose from. See screenshot:

So, is it possible to disable vertical tabs by user role? Or, barring that, disable them altogether for certain content types? For my use case I just want Location to not be displayed in vertical tabs.

I tried Renderable Fields and Field Group together but they managed the form incorrectly (buggy, I think). Arrange Fields can't separate out Vertical Tabs.

# Answer
There are few ways to do this:

1. You can use the Renderable Elements module (as you mentioned above). It enables you to register any piece of build on your installation and manage the display through Field UI. It will make (additional) elements available of existing entities on the manage forms/display screens or you can for example register the contact form and rearrange the fields through Field UI. Works currently fine on forms, support for other is coming in a second iteration.
2. Or add the following to your custom module:

```
$config['yourcontenttype_node_form'] = FALSE;
variable_set('vertical_tabs_forms', $config);

```
3. A sandbox module that disables vertical tabs

Here is this core issue that refers to this.
> 7 votes

# Answer
You can also use the #access check to keep people from seeing the vertical tabs.

```
$form['additional_settings']['#access'] = FALSE;

```

Simply add that to a hook form alter or in between the loading and the rendering of a form. After that you can call render($form) to get the markup.
> 6 votes

# Answer
I wrote a simple possible solution in the already mentioned thread: https://drupal.org/node/1048644#comment-7822687. For convenience, I'll paste it here.

There's a simple way to disable vertical tabs on a form, by simply changing the `$form['additional_settings']['#type']` variable's value to `'fieldset'` in an implementation of hook\_form\_alter() or hook\_form\_FORM\_ID\_alter(), if it's equal to `'vertical_tabs'`.
You don't need to change the access settings or walk the whole `$form` array recursively, the latter consumes unnecessarily too much resources.
(Tested in Drupal *7.23*.)

```
/**
 * Disable Vertical tabs on a form with simply changing the value of $form['additional_settings']['#type']
 * @see https://drupal.org/node/1048644
 */
function form_disable_vertical_tabs(&$form){
  // originally $form['additional_settings']['#type'] equals to 'vertical_tabs'
  if(isset($form['additional_settings']['#type']) && ($form['additional_settings']['#type'] === 'vertical_tabs')){
    $form['additional_settings']['#type'] = 'fieldset';
  }
}

/**
 * Implements hook_form_alter().
 */
function MYMODULEORTHEMENAME_form_alter(&$form, &$form_state, $form_id) {

  if($form_id == 'my_form_id'){
    // disable vertical tabs for this form
    form_disable_vertical_tabs($form);
  }
}

```

That's all, of course, **substitute `MYMODULEORTHEMENAME`** to your own module's or theme's name (the latter in a `template.php` file), **and `my_form_id`** to your form's id.

---

You can also disable the vertical fields only for users **who do NOT have the administrator role**:

```
/**
 * Implements hook_form_alter().
 */
function MYMODULEORTHEMENAME_form_alter(&$form, &$form_state, $form_id) {

  global $user;
  $is_administrator = in_array('administrator', array_values($user->roles));

  if($form_id == 'my_form_id'){
    // if $user does NOT have the administrator role.
    if (!$is_administrator) {
      // disable vertical tabs for this form
      form_disable_vertical_tabs($form);
    }
  }
}

```

In case someone is interested, I attached a patch (which does the same as above) to **Dripman**'s sandbox module: #2080739: Simplify the method of disabling Vertical tabs with just changing the `$form['additional_settings']['#type']` to `'fieldset'`.
> 2 votes

# Answer
Render-able elements is not currently supported, and acknowledges on the project page that it clashes with some other contributed modules so I wouldn't rely on it for production sites.

The question of how to disable vertical tabs completely is tackled in this thread.

Dripman has created a simple sandbox module to disable vertical tabs completely.

Depending on your desired level of engagement with coding, Dripman's module should be easily customisable to be selective on the basis of fields/roles.

Apologies for overlap with succinct answer by @nicoz
> 0 votes

# Answer
You can use the module Vertical Tabs Visibility.

> This module helps to manage vertical tabs visibility on content type add/edit forms.
>
> To manage vertical tabs visibility on content type add/edit forms. simply visit `/admin/config/user-interface/vertical-tabs-visibility` page and select content types. Vertical tabs at node add/edit form will be disabled for checked content types.

Currently module is in sandbox
> 0 votes

# Answer
For my use case, I was trying to disable the vertical tabs being applied on the **Publishing options** section on a node edit form (since this was the only fieldset a particular set of users have access to):

```
// Place somewhere in MYMODULE_form_alter()...
$form['additional_settings']['#type'] = 'fieldset';
$form['additional_settings']['#collapsible'] = FALSE;
$form['options']['#collapsible'] = FALSE;

```

For clarification, not only do you need to set `additional_settings` `#collapsible` to FALSE, any elements within must also have #collapsible`set to`FALSE`, in my case that was the`options\` element.
> 0 votes

# Answer
There's the Vertical Tabs Config module which offers hiding some or all tabs by role or for all users.

> This module allows you to:
>
> * Hide vertical tabs on add/edit node pages depending on content type and role.
> * Decide vertical tabs order (with a drag and drop interface since version 1.2).
> 0 votes

---
Tags: 7, entities, location, nodes
---


# Question
Title: Displaying a single result out of three results
I have a view block that is set up to produce three product titles sorted from a taxonomy term (*flowers*). I have a view whose machine name is *latest\_products*.

In a preprocess function I use the following code.

```
$variables['views_twig_var'] = views_embed_view('latest_products','block_1');

```

In a template, I use `{{ views_twig_var }}`, which produces all three titles on the page.

If it's possible, how would I use it in the template file to only show the first result?

`{{ views_twig_var[0] }}` doesn't work.

I would then use the second result further down the page, with the final result even further down.

For now, I created it in three different blocks, with each block producing a single result, but for my curiosity and for future reference I am wondering if there is a faster way.

# Answer
you can do it without preprocess, by using the Twig Tweak module, it gives you the possibility to render your view in twig with display filters and so on like the following:

```
{{ drupal_view_result('latest_products', 'block_1') }}

```

The `drupal_view_result` give you the array of result so you can get the first result with:

```
{{ drupal_view_result('latest_products', 'block_1')[0] }}

```

of type **ResultRow** and then get the entity with:

```
{{ drupal_view_result('latest_products', 'block_1')[0]._entity }}

```

For more information see the module Cheat sheet page
> 2 votes

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


# Question
Title: How do I include data from the order item type fields in the order receipt email?
I have created an "Event Registration" product type and order item type. In the order item type, I added fields for the registrant's name and job title. How can I print the submitted values for those fields in the commerce-order-receipt.html.twig?

# Answer
Figured it out! Took a few steps:

1. I created a View of type: Order Item. Added my custom fields to that view (Job Title, etc).
2. Added a Contextual Filter "Order item: ID". Provide Default Value: Content ID from URL.
3. I created a Viewfield on each of my Order Item Types, using the View I created in the previous step.
4. I went to /admin/commerce/config/order-item-types/default/edit/display and hid all the fields except for the Viewfield. Repeat for the other Order Item Types. In commerce-order-receipt.html.twig, add this code (which was found in commerce-checkout-order-summary.html.twig):

```
{{ order_item|commerce_entity_render('summary') }}

```
5. Style the output as you like in the receipt twig. Here is the pertinent portion of mine in case anyone finds it helpful:

```
        <tr>
          <td>
            {% block order_items %}
            <table style="padding-top: 15px; padding-bottom:15px; width: 100%">
              <tbody style="text-align: left;">
              {% for order_item in order_entity.getItems %}
              <tr>
                <td>
                  <span style="font-size: 15px;">
            {{ order_item.getQuantity|number_format }} x
            <span style="font-weight: bold;">{{ order_item.label }}</span>
            <span style="float: right;">{{ order_item.getTotalPrice|commerce_price_format }}</span>
          </span>
          <br>
          {{ order_item|commerce_entity_render('summary') }}
          <br><br><hr><br>
                </td>
              </tr>
              {% endfor %}
              </tbody>
            </table>
            {% endblock %}
          </td>
        </tr>

```
6. Clear cache, and that's it!
> 1 votes

# Answer
I just needed one product attribute (with field machine name 'field\_message') to be included in the item rows in the e-mail, so I adapted the template like this:

```
      {% for order_item in order_entity.getItems %}
      <tr>
        <td>
          {{ order_item.getQuantity|number_format }} x
        </td>
        <td>
          {{ order_item.label }}
        </td>
        <td>
          {% if order_item.field_message.value %}
            {{ order_item.field_message.value }}
          {% endif %}
        </td>
        <td style="text-align: right;">
          {{ order_item.getTotalPrice|commerce_price_format }}</span>
        </td>
      </tr>
      {% endfor %}

```

So if the order\_item has a value for field\_message, that value goes into a new third table column (if not then the cell is empty), with the fourth column now right-aligned with the total price as before.

And instead of putting this commerce-order-receipt.html.twig file in a new custom module, I just included it in my existing custom theme (in its templates directory), with the following in the THEMENAME.theme file:

```
/**
 * Implements hook_theme().
 */
function THEMENAME_theme($existing, $type, $theme, $path) {
  return [
    'commerce_order_receipt' => [
      'template' => 'commerce-order-receipt',
      'base hook' => 'commerce_order_receipt',
    ],
  ];
}

```
> 0 votes

---
Tags: 8, commerce, emails
---


# Question
Title: How to create a view filter plugin to filter a column created by a view field plugin
I have created a view field plugin to display an "internal status" for each node in a view.

Those status are not stored in a table (and should not) because each status may vary depending the current date (and some other fluctuating data).

The possible status outputted by this virtual field (not sure it is the correct terminology) are 1,2 or 3 (integer)

Here is the simplified code

1-Declare the virtual field in `hook_views_data_alter()`

```
function mymodule_views_data_alter(array &$data) {
  $data['node']['internal_status'] = [
    'title' => t('Internal Status'),
    'field' => [
      'title' => t('Internal Status'),
      'help' => t("Display internal status"),
      'id' => 'internal_status',
    ],
  ];
}

```

2- Create the view plugin

```
/**
 * Field handler to display internal status.
 *
 * @ViewsField("internal_status")
 */
class NodeInternalStatus extends FieldPluginBase {

  public function query() {}

  public function render(ResultRow $values) {
    $node = $values->_entity;
    $value= return_1_2_or_3_depending_on_dyn_data_like_the_current_date($node);
    switch ($value){
      case 1:
        return t('This is 1');
      case 2:
        return t('This is 2');
      case 3:
        return t('This is 3');
    }
    //will never go here if everything is ok
    return t('n/a');
  }
}

```

**My Question:** I would like to create a filter plugin to filter nodes according their internal status \[by using `return_1_2_or_3_depending_on_dyn_data_like_the_current_date($node)`\]

I have tried to extend the `inOperator` class but as the real column of the "internal status" field doesn't exists in the DB, I keep getting the following error:

```
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'node_field_data.internal_status' in 'where clause':

```

# Answer
After some digging I will answer myself to this question: it is not possible to create a filter on a non existent DB column.

**How to solve this issue:**

In my example, the values of this non existent column are calculated via the function `return_1_2_or_3_depending_on_dyn_data_like_the_current_date($node)`.

We couldn't use this function to create the filter. Instead, for each value returned by the function (in my case 1,2 or 3), we have to write a query with the same logic used in the "dropped" function.

All the logic must reside in the `query` method of the filter plugin.

Here is an example:

1- Add the filter in hook\_views\_data\_alter

```
function mymodule_views_data_alter(array &$data) {
  $data['node_field_data']['internal_status_filter'] = [
    'title' => t('Filter by Internal Status'),
    'filter' => [
      'title' => t('Filter by Internal Status'),
      'help' => t('Bla bla'),
      'id' => 'internal_status_filter',
    ],
  ];
}

```

2-Create the filter plugin (In my case, I have extended the `inOperator` Class)

```
/**
 * Filters the internal status of a node
 *
 * @ingroup views_filter_handlers
 *
 * @ViewsFilter("internal_status_filter")
 */
class InternalStatus extends InOperator {

  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
    parent::init($view, $display, $options);
    $this->valueTitle = t('Available Status');
    $this->definition['options callback'] = array($this, 'generateOptions');
  }

  public function query() {
    $configuration = [
      'left_table' => 'node_field_data',
      'left_field' => 'nid',
      'field'      => 'entity_id',
      'type'       => 'LEFT',
      'extra_operator'   => 'AND',
    ];
    if (
    $selected_status = $this->value[0];
    if ($this->operator == 'in') {
      $this->ensureMyTable();
      switch ($selected_status) {
        case (1):
          //Add a condition on another field
          $table_field='node__field_another_field';
          $configuration['table']=$table_field;
          $join = Views::pluginManager('join')->createInstance('standard', $configuration);
          $this->query->addRelationship($table_field, $join, 'node_field_data');
          $this->query->addWhere('AND', "${table_field}.field_simulation_is_past_value", 1, '=');
          //Add as many condition to get what you need
          break;
          ....
       }
     }
  }

  public function generateOptions() {
    return [
      1=>'Status 1',
      2=>'Status 2',
      3=>'Status 3',
    ];
  }

```

Make sure that your annotation at the top of the file `@ViewsFilter("internal_status_filter")` is the same id than the ones defined in `hook_views_data_alter`
> 1 votes

---
Tags: views, plugins
---


# Question
Title: Trying to configure parent link and child links in menu
I'm trying to create a submenu in the same way shown in the screenshot

module.links.menu.yml:

```
custom_forms_entity_export_csv.export:
  title: 'Export'
  description: 'Export Menu'
  route_name: custom_forms_entity_export_csv.export
  parent: commerce.admin_commerce

custom_forms_entity_export_csv.export_sales_form:
  title: 'Export Sales'
  description: 'Export Sales to a CSV file.'
  route_name: custom_forms_entity_export_csv.export_sales_form
  parent: commerce.admin_commerce

custom_forms_entity_export_csv.export_menu_form:
  title: 'Export Menu'
  description: 'Export Menu to a CSV file.'
  route_name: custom_forms_entity_export_csv.export_menu_form
  parent: custom_forms_entity_export_csv.export

```

module.routing.yml

```
custom_forms_entity_export_csv.export:
  path: '/admin/commerce/export'
  defaults:
    _controller: '\Drupal\system\Controller\SystemController::systemAdminMenuBlockPage'
    _title: 'Commerce'
  requirements:
    _permission: 'access commerce administration pages'

custom_forms_entity_export_csv.export_sales_form:
  path: '/admin/commerce/export/sales'
  defaults:
    _title: 'Sales'
    _form: \Drupal\custom_forms_entity_export_csv\Form\SalesExportCsvForm
  requirements:
    _permission: 'use custom export csv'

custom_forms_entity_export_csv.export_menu_form:
  path: '/admin/commerce/export/menu'
  defaults:
    _title: 'Menu'
    _form: \Drupal\custom_forms_entity_export_csv\Form\MenuExportCsvForm
  requirements:
    _permission: 'use custom export csv'

```

module.links.task.yml

```
custom_forms_entity_export_csv.export_sales_form:
  title: 'Download Sales'
  base_route: custom_forms_entity_export_csv.export
  route_name: custom_forms_entity_export_csv.export_sales_form
  weight: 100

custom_forms_entity_export_csv.export_menu_form:
  title: 'Download Menu'
  base_route: custom_forms_entity_export_csv.export
  route_name: custom_forms_entity_export_csv.export_menu_form
  weight: 100

```

But all I end up with is all three links, Export, Export Sales, and Export Menu as children under the same Commerce menu, like shown here:

What I want is for Export to have an arrow on the right to expand a submenu containing Export Sales and Export Menu.

# Answer
> 2 votes
Your 2nd menu link needs the `parent` property referencing your first `custom_forms_entity_export_csv.export` route :

```
custom_forms_entity_export_csv.export_sales_form:
  title: 'Export Sales'
  description: 'Export Sales to a CSV file.'
  route_name: custom_forms_entity_export_csv.export_sales_form
  parent: custom_forms_entity_export_csv.export

```

---
Tags: 8
---


# Question
Title: How do I override an exposed filter input type?
I'm writing a module to change input HTML attributes with the next code:

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

/**
 * Implements hook_form_alter().
 */
function custom_numeric_filter_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $field = 'yourfieldname';
  if ($form_id == 'views_exposed_form' && array_key_exists($field, $form)) {
    $form[$field]['#type'] = "range";
    $form[$field]['#step'] = 5;
    $form[$field]['#size'] = 5;
    $form[$field]['#min'] = 10;
    $form[$field]['#max'] = 60;
  }
}

```

The problem is that the type gets overwritten back to `number` by something else.

~~I have Better Exposed Filters installed, maybe it gets rewritten there but why? And how can I make sure my module code has priority?~~ With the help from NoSssweat I made sure it was executed after BEF and it didn't help.

# Answer
> 1 votes
Try in this way:

```
function seven_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  if (in_array($form_id, ['node_page_form', 'node_page_edit_form'])) {
    $form['field_number']['widget'][0]['value']['#type'] = 'range';
  }
}

```

I think this post will help you, check once - https://www.drupal.org/project/drupal/issues/2958499#comment-12558959

---
Tags: 8, views
---


# Question
Title: How do I pass dynamic parameters to a service?
Is it possible to pass dynamic parameters when calling a service?

### mymodule.services.yml

```
services:
  my_module.default:
    class: Drupal\services\DefaultService
    arguments: ['@entity_type.manager']

```

### DefaultService.php

```
namespace Drupal\my_module;
use Drupal\Core\Entity\EntityTypeManagerInterface;

/**
 * Class DefaultService.
 */
class DefaultService implements DefaultServiceInterface {

  /**
   * Drupal\Core\Entity\EntityTypeManagerInterface definition.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected $entityTypeManager;

  private $myValue;

  /**
   * Constructs a new DefaultService object.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;

    //how set $myValue?
    // $this->myValue = ???
  }

}

```

Is there a way to dynamically set `myValue` when calling this service, for example while calling the service from `hook_ENTITY_TYPE_update()`, passing the `$entity->id()` value?

I've found similar questions, such as How do I pass parameters to a service? or Create service with argument, but they don't answer my problem.

# Answer
> 3 votes
Giuseppe, I recommend defining your service using the Factory design pattern. You can then instance the factory and call a copy of your business logic class, initialized with the nid. I believe that this pattern is what @kiamlaluno was hinting at in his comment about using DatabaseBackendFactory.

## Factory injection example

A simple and common example of this pattern would be getting an instance of a storage controller from the EntityTypeManager.

In your .services.yml file:

```
example_service:
  class: Drupal\my_module\MyExampleClass
  arguments: ['@entity_type.manager']

```

In your service class:

```
<?php

use Drupal\Core\Entity\EntityTypeManagerInterface;

class MyExampleClass {

  /**
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  protected $termStorage;

  /**
   * @inheritDoc
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->termStorage = $entity_type_manager->getStorage('taxonomy_term');
  }
}

```

In the example above, the EntityTypeManager, which acts as a factory, has been injected, and then we call the `getStorage()` method to get an instance of `\Drupal\Core\Entity\EntityStorageInterface` that has been initialized for the **taxonomy\_term** entity type.

Similarly, you could define a service that is, itself, a factory, and the factory would then be responsible for creating instances of your business logic class.

You could inject your factory service, as in the example above, by replacing the EntityTypeManager service with your own. You can also create an instance in a hook, like this:

```
my_module_node_view($node, $view_mode, $langcode) {
  // Get instance of your factory service.
  $my_service = \Drupal::service('my_service');
  // Get an instance of your business logic class from the factory,
  // initialized to use the nid that we provided from $node->id().
  $node_processor = $my_service->get($node->id());
  // Make the call to process the nid.
  $node_process->doBusinessLogic();
}

```

# Plugins

It might also be helpful to know about Drupal 8's plugin system. Drupal 8's plugin system is essentially a specialized version of the factory pattern. If you have Drupal Console, then generating new Annotation plugins is easy. Depending on all of the requirements of your project, a custom plugin type might be exactly what you need.

Here are some tutorials and references on plugins that I have found to be useful:

# Answer
> 3 votes
Like @4k4 said you could approach it like this:

```
namespace Drupal\my_module;

use Drupal\Core\Entity\EntityTypeManagerInterface;

/**
 * Class DefaultService.
 */
class DefaultService implements DefaultServiceInterface {

  ...

  private $myValue;

  /**
   * Constructs a new DefaultService object.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager) {
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * Setter method.
   */
  public function setMyValue($value) {
    $this->myValue = $value;
    return $this;
  }

}

```

And then you can call it like:

```
/** @var \Drupal\my_module\DefaultServiceInterface $my_service */
$my_service = \Drupal::service('my_module.default');
$my_service->setMyValue($your_dynamic_value);

// Do more stuff.

```

---
Tags: 8, symfony-services
---


# Question
Title: <nolink> top items rendered as <a> and remain clickable (give page refresh)
I have a TB megamenu (8.x-1.x-dev) with a few top-level (parent) items that are not links, they should just trigger the submenu to drop down.

According to the documentation I could find, links marked as `<nolink>` or `route:nolink` will be rendered as `<span>` rather than `<a>` so styling can be retained, but they can't clicked, and submenus should still be toggled.

However, both `<nolink>` and `route:nolink` are still rendered as `<a>`, causing a page refresh when clicked.

I have tried adding the `nolink` definition as a special menu item under (A) admin/structure/menu/manage/main-menu, and in (B) the tb mega menu settings at admin/structure/tb-megamenu/main-menu, but nothing helps:

* When adding \`nolink\` to the Drupal menu link (A), it leaves the link empty, but you get the page refresh when you click it. Submenu does unfold.
* When adding \`nolink\` to the TB Megamenu link (B), it leaves the link empty, no page refresh as it now activates a css class that says \`.nolink {pointer-events:none;}\`, but button goes dead, and submenu does NOT unfold.

When on mobile, all menu items with children do unfold the submenu, don't trigger a page refresh; it's that behaviour I'd love to be able to have in desktop/laptop view too. (Even better if there is a switch "active link yes/no" or similar, so I can decide per button?)

Any help much appreciated :)

# Answer
> 1 votes
How are you getting those to save?

It should be `route:<nolink>`. Test that it works on a regular menu before trying the additional module to avoid confusion about what might be happening.

---
Tags: navigation
---


# Question
Title: How to allow access to page variant (Page Manager) if user belongs to list
## The Situation

I have an ECK entity called "Event" in my Drupal 7 site.
I have an entity reference field on Event that collects users who flag the Event with a non-global flag called "Sign up" via a rule.
I use Page Manager to control how an Event entity is shown to the users.

My context:
**Edit relationship "User from Event (on Event: List of attendees \[field\_attendees\]"**
`Event: Entity being viewed`
`Identifier: User from Event Attendees [field_attendees])`
`Keyword: event_attendees`
`Delta: 0`

Here is the Selection Rule:
`User: compare logged_in_user is User from Event Attendees [field_attendees]`

## The Problem

As you can see, one of my Page Variants has a selection rule that checks if the logged\_in\_user is on the list of attendees but it doesn't work because the selection rule takes a "delta" and that means that it takes a ***hard coded*** integer to select one of the list. And if I leave this empty, it automatically takes "0" i.e. the first one in the list. There seems to be no option to set the delta to include all or any.

## The Question

How can I create this selection rule to check if this user is 'on the list'?

# Answer
> 0 votes
Currently I'm using a selection rule that checks if the logged-in user has "flagged" the Event with a Signup. This works but checking if the logged-in user is on the list would be a waterproof solution.

---
Tags: 7, chaos-tool-suite
---


title: Hide path on frontpage redirect

text:
# Question
Title: Hide path on frontpage redirect
In a custom module i'm using an `EventSubscriber` to redirect different people to different frontpages. Below is the simplified code I'm using.

```
//GET PATH
$nid = 1;
$domain_url = \Drupal::service('path_alias.manager')->getAliasByPath('/node/'. $nid);

//FRONTPAGE REDIRECT
$response = new RedirectResponse($domain_url);
$event->setResponse($response);

```

The module is working but there is one detail I can't seem to solve.

For example on my website `domain.com` I have `node/1` that has an alias path `/home`.

When going to `domain.com` it is, because of my module as expected, redirected to `domain.com/home`. But what I want is the url not to show the `home` part. Is it possible to show the content of `/home` but keeping the url `domain.com`?

# Answer
> 0 votes
You can add the path to your homepage from admin/config/system/site-information

And replace /node/1 to /home.

You don't need an even subscriber to do that.

---
Tags: 9, event-subscribers
---


# Question
Title: How to check if dynamic select query returns zero records and return markup
I have a custom Drupal form that is populated with a dynamic query. How do I return an 'alert' if no results are returned? There has to be a better way of doing this than what I have come up with.

This is what I have so far and it throws an error when a record is returned because it continues processing the actual form.

Query:

```
public function loadByPID($pid = null) {
  $database = \Drupal\Core\Database\Database::getConnection('default', 'newDB');
  $query = $database->select ('Person');
  $query->condition('personid', $pid);
  $query->fields('Person', ['col1', 'col2', 'col3']);
  $results = $query->execute();
  return $results;
}

```

Call to query:

```
$results = $this->repository->loadByPID($pid);

```

The form and my attempt to check if there are zero records returned.

```
$rowCount = 0;
foreach ($results as $record) {
    $rowCount++;
}
if ($rowCount == 0) {
  // alert if no values
  $form['no_values'] = [
    '#markup' => $this->t('No entries exist.'),
    '#prefix' => '<div class="alert alert-warning my-5" role="alert">',
    '#suffix' => '</div>',
  ];
  return $form;
}else{
  // the actual form
  $form[]...
  $content['row']['fname'] = [
    '#markup' => $this->t($fname),
    '#prefix' => '<div class="col-md-11">',
    '#suffix' => '</div>',
  ];
  ...
  return $form;
};

```

Edit: The error I get is because it seems to keep processing the page and it's looking for a variable that is in the else{} form.

```
Undefined variable: fname in Drupal\myModule\Controller\DbtngExampleController->entryView() (line 186 of modules/custom/myModule/src/Controller/DbtngExampleController.php).

```

# Answer
You could try emitting a warning via the messenger service like:

```
if ($rowCount == 0) {
  // Alert if no values.
  \Drupal::messenger()->addWarning($this->t('No entries exist.'));
}

```

And then you can just discard `form['no_values']`.

**UPDATE:**

For the additional error that you are facing, you appear to not have the `$fname` variable defined in your `else` clause. Try declaring it outside the if else statement ie. `$fname = '';` or similar. It is not clear to me what the use is of that variable or which value it should contain.
> 1 votes

---
Tags: forms
---


# Question
Title: How to uninstall pdf_reader module without error? "The 'core' or the 'core_version_requirement' key must be present"
In summary: I cannot uninstall pdf\_reader sucessfully without bringing down my site with this error:

```
Drupal\Core\Extension\InfoParserException: The 'core' or the 'core_version_requirement' key must be present in modules/contrib/pdf_reader/pdf_reader.info.yml in Drupal\Core\Extension\InfoParserDynamic->parse() (line 73 of core/lib/Drupal/Core/Extension/InfoParserDynamic.php).

```

( I did search the above error but cannot see anything related).

Have a Drupal 8.9.8 dev site using Composer 1.10.7 (I did try and update to composer 2 but that caused a lot of other errors, which I wanted to save for another day!)

I had pdf\_reader installed and wanted to uninstall it.

Used composer to uninstall it:

```
drush pmu pdf_reader

```

This completes to success.

I then rebuild the cache with:

```
drush cache-rebuild

```

However I noticed in composer.json, there is still an entry:

```
"drupal/pdf_reader": "1.x-dev",

```

if I login to drupal and check the installed modules pages I can see it and it's unticked.

At this point if I try and reinstall it using the UI I get the message: *PDF Reader is already installed.*

If I look in the following directory, I can see the pdf\_reader folder still exists /web/modules/contrib/

If I now delete the above folder and clear the cache, it stops the website running with:

The website encountered an unexpected error. Please try again later.

```
Drupal\Core\Extension\InfoParserException: The 'core' or the 'core_version_requirement' key must be present in modules/contrib/pdf_reader/pdf_reader.info.yml in Drupal\Core\Extension\InfoParserDynamic->parse() (line 73 of core/lib/Drupal/Core/Extension/InfoParserDynamic.php).

```

At this point if I run:

```
drush cache-rebuild

```

I get a similar error:

```
In ExtensionDiscovery.php line 446:

  SplFileInfo::openFile(/var/www/html/web/modules/contrib/pdf_reader/pdf_read
  er.info.yml): failed to open stream: No such file or directory

```

(if I restore the pdf\_reader folder and clear the cache the sites come back online).

So it seems like something is out of synch and/or not updating, any help appreciated (I'm far from a drupal expert, so I'm sure it's something simple for an expert))

My Composer.json file:

```
{
    "name": "drupal/recommended-project",
    "description": "Project template for Drupal 8 projects with a relocated document root",
    "type": "project",
    "license": "GPL-2.0-or-later",
    "homepage": "https://www.drupal.org/project/drupal",
    "support": {
        "docs": "https://www.drupal.org/docs/user_guide/en/index.html",
        "chat": "https://www.drupal.org/node/314178"
    },
    "repositories": [
        {
            "type": "composer",
            "url": "https://packages.drupal.org/8"
        }
    ],
    "require": {
        "composer/installers": "^1.2",
        "drupal/admin_toolbar": "^2.3",
        "drupal/astrology": "^1.4",
        "drupal/bootstrap_barrio": "^5.1",
        "drupal/coffee": "^1.0",
        "drupal/copyright_footer": "^1.7",
        "drupal/core-composer-scaffold": "^8.8",
        "drupal/core-project-message": "^8.8",
        "drupal/core-recommended": "^8.8",
        "drupal/devel": "^4.0",
        "drupal/entity_delete": "^1.6",
        "drupal/fb_likebox": "^2.1",
        "drupal/feeds": "^3.0@alpha",
        "drupal/feeds_tamper": "^2.0@beta",
        "drupal/flexslider_fields": "^2.0",
        "drupal/fontawesome": "^2.17",
        "drupal/gdoc_field": "^1.1",
        "drupal/migrate_plus": "^5.1",
        "drupal/migrate_tools": "^5.0",
        "drupal/migrate_upgrade": "^3.2",
        "drupal/paragraphs": "^1.12",
        "drupal/pathauto": "^1.8",
        "drupal/pdf": "^1.0",
        "drupal/pdf_reader": "1.x-dev",
        "drupal/superfish": "^1.4",
        "drupal/tablefield": "^2.1",
        "drush/drush": "^10.3"
    },
    "conflict": {
        "drupal/drupal": "*"
    },
    "minimum-stability": "dev",
    "prefer-stable": true,
    "config": {
        "sort-packages": true
    },
    "extra": {
        "drupal-scaffold": {
            "locations": {
                "web-root": "web/"
            }
        },
        "installer-paths": {
            "web/core": [
                "type:drupal-core"
            ],
            "web/libraries/{$name}": [
                "type:drupal-library"
            ],
            "web/modules/contrib/{$name}": [
                "type:drupal-module"
            ],
            "web/profiles/contrib/{$name}": [
                "type:drupal-profile"
            ],
            "web/themes/contrib/{$name}": [
                "type:drupal-theme"
            ],
            "drush/Commands/contrib/{$name}": [
                "type:drupal-drush"
            ],
            "web/modules/custom/{$name}": [
                "type:drupal-custom-module"
            ],
            "web/themes/custom/{$name}": [
                "type:drupal-custom-theme"
            ]
        },
        "drupal-core-project-message": {
            "include-keys": [
                "homepage",
                "support"
            ],
            "post-create-project-cmd-message": [
                "<bg=blue;fg=white>                                                         </>",
                "<bg=blue;fg=white>  Congratulations, you’ve installed the Drupal codebase  </>",
                "<bg=blue;fg=white>  from the drupal/recommended-project template!          </>",
                "<bg=blue;fg=white>                                                         </>",
                "",
                "<bg=yellow;fg=black>Next steps</>:",
                "  * Install the site: https://www.drupal.org/docs/8/install",
                "  * Read the user guide: https://www.drupal.org/docs/user_guide/en/index.html",
                "  * Get support: https://www.drupal.org/support",
                "  * Get involved with the Drupal community:",
                "      https://www.drupal.org/getting-involved",
                "  * Remove the plugin that prints this message:",
                "      composer remove drupal/core-project-message"
            ]
        }
    }
}

```

# Answer
After a lot of messing around, (such as installing random modules and trying to uninstall them) I figured the problems wasn't directly related to drupal. I'm using a container and ddev. Once I restarted the ddev enviroment everything worked (turn it off and on again), que the face plant.
> 1 votes

---
Tags: 8, composer
---


# Question
Title: How to output plain URL to the node in Views?
I would like to output plain absolute URL of the node from Views as part of my XML feed (via Views Datasource).

So far I have found the following field handler:

> Content: Link - Provide a simple link to the content.

which is provided by Views it-self, but checking `views_handler_field_node_link.inc` file doesn't seems to support displaying plain text (and there are no any field formatters, as it's field specific), but instead I've got:

```
<a href="http://localhost/node/123">view</a>

```

without possibility to change the format (apart of the text it-self).

Is there any other way to display just plain URL of the node using Views field handler (without having actual field)?

# Answer
> 9 votes
*Content: Path* works with Drupal 7. Select *Use absolute link (begins with "http://")* in *Rewrite results* section of the field settings.

>

# Answer
> 4 votes
Instead of Content: Link, use the **Content: Path** field.

# Answer
> 0 votes
Just noting for Drupal 8. In more recent versions of Drupal 8 (e.g 8.8), you can use Content \> Link to Content:

> Output the URL as text

---
Tags: 7, views
---


# Question
Title: How to use "IS NULL" and "IS NOT NULL" Operators in JSON API Collections?
I am creating an API with Conditions and Operators. For `'='` and `'<>'` operators its working fine. But for `"IS NULL"` and `"IS NOT NULL"` operators the response is 400: Bad Request.

```
{{URL}}/jsonapi/node/CONTENT_TYPE?filter[filter1][condition][path]=TAXONOMY_FIELD.drupal_internal__tid&filter[filter1][condition][value]={{TID}}&filter[filter1][condition][operator]=IS NULL

```

**Request:**

**Response:** The error says: `Filters using the 'IS NULL' operator should not provide a value.`

Should the operators be encoded ? If yes, then which encoding should be used and what is the encoded string for these operators ?

# Answer
You don't need this line, because value is supposed to be null

```
&filter[filter1][condition][value]={{TID}}

```
> 0 votes

---
Tags: 8
---


# Question
Title: With Commerce Product taxonomy term view, is there a way to have page title set to the translated term title?
The only way to have the taxonomy term name in the title of a taxonomy term Commerce Products view page I've found so far is the example view in the estore theme (I still don't get how tid which should stand for Term ID becomes the title field value):

The problem is that the title shown is not translated on multilingual sites when the term definitely has a proper translation. Is there any way to show that title translated?

For some reason there are no `Product: Has taxonomy term ID` as there is `Content: Has taxonomy term ID` in the default taxonomy term view that is displaying the title translated.

AFAIU `{{ arguments.tid|t }}` is not the way because it will go through a different subsystem.

# Answer
> 0 votes
I had to workaround it in code by modifying an example posted by djg\_tram:

```
/**
 * @file
 * Workaround for taxonomy term title not being i18zed.
 */
use Drupal\views\ViewExecutable;
use Drupal\taxonomy\Entity\Term;

/**
 * Implements hook_views_pre_render().
 */
function exposed_filter_workaround_views_pre_render(ViewExecutable $view) {
  $view_id = 'products';
  $view_display = 'page_category';

  if ($view->id() == $view_id && $view->current_display == $view_display) {
    $lang_id = \Drupal::languageManager()->getCurrentLanguage()->getId();

    $term_id = $view->args[0];
    $term = Term::load($term_id);

    $term_translated = $term->getTranslation($lang_id);
    $view->setTitle($term_translated->label());
  }
}

```

---
Tags: 8, views, commerce, taxonomy-terms, i18n-l10n
---


# Question
Title: How I can alter reCAPTCHA script tag in html_head
The reCaptcha module adds a Javascript with hook\_captcha(). I want to add another attribute "type" to this script tag. I can't find a hook to achieve this.

Here is the code from the recaptcha.module (line 118):

```
$captcha['form']['recaptcha_widget'] = [
        '#markup' => '<div' . new Attribute($attributes) . '></div>',
        '#suffix' => $noscript,
        '#attached' => [
          'html_head' => [
            [
              [
                '#tag' => 'script',
                '#attributes' => [
                  'src' => Url::fromUri($recaptcha_src, ['query' => ['hl' => \Drupal::service('language_manager')->getCurrentLanguage()->getId()], 'absolute' => TRUE])->toString(),
                  'async' => TRUE,
                  'defer' => TRUE,
                ],
              ],
              'recaptcha_api',
            ],
          ],
        ],
      ];

```

When I try to access the script tag with e.g. hook\_page\_attachments\_alter() or any other hook\_preprocess\_xxxx() it is missing. I also tried to increase my module weight.

# Answer
> 2 votes
I would suggest using a #process callback and avoid code duplication. This is what such a solution could look like:

```
/**
 * Implements hook_element_info_alter().
 */
function my_module_element_info_alter(array &$element) {
  if (isset($element['captcha'])) {
    $element['captcha']['#process'][] = '_custom_recaptcha_process';
  }
}

/**
 * Add type attribute to recaptcha form element.
 *
 * @return array
 *   The processed element.
 *
 * @see captcha_element_info()
 * @see image_captcha_element_info_alter()
 */
function _custom_recaptcha_process($element) {
  $recatchaWidgetHtmlHead = &$element['captcha_widgets']['recaptcha_widget']['#attached']['html_head'] ?? [];
  array_walk($recatchaWidgetHtmlHead, function(&$captcha_widget) {
    if ($captcha_widget[1] === 'recaptcha_api') {
      $captcha_widget[0]['#attributes']['type'] = 'value';
    }
  });
  return $element;
}

```

and this would be the output:

Good luck!

# Answer
> 0 votes
Since hook\_captcha() is a hook, you can override it by implementing it in your own custom module.

As long as your module has higher weight, it will run after recaptcha\_captcha.

So basically copy all the code in recaptcha\_captcha and rename the function name to `mymodule_captcha` and add the `type` to the `#attributes` array and you're golden.

---

In this rare case, the only way appears to be patching the module directly.

Hopefully you're using a composer managed site and all you have to do is create a patch and have composer auto apply it for you.

---
Tags: javascript, hooks, captcha
---


# Question
Title: Why isn't a PDO driver detected on the install page?
I have an old Drupal 7 project and I need to set it up on my localhost. I have Ubuntu 16.04, Apache 2, php 7.0, and MySQL 5.7 installed. Everything is working fine for other PHP scripts, But when I tried to install Drupal 7 project, I got this error.

> Your web server does not appear to support any common PDO database extensions. Check with your hosting provider to see if they support PDO (PHP Data Objects) and offer any databases that Drupal supports.

I could not figure it out why Drupal doesn't detect PDO. How can I fix this issue?

# Answer
The error could be thrown for three different reasons.

* Some of the Drupal core files in the includes/database directory are missing
* There isn't any extension implementing the necessary PDO drivers
* The extension implementing the necessary PDO driver isn't enabled in the php.ini file or other .ini files used from PHP

To check which database driver is available, Drupal first looks for its own files in the *includes/database* directory, initializes an instance of a class that extends `DatabaseTasks` (for example `DatabaseTasks_mysql` for MySQL) and calls its `installable()` method.

```
public function installable() {
  return $this->hasPdoDriver() && empty($this->error);
}

protected function hasPdoDriver() {
  return in_array($this->pdoDriver, PDO::getAvailableDrivers());
}

```

If the method returns `FALSE`, the PDO driver is considered not available. (See `drupal_get_database_types()` for details.)

Notice that, if the PDO extension (not a PDO driver) isn't available, the error shown from Drupal is the following one.

> 'Your web server does not appear to support PDO (PHP Data Objects). Ask your hosting provider if they support the native PDO extension.

In that case, Drupal would also show the following message, followed by a list of one or more missing PHP extensions.

> Drupal requires you to enable the PHP extensions in the following list (see the system requirements page for more information)
> 1 votes

---
Tags: 7, database, installation
---


title: Views & JSON API

text:
# Question
Title: Views & JSON API
I can see Drupal 8 Views support REST Export.

But not JSON API.

So how to integrate Views with JSON API?

https://www.drupal.org/project/jsonapi

# Answer
> 2 votes
If you want to display the structure of the view as JSON API output you need to get the UUID of the view and then pass it to the json api For example as given below.

http://yoursite/jsonapi/view/view/889120bb-98f2-43be-8ca3-d93d1cd15590

To get the UUID of the view you need to go http://yoursite/jsonapi and scroll to the View portion of the output and then go to the links block. That will list all the views in the site with their UUIDs.

# Answer
> 1 votes
Just enable RESTful Web Services and provide REST export in your view.

# Answer
> 0 votes
`/jsonapi/view/view` will give you a comprehensive list of all the views.

The data:attributes:drupal\_internal\__id and data:attributes:label nodes will tell you which view you are looking at in the list.

---
Tags: views, 8
---


# Question
Title: How can a description be added to the body field summary widget in node edit form?
On a particular content type I have made summary input required by checking both "Summary Input" and "Summary required" on the body field settings.

We would like to add a help text to the summary field on the resulting form. I have tried using `hook_form_BASE_FORM_ID_alter` as seen below which is working for the title field.

```
$title_description = 'Why we need a title.';
$title_widget =& $form['title']['widget'];
if (empty($title_widget[0]['value']['#description'])) {
  $title_widget[0]['value']['#description'] = $title_description;
}

```

I am having a hard time finding the summary in the $form array however.

To recap how can I alter this widget to add a description?

# Answer
I assume you're using Drupal 8.

Try the below in your hook alter. This also assumes the usage of the default `body` field in use:

```
use Drupal\Core\StringTranslation\TranslatableMarkup;

// Ensure summary field existence.
if (isset($form['body']['widget'][0]['summary'])) {
  $form['body']['widget'][0]['summary']['#description'] = new TranslatableMarkup('Your summary description goes here.');
}

```
> 3 votes

---
Tags: 8, forms
---


# Question
Title: How can i debug why files are not being created when using migrate files to media module?
I run the drush migrate-duplicate-file-detection migd8\_grants\_media\_step1 successfully, and then run the node migration and step 1, however the media is being populated with the name only, the file is not attached nor are the files being moved over to the sites default/files/grants directory as they should Steps to reproduce

this is my step 1 yml.

```
# File to Media Migration configuration for grants Media migration

id: migd8_grants_media_step1
label: Grants Media Step 1
migration_group: cncs
source:
  key: migrate
  plugin: media_entity_generator_d7
  entity_type: node
  bundle: grants
  langcode: und
  d7_file_url: 'https://www.externalwebsite/sites/default/files/'
  field_names:
  - field_files

destination:
  plugin: entity:media

process:

  bundle:
    plugin: default_value
    default_value: document

# Using the alt tag if available, else the file name.
  name:
    plugin: media_name
    source: file_name

# This process plugin will skip the whole row if a existing media is found.
  existing_media_file:
    plugin: check_media_duplicate
    source: target_id

# This process plugin will skip the whole row if a duplicate document is found.
  unique_file_id:
    plugin: check_duplicate
    source: target_id

# Map the field
field_media_document/target_id: target_id
field_media_document/target_id:
  plugin: media_file_copy
  move: FALSE
  reuse: TRUE
  path: 'public://grants/'
  source: file_path

langcode: und

uid:
  plugin: default_value
  default_value: 1

```

# Answer
> 0 votes
the answer was that i had to put the nid in the import so the nid was the same in the source and target content in order for this to work.

# Answer
> 1 votes
You have an an error in your yml file, should be:

```
# Map the field
field_media_image/title: title
field_media_image/target_id:
    plugin: media_file_copy
    move: FALSE
    reuse: TRUE
    path: 'public://grants/'
    source: file_path

langcode: langcode

```

---
Tags: migrations
---


# Question
Title: Condition in variation product template is not triggered correctly (ajax caching ?)
I have a commerce project with a specific product type using an attribute to generate variation.

Variation product has two specific fields that I want to hide switch attribute.

I implemented hook\_preprocess\_commerce\_product to check this. In my hook, I check for a variation in POST (purchased\_entity) or GET (v=xyz). If no one is found, I retrieve the default variation and set into the $variables array a new value called "is\_custom\_variation". This value is set to TRUE when the variation is a "custom" one. Only one variation in a product can be a custom variation, other are standard variations.

The "add to cart" form use a "select" form element to (ajax) switch between variations.

In the product template (commerce-product--full.html.twig) I added the following code :

```
<article{{ attributes }}>
{% if is_custom_variation %}
  {{- product|without('variation_attributes', 'variation_field_1', 'variation_field_2') -}}
{% else %}
  {{- product|without('variation_attributes') -}}
{% endif %}
</article>

```

Strange thing appears when I test the code :

* I load the product page with the default variation as "custom" variation : field 1 and field 2 are hidden. When I switch to another "non-custom" variation, fields are hidden too.
* I load the product page with a "non-custom" variation : field 1 and field 2 are displayed. When I switch to the "custom" variation, fields are displayed too.

By enabling xdebug, I see that each time the template is called, the variable "is\_custom\_variation" is correctly set (TRUE on custom variation, FALSE otherwise)

Maybe anyone can point me what is wrong on my implementation... I don't know why the template is using always the same process after the first display. Is it related to ajax reload of the variation ?

Thanks in advance for any suggestion.

# Answer
If you have other input data(url, query params, timestamp, cookie, etc) than $variables in your HOOK\_preprocess you have to update your cache rules otherwise first time you get trough that hook will get cached for the rest of iterations of same $variables input.

In your case I suggest using cache context or cache tags where they change based on POST and GET variables.

https://www.drupal.org/docs/8/api/render-api/cacheability-of-render-arrays
> 0 votes

---
Tags: commerce
---


# Question
Title: Group an aggregated view by date without time
I would like to create a view that uses aggregation on an entity to display the count and the sum by date. But it should be grouped by date only without time even the original date value has time values. I.e.

Entity: processedTime | amount | value | ... 01/01/2017 08:00:00 | 10 | 1 | ... 01/01/2017 08:18:10 | 10 | 1 | ... 01/01/2017 10:00:00 | 10 | 1 | ... 01/02/2017 08:00:00 | 10 | 1 | ... 01/02/2017 09:30:00 | 10 | 1 | ... ...

the view should output 01/01/2017 | 30 | 3 | ... 01/02/2017 | 20 | 2 | ...

If I create a view with aggregation grouped by the date field, the view also evaluates the time and tries to group by the entire value of the date field. How can I group only by year, month and day without time?

# Answer
> 0 votes
Add a field to the view for the date field you want to group by. In the filter config, set the date format to whatever level of granularity you want for the filter (in the image, it's by month), and tick *exclude from display*. Then you can group by this field.

# Answer
> 0 votes
I was able to aggregate by year with a date field with a Year only format (Y) and AVG as the aggregation method on the field. Grouping was on the NID which was hidden from view.

---
Tags: views, 8, entities
---


# Question
Title: #ajax on a managed_file custom form field is not working
I have a custom Drupal 8 form using a managed\_file field with an #ajax callback but the ajax callback is never called (example below). I assume that it's because the managed file field type is already using ajax. Is there a way that I can implement my own ajax callback within my custom module to fire after the managed file's own ajax completes?

```
 $form['file'] = array(
      '#title' => t('Image File'),
      '#type' => 'managed_file',
      '#required' => TRUE,
      '#upload_location' => 'private://',
      '#multiple' => FALSE,

      '#upload_validators'    => [
        'file_validate_is_image'      => array(),
        'file_validate_extensions'    => array('jpg png psd ai bmp eps jpeg pdf tif tiff'),
        'file_validate_size'          => array(56600000)
      ],

      '#ajax' => [
        'callback' => array($this, 'myAjaxCallback'),
        'event' => 'change',
        'wrapper' =>  'im-area',
        'progress' => array(
          'type' => 'throbber',
          'message' => t('Choose City'),
        ),
      ],
    );

```

# Answer
> 5 votes
I don't think you can attach multiple ajax callbacks to a form element. But you could override the callback by extending the core element:

*/src/Element/MyManagedFile.php*

```
<?php

namespace Drupal\mymodule\Element;

use Drupal\file\Element\ManagedFile;
use Drupal\Core\Ajax\AlertCommand;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * My Managed File Element.
 *
 * @FormElement("my_managed_file")
 */
class MyManagedFile extends ManagedFile {

 /**
 * {@inheritdoc}
 */
 public static function uploadAjaxCallback(&$form, FormStateInterface &$form_state, Request $request) {
    $response = parent::uploadAjaxCallback($form, $form_state, $request);
    $response->addCommand(new AlertCommand('Hello!!!'));
    return $response;
  }

}

```

And then use it in the custom form:

```
 $form['file'] = array(
      '#title' => t('Image File'),
      '#type' => 'my_managed_file',

```

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


title: Add JS to all webform

text:
# Question
Title: Add JS to all webform
I have a Drupal 9 custom theme and would like to attach a JS file on the webform.

Adding JS file in `themename.libraries.yml` does not work.

```
webform:
  js:
    theme:
      js/webform.min.js: {}

```

**What is the right way to attach a JS file to the other module(webform)?**

# Answer
> 2 votes
Adding lines to `themename.libraries.yml` is not enough to add the JS, you just declared a library doing this.

Now if you want to use that library on all your theme pages, you need to add in `themename.info.yml`

```
libraries:
  - themename/webform

```

But if you just need to attach the library to your forms, you can use the hook\_form\_alter, target your webform ids and write `$form['#attached']['library'][] = 'themename/webform';`

---
Tags: javascript, webforms, 9
---


# Question
Title: Term not being migrated into taxonomy reference field
I've got two migrations set up, pulling from two separate JSON feeds.

The first is a feed of taxonomy terms with a tid, vid, and name. I'm able to run migration on this fine and generate the relevant terms on my Drupal 8 test build.

The second JSON feed is one of node articles, that includes a taxonomy reference field, with a name value that matches up with the terms migrated in the previous migration described.

When I run the second migration for nodes, the taxonomy reference field is blank.

I've tried both entity\_generate and migrate\_lookup plugins to no success

```
field_taxonomy_term:
  plugin: migrate_lookup
  migration: migrate_taxonomy_terms_en
  source: tid

```

The JSON file for the taxonomy terms looks like the following:

```
[{
"name":"Term one",
"tid":"1",
"vid":"Vocabulary"
},
{
"name":"Term two",
"tid":"2",
"vid":"Vocabulary","}]

```

The JSON feed for the node migration looks like:

```
   {"title":"Page title","field_taxonomy_term":"Term one"}

```

Does anyone have ideas on what I'm missing?

Thanks!

# Answer
I'm sorry that in 8 months no one has answered this question.

I was stuck on this as well and finally got it to work by using the following format nested under the process key of your migration that will look up the previously migrated taxonomy:

```
field_taxonomy_term:
  plugin: migrate_lookup
  migration: migrate_taxonomy_terms_en
  source: field_taxonomy_term

```

The field\_taxonomy\_term from your node source should be the entity id of the taxonomy term.

Also it should be noted that I migrated the taxonomy vocabulary and the node that will reference the taxonomy as a group. I'm not sure if that matters or not. The order the migrations are executed in is determined by setting the dependency on the taxonomy migration in the node migration.
> 1 votes

---
Tags: migrations
---


# Question
Title: How do I test a CKEditor 4 text format field with Behat/Mink?
I am using an @javascript test in Behat on CircleCI to check my Drupal 8 site.

When I use the standard `I fill in "my field" with "value"` step, it works for fields with the plain text format, but it fails for fields that use CKEditor.

How can I fill in fields on CKEditor?

# Answer
> 2 votes
This doesn't yet have official support in the Drupal Extension. The linked thread has some examples that use traits.

However, I found this gist by johnennewdeeson to be a faster, easier solution for me, just cut and paste into `FeatureContext.php`:

```
  /**
   * @Then I fill in wysiwyg on field :locator with :value
   */
  public function iFillInWysiwygOnFieldWith($locator, $value) {
    $el = $this->getSession()->getPage()->findField($locator);

    if (empty($el)) {
      throw new ExpectationException('Could not find WYSIWYG with locator: ' . $locator, $this->getSession());
    }

    $fieldId = $el->getAttribute('id');

    if (empty($fieldId)) {
      throw new Exception('Could not find an id for field with locator: ' . $locator);
    }

    $this->getSession()
      ->executeScript("CKEDITOR.instances[\"$fieldId\"].setData(\"$value\");");
  }

```

---
Tags: testing, input-formats
---


# Question
Title: Why don't I see the colorbutton plugin in CKEditor?
I installed the Colorbutton module and its composer dependencies:

```
"drupal/colorbutton": "^1",
"drupal-ckeditor-libraries-group/colorbutton": "^4.14",
"drupal-ckeditor-libraries-group/panelbutton": "^4.14",

```

I then enabled the module, configured the **Basic HTML** text form, and added the new buttons to my toolbar.

However, I don't see the buttons as an authenticated user (admin or regular authenticated user).

I rebuilt the Drupal cache, cleared the browser cache... Still the same problem.

How do I display the color buttons?

# Answer
By default, **Basic HTML** strips `<span style>` attributes, which CKEditor uses to apply color.

On `/admin/config/content/formats/manage/basic_html`, if you add `<span style>` to the **Allowed HTML Tags**, the buttons will be displayed.
> 0 votes

---
Tags: input-formats
---


title: Get parent menu item of a current node

text:
# Question
Title: Get parent menu item of a current node
I'm trying to get the parent menu item of node I am currently on:

```
$node_id = // some id
$menu_link_manager = \Drupal::service('plugin.manager.menu.link');
$menu_link = $menu_link_manager->loadLinksByRoute('entity.node.canonical', array('node' => $node_id));
$parent = $menu_link->getParent();

```

but for some reason it always fails with this error:

```
Error: Call to a member function getParent() on array

```

When I inspect `$menu_link` I can clearly see it is there:

Also the method of `getParent()` seems to be correct: Docs

Would appreciate any help!

# Answer
> 3 votes
I think you need to reset the collection first, as the `::loadLinksByRoute()` annotation states that it returns an array of `MenuLinkInterfaces[]`.

See `/core/lib/Drupal/Core/Menu/MenuLinkManagerInterface.php`:

```

  /**
   * Loads multiple plugin instances based on route.
   *
   * @param string $route_name
   *   The route name.
   * @param array $route_parameters
   *   (optional) The route parameters. Defaults to an empty array.
   * @param string $menu_name
   *   (optional) Restricts the found links to just those in the named menu.
   *
   * @return \Drupal\Core\Menu\MenuLinkInterface[]
   *   An array of instances keyed by plugin ID.
   */
  public function loadLinksByRoute($route_name, array $route_parameters = [], $menu_name = NULL);

```

So do something like:

```
/** @var \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager */
$menu_link_manager = \Drupal::service('plugin.manager.menu.link');
$menu_links = $menu_link_manager->loadLinksByRoute('entity.node.canonical', array('node' => $node_id));
// Reset collection by retrieving the first item.
$menu_link = reset($menu_links);
// Now call the parent method.
$parent = $menu_link->getParent();

```

---
Tags: 8
---


# Question
Title: Custom placeholder markup when leveraging #lazy_builder in elements
Using bigpipe.

To avoid blocking page loads for long-lasting API calls, etc, I implement:

```
$element = [
  '#lazy_builder' => ['service.admin:method', []],
  '#create_placeholder' => TRUE,
];

```

and it works great! The page loads, and once the service returns the render array, it gets popped into the placeholder.

However, the placeholder span is empty and does not provide the user with any useful status. My goal is to have the empty placeholder replaced with a message (i.e. 'Loading data..'). This is proving more difficult than I assumed - I feel like I must be missing something.

My first crack was manually defining the placeholder:

```
$element = [
  '#markup' => 'Loading data..',
  '#attached' => [
    'placeholders' => [
      'Loading data..' => [
        '#lazy_builder' => ['service.admin:method', []],
      ],
    ],
  ],
];

```

This generates the desired content, but blocks any elements further down of it from loading until the method returns - pausing with half the page rendered. I assume it pushes the lazy\_builder into the render process where it isn't as useful for this purpose.

I skimmed through core and couldn't glean any examples of this.

Is there an easy way to add text to the placeholder? This cannot be a novel need.

Warm Regards.

# Answer
I know this is an old question, but for anyone who stumbles upon it via a search engine (like I did), then the answer is that as of right now, you can't provide custom placeholder markup, *but* there **is** a Drupal.org issue with patches that adds this functionality, so it's possible that the feature will eventually be available in the Big Pipe module without a patch.
> 1 votes

---
Tags: 8, ajax, caching
---


# Question
Title: How to let the user fill in the "Recipient" field of the contact form?
I created a new type of contact form. It is called "Invitation".

The problem is that the recipient field does not appear and it is not editable.

I want the user to fill in the recipient's email to send invitations.

How to let the user fill in the "Recipient" field of the contact form ?

# Answer
> 1 votes
The recipient isn't a Drupal field so I don't think this can be done without custom coding.

This is probably to guard against using the form for spamming. If the recipient field were accessible to anonymous users, then anyone could use the form to send unsolicited emails.

---
Tags: 8, entities, forms
---


title: Webform is not sending body as HTML

text:
# Question
Title: Webform is not sending body as HTML
**Within the e-mail handlers** I've selected the body as '**twig template**'. **But no HTML is sent.**

I've activated **Swiftmailer** to send attachments ... is that the problem?

```
<p>Submitted values:</p>
{{ webform_token('[webform_submission:values]', webform_submission, [], options) }}
<p> URL: {{ webform_token('[current-page:url]', webform_submission, [], options) }}</p>
<p> Page name: {{ webform_token('[current-page:title]', webform_submission, [], options) }}</p>

```

**Value in body (email):**

Submitted values: \*Name\* sfd dsf \*E-mail\* test@test.com \[1\] \*Phone\* sdfsdfsdf \[2\] \*VAT\* sdfsdfdfs \*Question?\* Yes \*Newsletter\* List1, List2, List3 \*Message\* sdfsdf sdf sdf s dfsdfs URL: https://test.test.com/page/title/subtitle Page name: Pagename \[1\] test2@test.com \[2\] tel:sdfsdfsdf

# Answer
I had similar issue with emails sent from webform module (Drupal 9.0.7 & webform 6.0.0-alpha20), solved using following steps.

1. Install and enable Mail mail module https://www.drupal.org/project/mimemail
2. Ensure email format is "Full html" at /admin/config/system/mimemail
3. Go to /admin/config/system/mailsystem and choose "Mime Mail mailer" for "Formatter" and "Sender" fields under default mail settings.
4. In your webform, go to settings-\> Email/handlers -\> Advanced tab. Make sure "Send email as HTML" is checked.
> 4 votes

---
Tags: 8, webforms
---